Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Oct 2013 20:44:19 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r256752 - in head: share/man/man4 sys/dev/altera/atse sys/mips/beri
Message-ID:  <201310182044.r9IKiJYs000507@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Fri Oct 18 20:44:19 2013
New Revision: 256752
URL: http://svnweb.freebsd.org/changeset/base/256752

Log:
  MFP4: 221483, 221567, 221568, 221670, 221677, 221678, 221800, 221801,
  221804, 221805, 222004, 222006, 222055, 222820, 1135077, 1135118, 1136259
  
  Add atse(4), a driver for the Altera Triple Speed Ethernet MegaCore.
  
  The current driver support gigabit Ethernet speeds only and works with
  the MegaCore only in the internal FIFO configuration in the soon to be
  open sourced BERI CPU configuration.
  
  Submitted by:	bz
  MFC after:	3 days
  Sponsored by:	DARPA/AFRL

Added:
  head/share/man/man4/altera_atse.4   (contents, props changed)
  head/sys/dev/altera/atse/
  head/sys/dev/altera/atse/a_api.h   (contents, props changed)
  head/sys/dev/altera/atse/if_atse.c   (contents, props changed)
  head/sys/dev/altera/atse/if_atse_fdt.c   (contents, props changed)
  head/sys/dev/altera/atse/if_atse_nexus.c   (contents, props changed)
  head/sys/dev/altera/atse/if_atsereg.h   (contents, props changed)
Modified:
  head/share/man/man4/Makefile
  head/sys/mips/beri/files.beri

Modified: head/share/man/man4/Makefile
==============================================================================
--- head/share/man/man4/Makefile	Fri Oct 18 17:43:48 2013	(r256751)
+++ head/share/man/man4/Makefile	Fri Oct 18 20:44:19 2013	(r256752)
@@ -35,6 +35,7 @@ MAN=	aac.4 \
 	alc.4 \
 	ale.4 \
 	alpm.4 \
+	altera_atse.4 \
 	altera_avgen.4 \
 	altera_jtag_uart.4 \
 	altera_sdcard.4 \
@@ -574,6 +575,7 @@ MLINKS+=age.4 if_age.4
 MLINKS+=agp.4 agpgart.4
 MLINKS+=alc.4 if_alc.4
 MLINKS+=ale.4 if_ale.4
+MLINKS+=altera_atse.4 atse.4
 MLINKS+=altera_sdcard.4 altera_sdcardc.4
 MLINKS+=altq.4 ALTQ.4
 MLINKS+=ath.4 if_ath.4

Added: head/share/man/man4/altera_atse.4
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/share/man/man4/altera_atse.4	Fri Oct 18 20:44:19 2013	(r256752)
@@ -0,0 +1,100 @@
+.\"-
+.\" Copyright (c) 2013 SRI International
+.\" All rights reserved.
+.\"
+.\" This software was developed by SRI International and the University of
+.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+.\" ("CTSRD"), as part of the DARPA CRASH research programme.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 18, 2013
+.Dt ALTERA_ATSE 4
+.Os
+.Sh NAME
+.Nm atse
+.Nd driver for the Altera Triple-Speed Ethernet MegaCore
+.Sh SYNOPSIS
+.Cd "device atse"
+.Cd "options ATSE_CFI_HACK"
+.Pp
+In
+.Pa /boot/device.hints :
+.Cd hint.atse.0.at="nexus0"
+.Cd hint.atse.0.maddr=0x7f007000
+.Cd hint.atse.0.msize=0x540
+.Cd hint.atse.0.rc_irq=1
+.Cd hint.atse.0.rx_maddr=0x7f007500
+.Cd hint.atse.0.rx_msize=0x8
+.Cd hint.atse.0.rxc_maddr=0x7f007520
+.Cd hint.atse.0.rxc_msize=0x20
+.Cd hint.atse.0.tx_irq=2
+.Cd hint.atse.0.tx_maddr=0x7f007400
+.Cd hint.atse.0.tx_msize=0x8
+.Cd hint.atse.0.txc_maddr=0x7f007420
+.Cd hint.atse.0.txc_msize=0x20
+.Cd hint.e1000phy.0.at="miibus0"
+.Cd hint.e1000phy.0.phyno=0
+.Sh DESCRIPTION
+The
+.Nm
+device driver provides support for the Altera Triple-Speed Ethernet
+MegaCore.
+.Sh HARDWARE
+The current version of the
+.Nm
+driver supports the Ethernet MegaCore as described in version 11.1 of 
+Altera's documentation when the device is configured with internal FIFOs.
+.Sh SEE ALSO
+.Xr miibus 4 ,
+.Xr netintro 4 ,
+.Xr ifconfig 8
+.Rs
+.%T Triple-Speed Ethernet MegaCore Function User Guide
+.%D November 2011
+.%I Altera Corporation
+.Re
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+device driver and this manual page were
+developed by SRI International and the University of Cambridge Computer
+Laboratory under DARPA/AFRL contract
+.Pq FA8750-10-C-0237
+.Pq Do CTSRD Dc ,
+as part of the DARPA CRASH research programme.
+This device driver was written by
+.An Bjoern A. Zeeb .
+.Sh BUGS
+The
+.Nm
+driver only supports a single configuration of the MegaCore as installed
+on the Terasic Technologies Altera DE4 Development and Education Board.
+.Pp
+Only gigabit Ethernet speeds are currently supported.

Added: head/sys/dev/altera/atse/a_api.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/atse/a_api.h	Fri Oct 18 20:44:19 2013	(r256752)
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2012 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * Altera, Embedded Peripherals IP, User Guide, v. 11.0, June 2011.
+ * UG-01085-11.0.
+ */
+
+#ifndef _A_API_H
+#define _A_API_H
+
+/* Table 16-1. Memory Map. */
+#define	A_ONCHIP_FIFO_MEM_CORE_DATA		0x00
+#define	A_ONCHIP_FIFO_MEM_CORE_METADATA		0x04
+
+#define	A_ONCHIP_FIFO_MEM_CORE_SOP		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_EOP		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_EMPTY_MASK	0x000000f7
+#define	A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT	2
+	/* Reserved				(1<<7)	   */
+#define	A_ONCHIP_FIFO_MEM_CORE_CHANNEL_MASK	0x0000ff00
+#define	A_ONCHIP_FIFO_MEM_CORE_CHANNEL_SHIFT	8
+#define	A_ONCHIP_FIFO_MEM_CORE_ERROR_MASK	0x00ff0000
+#define	A_ONCHIP_FIFO_MEM_CORE_ERROR_SHIFT	16
+	/* Reserved				0xff000000 */
+
+/* Table 16-3. FIFO Status Register Memory Map. */
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL	0x00
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_I_STATUS	0x04
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT		0x08
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE	0x0c
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTFULL	0x10
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_ALMOSTEMPTY	0x14
+
+/* Table 16-5. Status Bit Field Descriptions. */
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_FULL		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_EMPTY		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTFULL	(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_ALMOSTEMPTY	(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_STATUS_UNDERFLOW		(1<<5)
+
+/* Table 16-6. Event Bit Field Descriptions. */
+/* XXX Datasheet has weird bit fields. Validate. */
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_EMPTY		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_FULL		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTEMPTY	(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_ALMOSTFULL		(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_EVENT_UNDERFLOW		(1<<5)
+
+/* Table 16-7. InterruptEnable Bit Field Descriptions. */
+/* XXX Datasheet has weird bit fields. Validate. */
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY		(1<<0)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_FULL		(1<<1)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY		(1<<2)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL		(1<<3)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW		(1<<4)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW		(1<<5)
+#define	A_ONCHIP_FIFO_MEM_CORE_INTR_ALL			\
+	    (A_ONCHIP_FIFO_MEM_CORE_INTR_EMPTY|		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_FULL|		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTEMPTY|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALMOSTFULL|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_OVERFLOW|	\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_UNDERFLOW)
+
+#endif /* _A_API_H */
+
+/* end */

Added: head/sys/dev/altera/atse/if_atse.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/altera/atse/if_atse.c	Fri Oct 18 20:44:19 2013	(r256752)
@@ -0,0 +1,1979 @@
+/*-
+ * Copyright (c) 2012,2013 Bjoern A. Zeeb
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-11-C-0249)
+ * ("MRC2"), as part of the DARPA MRC research programme.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Altera Triple-Speed Ethernet MegaCore, Function User Guide
+ * UG-01008-3.0, Software Version: 12.0, June 2012.
+ * Available at the time of writing at:
+ * http://www.altera.com/literature/ug/ug_ethernet.pdf
+ *
+ * We are using an Marvell E1111 (Alaska) PHY on the DE4.  See mii/e1000phy.c.
+ */
+/*
+ * XXX-BZ NOTES:
+ * - ifOutBroadcastPkts are only counted if both ether dst and src are all-1s;
+ *   seems an IP core bug, they count ether broadcasts as multicast.  Is this
+ *   still the case?
+ * - figure out why the TX FIFO fill status and intr did not work as expected.
+ * - test 100Mbit/s and 10Mbit/s
+ * - blacklist the one special factory programmed ethernet address (for now
+ *   hardcoded, later from loader?)
+ * - resolve all XXX, left as reminders to shake out details later
+ * - Jumbo frame support
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_device_polling.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/jail.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/types.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/altera/atse/if_atsereg.h>
+#include <dev/altera/atse/a_api.h>
+
+MODULE_DEPEND(atse, ether, 1, 1, 1);
+MODULE_DEPEND(atse, miibus, 1, 1, 1);
+
+
+#define	ATSE_WATCHDOG_TIME	5
+
+#ifdef DEVICE_POLLING
+static poll_handler_t atse_poll;
+#endif
+
+/* XXX once we'd do parallel attach, we need a global lock for this. */
+#define	ATSE_ETHERNET_OPTION_BITS_UNDEF	0
+#define	ATSE_ETHERNET_OPTION_BITS_READ	1
+static int atse_ethernet_option_bits_flag = ATSE_ETHERNET_OPTION_BITS_UNDEF;
+static uint8_t atse_ethernet_option_bits[ALTERA_ETHERNET_OPTION_BITS_LEN];
+
+/*
+ * Softc and critical resource locking.
+ */
+#define	ATSE_LOCK(_sc)		mtx_lock(&(_sc)->atse_mtx)
+#define	ATSE_UNLOCK(_sc)	mtx_unlock(&(_sc)->atse_mtx)
+#define	ATSE_LOCK_ASSERT(_sc)	mtx_assert(&(_sc)->atse_mtx, MA_OWNED)
+
+#ifdef DEBUG
+#define	DPRINTF(format, ...)	printf(format, __VA_ARGS__)
+#else
+#define	DPRINTF(format, ...)
+#endif
+
+/* a_api.c functions; factor out? */
+static inline void
+a_onchip_fifo_mem_core_write(struct resource *res, uint32_t off,
+    uint32_t val4, const char *desc, const char *f, const int l)
+{
+
+	val4 = htole32(val4);
+	DPRINTF("[%s:%d] FIFOW %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
+	bus_write_4(res, off, val4);
+}
+static inline uint32_t
+a_onchip_fifo_mem_core_read(struct resource *res, uint32_t off,
+    const char *desc, const char *f, const int l)
+{
+	uint32_t val4;
+
+	val4 = le32toh(bus_read_4(res, off));
+	DPRINTF("[%s:%d] FIFOR %s 0x%08x = 0x%08x\n", f, l, desc, off, val4);
+	return (val4);
+}
+
+/* The FIFO does an endian convertion, so we must not do it as well. */
+/* XXX-BZ in fact we should do a htobe32 so le would be fine as well? */
+#define	ATSE_TX_DATA_WRITE(sc, val4)					\
+	bus_write_4((sc)->atse_tx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA, val4)
+
+#define	ATSE_TX_META_WRITE(sc, val4)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_tx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    (val4), "TXM", __func__, __LINE__)
+#define	ATSE_TX_META_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_tx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    "TXM", __func__, __LINE__)
+
+#define	ATSE_TX_READ_FILL_LEVEL(sc)					\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL,		\
+	    "TX_FILL", __func__, __LINE__)
+#define	ATSE_RX_READ_FILL_LEVEL(sc)					\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_FILL_LEVEL,		\
+	    "RX_FILL", __func__, __LINE__)
+
+/* The FIFO does an endian convertion, so we must not do it as well. */
+/* XXX-BZ in fact we shoudl do a htobe32 so le would be fine as well? */
+#define	ATSE_RX_DATA_READ(sc)						\
+	bus_read_4((sc)->atse_rx_mem_res, A_ONCHIP_FIFO_MEM_CORE_DATA)
+#define	ATSE_RX_META_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rx_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_METADATA,				\
+	    "RXM", __func__, __LINE__)
+
+#define	ATSE_RX_EVENT_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,			\
+	    "RX_EVENT", __func__, __LINE__)
+
+#define	ATSE_TX_EVENT_READ(sc)						\
+	a_onchip_fifo_mem_core_read((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,			\
+	    "TX_EVENT", __func__, __LINE__)
+
+#define	ATSE_RX_EVENT_CLEAR(sc)						\
+	do {								\
+		uint32_t val4;						\
+									\
+		val4 = a_onchip_fifo_mem_core_read(			\
+		    (sc)->atse_rxc_mem_res,				\
+		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,		\
+		    "RX_EVENT", __func__, __LINE__);			\
+		if (val4 != 0x00)					\
+			a_onchip_fifo_mem_core_write(			\
+			    (sc)->atse_rxc_mem_res,			\
+			    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,	\
+			    val4, "RX_EVENT", __func__, __LINE__);	\
+	} while(0)
+#define	ATSE_TX_EVENT_CLEAR(sc)						\
+	do {								\
+		uint32_t val4;						\
+									\
+		val4 = a_onchip_fifo_mem_core_read(			\
+		    (sc)->atse_txc_mem_res,				\
+		    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,		\
+		    "TX_EVENT", __func__, __LINE__);			\
+		if (val4 != 0x00)					\
+			a_onchip_fifo_mem_core_write(			\
+			    (sc)->atse_txc_mem_res,			\
+			    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_EVENT,	\
+			    val4, "TX_EVENT", __func__, __LINE__);	\
+	} while(0)
+
+#define	ATSE_RX_INTR_ENABLE(sc)						\
+	a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALL,				\
+	    "RX_INTR", __func__, __LINE__)	/* XXX-BZ review later. */
+#define	ATSE_RX_INTR_DISABLE(sc)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_rxc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0,		\
+	    "RX_INTR", __func__, __LINE__)
+#define	ATSE_TX_INTR_ENABLE(sc)						\
+	a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE,		\
+	    A_ONCHIP_FIFO_MEM_CORE_INTR_ALL,				\
+	    "TX_INTR", __func__, __LINE__)	/* XXX-BZ review later. */
+#define	ATSE_TX_INTR_DISABLE(sc)					\
+	a_onchip_fifo_mem_core_write((sc)->atse_txc_mem_res,		\
+	    A_ONCHIP_FIFO_MEM_CORE_STATUS_REG_INT_ENABLE, 0,		\
+	    "TX_INTR", __func__, __LINE__)
+
+/*
+ * Register space access macros.
+ */
+static inline void
+csr_write_4(struct atse_softc *sc, uint32_t reg, uint32_t val4,
+    const char *f, const int l)
+{
+
+	val4 = htole32(val4);
+	DPRINTF("[%s:%d] CSR W %s 0x%08x (0x%08x) = 0x%08x\n", f, l,
+	    "atse_mem_res", reg, reg * 4, val4);
+	bus_write_4(sc->atse_mem_res, reg * 4, val4);
+}
+
+static inline uint32_t
+csr_read_4(struct atse_softc *sc, uint32_t reg, const char *f, const int l)
+{
+	uint32_t val4;
+
+	val4 = le32toh(bus_read_4(sc->atse_mem_res, reg * 4));
+	DPRINTF("[%s:%d] CSR R %s 0x%08x (0x%08x) = 0x%08x\n", f, l, 
+	    "atse_mem_res", reg, reg * 4, val4);
+	return (val4);
+}
+
+/*
+ * See page 5-2 that it's all dword offsets and the MS 16 bits need to be zero
+ * on write and ignored on read.
+ */
+static inline void
+pxx_write_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, uint16_t val,
+    const char *f, const int l, const char *s)
+{
+	uint32_t val4;
+
+	val4 = htole32(val & 0x0000ffff);
+	DPRINTF("[%s:%d] %s W %s 0x%08x (0x%08jx) = 0x%08x\n", f, l, s,
+	    "atse_mem_res", reg, (bmcr + reg) * 4, val4);
+	bus_write_4(sc->atse_mem_res, (bmcr + reg) * 4, val4);
+}
+
+static inline uint16_t
+pxx_read_2(struct atse_softc *sc, bus_addr_t bmcr, uint32_t reg, const char *f,
+    const int l, const char *s)
+{
+	uint32_t val4;
+	uint16_t val;
+
+	val4 = bus_read_4(sc->atse_mem_res, (bmcr + reg) * 4);
+	val = le32toh(val4) & 0x0000ffff;
+	DPRINTF("[%s:%d] %s R %s 0x%08x (0x%08jx) = 0x%04x\n", f, l, s,
+	    "atse_mem_res", reg, (bmcr + reg) * 4, val);
+	return (val);
+}
+
+#define	CSR_WRITE_4(sc, reg, val)	\
+	csr_write_4((sc), (reg), (val), __func__, __LINE__)
+#define	CSR_READ_4(sc, reg)		\
+	csr_read_4((sc), (reg), __func__, __LINE__)
+#define	PCS_WRITE_2(sc, reg, val)	\
+	pxx_write_2((sc), sc->atse_bmcr0, (reg), (val), __func__, __LINE__, \
+	    "PCS")
+#define	PCS_READ_2(sc, reg)		\
+	pxx_read_2((sc), sc->atse_bmcr0, (reg), __func__, __LINE__, "PCS")
+#define	PHY_WRITE_2(sc, reg, val)	\
+	pxx_write_2((sc), sc->atse_bmcr1, (reg), (val), __func__, __LINE__, \
+	    "PHY")
+#define	PHY_READ_2(sc, reg)		\
+	pxx_read_2((sc), sc->atse_bmcr1, (reg), __func__, __LINE__, "PHY")
+
+static void atse_tick(void *);
+static int atse_detach(device_t);
+
+devclass_t atse_devclass;
+
+static int
+atse_tx_locked(struct atse_softc *sc, int *sent)
+{
+	struct mbuf *m;
+	uint32_t val4, fill_level;
+	int c;
+
+	ATSE_LOCK_ASSERT(sc);
+
+	m = sc->atse_tx_m;
+	KASSERT(m != NULL, ("%s: m is null: sc=%p", __func__, sc));
+	KASSERT(m->m_flags & M_PKTHDR, ("%s: not a pkthdr: m=%p", __func__, m));
+
+	/*
+	 * Copy to buffer to minimize our pain as we can only store
+	 * double words which, after the first mbuf gets out of alignment
+	 * quite quickly.
+	 */
+	if (sc->atse_tx_m_offset == 0) {
+		m_copydata(m, 0, m->m_pkthdr.len, sc->atse_tx_buf);
+		sc->atse_tx_buf_len = m->m_pkthdr.len;
+	}
+
+	fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+#if 0	/* Returns 0xdeadc0de. */
+	val4 = ATSE_TX_META_READ(sc);
+#endif
+	if (sc->atse_tx_m_offset == 0) {
+		/* Write start of packet. */
+		val4 = A_ONCHIP_FIFO_MEM_CORE_SOP;
+		val4 &= ~A_ONCHIP_FIFO_MEM_CORE_EOP;
+		ATSE_TX_META_WRITE(sc, val4);
+	}
+
+	/* TX FIFO is single clock mode, so we have the full FIFO. */
+	c = 0;
+	while ((sc->atse_tx_buf_len - sc->atse_tx_m_offset) > 4 &&
+	     fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+
+		bcopy(&sc->atse_tx_buf[sc->atse_tx_m_offset], &val4,
+		    sizeof(val4));
+		ATSE_TX_DATA_WRITE(sc, val4);
+		sc->atse_tx_m_offset += sizeof(val4);
+		c += sizeof(val4);
+
+		fill_level++;
+		if (fill_level == AVALON_FIFO_TX_BASIC_OPTS_DEPTH)
+			fill_level = ATSE_TX_READ_FILL_LEVEL(sc);
+	}
+	if (sent != NULL)
+		*sent += c;
+
+	/* Set EOP *before* writing the last symbol. */
+	if (sc->atse_tx_m_offset >= (sc->atse_tx_buf_len - 4) &&
+	    fill_level < AVALON_FIFO_TX_BASIC_OPTS_DEPTH) {
+		int leftm;
+		uint32_t x;
+
+		/* Set EndOfPacket. */
+		val4 = A_ONCHIP_FIFO_MEM_CORE_EOP;
+		/* Set EMPTY. */
+		leftm = sc->atse_tx_buf_len - sc->atse_tx_m_offset;
+		val4 |= ((4 - leftm) << A_ONCHIP_FIFO_MEM_CORE_EMPTY_SHIFT);
+		x = val4;
+		ATSE_TX_META_WRITE(sc, val4);
+
+		/* Write last symbol. */
+		val4 = 0;
+		bcopy(sc->atse_tx_buf + sc->atse_tx_m_offset, &val4, leftm);
+		ATSE_TX_DATA_WRITE(sc, val4);
+
+		if (sent != NULL)
+			*sent += leftm;
+
+		/* OK, the packet is gone. */
+		sc->atse_tx_m = NULL;
+		sc->atse_tx_m_offset = 0;
+
+		/* If anyone is interested give them a copy. */
+		BPF_MTAP(sc->atse_ifp, m);
+
+		m_freem(m);
+		return (0);
+	}
+
+	return (EBUSY);
+}
+
+static void
+atse_start_locked(struct ifnet *ifp)
+{
+	struct atse_softc *sc;
+	int error, sent;
+
+	sc = ifp->if_softc;
+	ATSE_LOCK_ASSERT(sc);
+
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING || (sc->atse_flags & ATSE_FLAGS_LINK) == 0)
+		return;
+
+#if 1
+	/* 
+	 * Disable the watchdog while sending, we are batching packets.
+	 * Though we should never reach 5 seconds, and are holding the lock,
+	 * but who knows.
+	 */
+	sc->atse_watchdog_timer = 0;
+#endif
+
+	if (sc->atse_tx_m != NULL) {
+		error = atse_tx_locked(sc, &sent);
+		if (error != 0)
+			goto done;
+	}
+	/* We have more space to send so continue ... */
+	for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
+
+		IFQ_DRV_DEQUEUE(&ifp->if_snd, sc->atse_tx_m);
+		sc->atse_tx_m_offset = 0;
+		if (sc->atse_tx_m == NULL)
+			break;
+		error = atse_tx_locked(sc, &sent);
+		if (error != 0)
+			goto done;
+	}
+
+done:
+	/* If the IP core walks into Nekromanteion try to bail out. */
+	if (sent > 0)
+		sc->atse_watchdog_timer = ATSE_WATCHDOG_TIME;
+}
+
+static void
+atse_start(struct ifnet *ifp)
+{
+	struct atse_softc *sc;
+
+	sc = ifp->if_softc;
+	ATSE_LOCK(sc);
+	atse_start_locked(ifp);
+	ATSE_UNLOCK(sc);
+}
+
+static int
+atse_stop_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	uint32_t mask, val4;
+	int i;
+
+	ATSE_LOCK_ASSERT(sc);
+
+	sc->atse_watchdog_timer = 0;
+	callout_stop(&sc->atse_tick);
+
+	ifp = sc->atse_ifp;
+	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+	ATSE_RX_INTR_DISABLE(sc);
+	ATSE_TX_INTR_DISABLE(sc);
+	ATSE_RX_EVENT_CLEAR(sc);
+	ATSE_TX_EVENT_CLEAR(sc);
+
+	/* Disable MAC transmit and receive datapath. */
+	mask = BASE_CFG_COMMAND_CONFIG_TX_ENA|BASE_CFG_COMMAND_CONFIG_RX_ENA;
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	val4 &= ~mask;
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+	/* Wait for bits to be cleared; i=100 is excessive. */
+	for (i = 0; i < 100; i++) {
+		val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+		if ((val4 & mask) == 0)
+			break;
+		DELAY(10);
+	}
+	if ((val4 & mask) != 0)
+		device_printf(sc->atse_dev, "Disabling MAC TX/RX timed out.\n");
+		/* Punt. */
+
+	sc->atse_flags &= ~ATSE_FLAGS_LINK;
+
+	/* XXX-BZ free the RX/TX rings. */
+
+	return (0);
+}
+
+static uint8_t
+atse_mchash(struct atse_softc *sc __unused, const uint8_t *addr)
+{
+	int i, j;
+	uint8_t x, y;
+
+	x = 0;
+	for (i = 0; i < ETHER_ADDR_LEN; i++) {
+		y = addr[i] & 0x01;
+		for (j = 1; j < 8; j++)
+			y ^= (addr[i] >> j) & 0x01;
+		x |= (y << i);
+	}
+	return (x);
+}
+
+static int
+atse_rxfilter_locked(struct atse_softc *sc)
+{
+	struct ifnet *ifp;
+	struct ifmultiaddr *ifma;
+	uint32_t val4;
+	int i;
+
+	/* XXX-BZ can we find out if we have the MHASH synthesized? */
+	val4 = CSR_READ_4(sc, BASE_CFG_COMMAND_CONFIG);
+	/* For simplicity always hash full 48 bits of addresses. */
+	if ((val4 & BASE_CFG_COMMAND_CONFIG_MHASH_SEL) != 0)
+		val4 &= ~BASE_CFG_COMMAND_CONFIG_MHASH_SEL;
+
+	ifp = sc->atse_ifp;
+	if (ifp->if_flags & IFF_PROMISC)
+		val4 |= BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+	else
+		val4 &= ~BASE_CFG_COMMAND_CONFIG_PROMIS_EN;
+
+	CSR_WRITE_4(sc, BASE_CFG_COMMAND_CONFIG, val4);
+
+	if (ifp->if_flags & IFF_ALLMULTI) {
+		/* Accept all multicast addresses. */
+		for (i = 0; i <= MHASH_LEN; i++)
+			CSR_WRITE_4(sc, MHASH_START + i, 0x1);
+	} else {
+		/* 
+		 * Can hold MHASH_LEN entries.
+		 * XXX-BZ bitstring.h would be more general.
+		 */
+		uint64_t h;
+
+		h = 0;
+		/*
+		 * Re-build and re-program hash table.  First build the
+		 * bit-field "yes" or "no" for each slot per address, then
+		 * do all the programming afterwards.
+		 */
+		if_maddr_rlock(ifp);
+		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+			if (ifma->ifma_addr->sa_family != AF_LINK)
+				continue;
+
+			h |= (1 << atse_mchash(sc,
+			    LLADDR((struct sockaddr_dl *)ifma->ifma_addr)));
+		}
+		if_maddr_runlock(ifp);
+		for (i = 0; i <= MHASH_LEN; i++)
+			CSR_WRITE_4(sc, MHASH_START + i,
+			    (h & (1 << i)) ? 0x01 : 0x00);
+	}
+
+	return (0);
+}
+
+static int
+atse_ethernet_option_bits_read_fdt(device_t dev)
+{
+	struct resource *res;
+	device_t fdev;
+	int i, rid;
+
+	if (atse_ethernet_option_bits_flag & ATSE_ETHERNET_OPTION_BITS_READ)
+		return (0);
+
+	fdev = device_find_child(device_get_parent(dev), "cfi", 0);
+	if (fdev == NULL)
+		return (ENOENT);
+
+	rid = 0;
+	res = bus_alloc_resource_any(fdev, SYS_RES_MEMORY, &rid,
+	    RF_ACTIVE | RF_SHAREABLE);
+	if (res == NULL)
+		return (ENXIO);
+
+	for (i = 0; i < ALTERA_ETHERNET_OPTION_BITS_LEN; i++)
+		atse_ethernet_option_bits[i] = bus_read_1(res,
+		    ALTERA_ETHERNET_OPTION_BITS_OFF + i);
+
+	bus_release_resource(fdev, SYS_RES_MEMORY, rid, res);
+	atse_ethernet_option_bits_flag |= ATSE_ETHERNET_OPTION_BITS_READ;
+
+	return (0);
+}
+
+static int
+atse_ethernet_option_bits_read(device_t dev)
+{
+	int error;
+
+	error = atse_ethernet_option_bits_read_fdt(dev);
+	if (error == 0)
+		return (0);
+	
+	device_printf(dev, "Cannot read Ethernet addresses from flash.\n");
+	return (error);
+}
+
+static int
+atse_get_eth_address(struct atse_softc *sc)
+{
+	unsigned long hostid;
+	uint32_t val4;
+	int unit;
+
+	/*
+	 * Make sure to only ever do this once.  Otherwise a reset would
+	 * possibly change our ethernet address, which is not good at all.
+	 */
+	if (sc->atse_eth_addr[0] != 0x00 || sc->atse_eth_addr[1] != 0x00 ||
+	    sc->atse_eth_addr[2] != 0x00)
+		return (0);
+
+	if ((atse_ethernet_option_bits_flag &
+	    ATSE_ETHERNET_OPTION_BITS_READ) == 0)
+		goto get_random;
+
+	val4 = atse_ethernet_option_bits[0] << 24;
+	val4 |= atse_ethernet_option_bits[1] << 16;
+	val4 |= atse_ethernet_option_bits[2] << 8;
+	val4 |= atse_ethernet_option_bits[3];
+	/* They chose "safe". */
+	if (val4 != le32toh(0x00005afe)) {
+		device_printf(sc->atse_dev, "Magic '5afe' is not safe: 0x%08x. "
+		    "Falling back to random numbers for hardware address.\n",
+		     val4);
+		goto get_random;
+	}
+
+	sc->atse_eth_addr[0] = atse_ethernet_option_bits[4];
+	sc->atse_eth_addr[1] = atse_ethernet_option_bits[5];
+	sc->atse_eth_addr[2] = atse_ethernet_option_bits[6];
+	sc->atse_eth_addr[3] = atse_ethernet_option_bits[7];
+	sc->atse_eth_addr[4] = atse_ethernet_option_bits[8];
+	sc->atse_eth_addr[5] = atse_ethernet_option_bits[9];
+
+	/* Handle factory default ethernet addresss: 00:07:ed:ff:ed:15 */
+	if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x07 &&
+	    sc->atse_eth_addr[2] == 0xed && sc->atse_eth_addr[3] == 0xff &&
+	    sc->atse_eth_addr[4] == 0xed && sc->atse_eth_addr[5] == 0x15) {
+
+		device_printf(sc->atse_dev, "Factory programmed Ethernet "
+		    "hardware address blacklisted.  Falling back to random "
+		    "address to avoid collisions.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	if (sc->atse_eth_addr[0] == 0x00 && sc->atse_eth_addr[1] == 0x00 &&
+	    sc->atse_eth_addr[2] == 0x00 && sc->atse_eth_addr[3] == 0x00 &&
+	    sc->atse_eth_addr[4] == 0x00 && sc->atse_eth_addr[5] == 0x00) {
+		device_printf(sc->atse_dev, "All zero's Ethernet hardware "
+		    "address blacklisted.  Falling back to random address.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	if (ETHER_IS_MULTICAST(sc->atse_eth_addr)) {
+		device_printf(sc->atse_dev, "Multicast Ethernet hardware "
+		    "address blacklisted.  Falling back to random address.\n");
+		device_printf(sc->atse_dev, "Please re-program your flash.\n");
+		goto get_random;
+	}
+
+	/*
+	 * If we find an Altera prefixed address with a 0x0 ending
+	 * adjust by device unit.  If not and this is not the first
+	 * Ethernet, go to random.
+	 */
+	unit = device_get_unit(sc->atse_dev);
+	if (unit == 0x00)
+		return (0);
+
+	if (unit > 0x0f) {
+		device_printf(sc->atse_dev, "We do not support Ethernet "
+		    "addresses for more than 16 MACs. Falling back to "
+		    "random hadware address.\n");
+		goto get_random;
+	}
+	if ((sc->atse_eth_addr[0] & ~0x2) != 0 ||
+	    sc->atse_eth_addr[1] != 0x07 || sc->atse_eth_addr[2] != 0xed ||
+	    (sc->atse_eth_addr[5] & 0x0f) != 0x0) {
+		device_printf(sc->atse_dev, "Ethernet address not meeting our "
+		    "multi-MAC standards. Falling back to random hadware "
+		    "address.\n");
+		goto get_random;
+	}
+	sc->atse_eth_addr[5] |= (unit & 0x0f);
+
+	return (0);
+
+get_random:
+	/*
+	 * Fall back to random code we also use on bridge(4).
+	 */
+	getcredhostid(curthread->td_ucred, &hostid);
+	if (hostid == 0) {
+		arc4rand(sc->atse_eth_addr, ETHER_ADDR_LEN, 1);
+		sc->atse_eth_addr[0] &= ~1;/* clear multicast bit */
+		sc->atse_eth_addr[0] |= 2; /* set the LAA bit */
+	} else {
+		sc->atse_eth_addr[0] = 0x2;
+		sc->atse_eth_addr[1] = (hostid >> 24)	& 0xff;
+		sc->atse_eth_addr[2] = (hostid >> 16)	& 0xff;
+		sc->atse_eth_addr[3] = (hostid >> 8 )	& 0xff;
+		sc->atse_eth_addr[4] = hostid		& 0xff;
+		sc->atse_eth_addr[5] = sc->atse_unit	& 0xff;
+	}
+
+	return (0);
+}
+
+static int
+atse_set_eth_address(struct atse_softc *sc, int n)
+{
+	uint32_t v0, v1;
+
+	v0 = (sc->atse_eth_addr[3] << 24) | (sc->atse_eth_addr[2] << 16) |
+	    (sc->atse_eth_addr[1] << 8) | sc->atse_eth_addr[0];
+	v1 = (sc->atse_eth_addr[5] << 8) | sc->atse_eth_addr[4];
+
+	if (n & ATSE_ETH_ADDR_DEF) {
+		CSR_WRITE_4(sc, BASE_CFG_MAC_0, v0);
+		CSR_WRITE_4(sc, BASE_CFG_MAC_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP1) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_0_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP2) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_1_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP3) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_2_1, v1);
+	}
+	if (n & ATSE_ETH_ADDR_SUPP4) {
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_0, v0);
+		CSR_WRITE_4(sc, SUPPL_ADDR_SMAC_3_1, v1);
+	}
+
+	return (0);
+}
+
+static int
+atse_reset(struct atse_softc *sc)
+{
+	int i;
+	uint32_t val4, mask;
+	uint16_t val;
+
+	/* 1. External PHY Initialization using MDIO. */
+	/*
+	 * We select the right MDIO space in atse_attach() and let MII do
+	 * anything else.
+	 */
+
+	/* 2. PCS Configuration Register Initialization. */
+	/* a. Set auto negotiation link timer to 1.6ms for SGMII. */
+	PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_0, 0x0D40);
+	PCS_WRITE_2(sc, PCS_EXT_LINK_TIMER_1, 0x0003);
+
+	/* b. Configure SGMII. */
+	val = PCS_EXT_IF_MODE_SGMII_ENA|PCS_EXT_IF_MODE_USE_SGMII_AN;
+	PCS_WRITE_2(sc, PCS_EXT_IF_MODE, val);
+
+	/* c. Enable auto negotiation. */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310182044.r9IKiJYs000507>