- Replace lnc(4) driver with NetBSD's le(4), which gives us better performance,
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 7 Jul 2006 14:16:29 +0000 (14:16 +0000)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 7 Jul 2006 14:16:29 +0000 (14:16 +0000)
  especially for VMWare users.
- Sync lnc(4) manpage.

Submitted-by: Bill Marquette <bill.marquette@gmail.com>
Manpage-reviewed-and-adjusted-by: swildner
19 files changed:
gnu/usr.bin/groff/tmac/mdoc.local
share/man/man4/man4.i386/lnc.4
sys/conf/files
sys/dev/netif/lnc/Makefile
sys/dev/netif/lnc/am7990.c [new file with mode: 0644]
sys/dev/netif/lnc/am79900.c [new file with mode: 0644]
sys/dev/netif/lnc/am79900reg.h [new file with mode: 0644]
sys/dev/netif/lnc/am79900var.h [new file with mode: 0644]
sys/dev/netif/lnc/am7990reg.h [new file with mode: 0644]
sys/dev/netif/lnc/am7990var.h [new file with mode: 0644]
sys/dev/netif/lnc/if_lnc.c [deleted file]
sys/dev/netif/lnc/if_lnc.h [deleted file]
sys/dev/netif/lnc/if_lnc_isa.c
sys/dev/netif/lnc/if_lnc_pci.c
sys/dev/netif/lnc/if_lncreg.h [deleted file]
sys/dev/netif/lnc/if_lncvar.h [deleted file]
sys/dev/netif/lnc/lance.c [new file with mode: 0644]
sys/dev/netif/lnc/lancereg.h [new file with mode: 0644]
sys/dev/netif/lnc/lancevar.h [new file with mode: 0644]

index 298b0a7..6674b43 100644 (file)
@@ -23,7 +23,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $FreeBSD: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.2.2.19 2003/03/25 10:20:12 murray Exp $
-.\" $DragonFly: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.11 2006/03/08 09:53:30 swildner Exp $
+.\" $DragonFly: src/gnu/usr.bin/groff/tmac/mdoc.local,v 1.12 2006/07/07 14:16:29 sephe Exp $
 .\"
 .\"     %beginstrip%
 .
@@ -86,6 +86,7 @@
 .ds doc-operating-system-FreeBSD-5.4  5.4
 .ds doc-operating-system-FreeBSD-5.5  5.5
 .ds doc-operating-system-FreeBSD-6.0  6.0
+.ds doc-operating-system-FreeBSD-6.1  6.1
 .ds doc-operating-system-FreeBSD-7.0  7.0
 .
 .\" NetBSD releases not found in doc-common.
index 762ba1a..01b3137 100644 (file)
@@ -1,7 +1,12 @@
+.\"    $NetBSD: le.4,v 1.22 2004/10/04 19:12:52 rumble Exp $
 .\"
-.\" Copyright (c) 1997 David E. O'Brien
+.\"-
+.\" Copyright (c) 1992, 1993
+.\"    The Regents of the University of California.  All rights reserved.
 .\"
-.\" All rights reserved.
+.\" This software was developed by the Computer Systems Engineering group
+.\" at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+.\" contributed to Berkeley.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" 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.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
 .\"
-.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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.
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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: src/share/man/man4/man4.i386/lnc.4,v 1.12.2.6 2001/08/17 13:08:45 ru Exp $
-.\" $DragonFly: src/share/man/man4/man4.i386/lnc.4,v 1.3 2006/02/17 19:37:10 swildner Exp $
+.\"    from: Header: le.4,v 1.2 92/10/13 05:31:33 leres Exp
+.\"    from: @(#)le.4  8.1 (Berkeley) 6/9/93
+.\" $FreeBSD: /repoman/r/ncvs/src/share/man/man4/le.4,v 1.2 2006/02/02 14:57:00 marius Exp $
+.\" $DragonFly: src/share/man/man4/man4.i386/lnc.4,v 1.4 2006/07/07 14:16:29 sephe Exp $
 .\"
-.Dd January 19, 1997
+.Dd July 07, 2006
 .Dt LNC 4 i386
 .Os
 .Sh NAME
 .Nm lnc
-.Nd AMD Lance/PCnet Ethernet device driver
+.Nd AMD Am7900 LANCE and Am79C9xx PCnet Ethernet interface driver
 .Sh SYNOPSIS
-.Cd "device lnc0 at isa? port 0x280 irq 10 drq 0"
+.Cd "device lnc"
 .Sh DESCRIPTION
 The
 .Nm
 driver provides support for the AMD family of Lance/PCnet Ethernet NICs
 including the Am7990 and Am79C960.
-The Ethernet cards supported by the
+.Pp
+The
+.Nm
+driver also supports PCnet adapters based on the
+.Tn AMD 79C9xx
+family of chips, which are single-chip implementations of a
+.Tn LANCE
+chip and a DMA engine.
+This includes a superset of the
+.Tn PCI
+bus Ethernet chip sets supported by the
+.Xr pcn 4
+driver.
+The
 .Nm
-interface are:
+driver treats all of these
+.Tn PCI
+bus Ethernet chip sets as an
+.Tn AMD Am79C970 PCnet-PCI
+and does not support the additional features like the MII bus and burst mode of
+.Tn AMD Am79C971 PCnet-FAST
+and greater chip sets.
+Thus the
+.Xr pcn 4
+driver should be preferred for the latter.
 .Pp
-.Bl -item -offset indent -compact
+The
+.Nm
+driver supports reception and transmission of extended frames for
+.Xr vlan 4 .
+Selective reception of multicast Ethernet frames is provided by a 64-bit mask;
+multicast destination addresses are hashed to a bit entry using the Ethernet
+CRC function.
+.Sh HARDWARE
+.\" .Ss ISA
+.\" The
+.\" .Tn ISA
+.\" bus Ethernet cards supported by the
+.\" .Nm
+.\" driver are:
+.\" .Pp
+.\" .Bl -bullet -compact
+.\" .It
+.\" .Tn BICC Isolan
+.\" .It
+.\" .Tn Novell NE2100
+.\" .It
+.\" .Tn Digital DEPCA
+.\" .El
+.\" .Ss EISA
+.\" The
+.\" .Tn EISA
+.\" bus Ethernet cards supported by the
+.\" .Nm
+.\" driver are:
+.\" .Pp
+.\" .Bl -bullet -compact
+.\" .It
+.\" .Tn DEC DE422
+.\" .El
+.\" .Ss MCA
+.\" The
+.\" .Tn MCA
+.\" bus Ethernet cards supported by the
+.\" .Nm
+.\" driver are:
+.\" .Pp
+.\" .Bl -bullet -compact
+.\" .It
+.\" .Tn SKNET Personal MC2
+.\" .It
+.\" .Tn SKNET MC2+
+.\" .El
+.Ss PCI
+The
+.Tn PCI
+bus Ethernet chip sets supported by the
+.Nm
+driver are:
+.Pp
+.Bl -bullet -compact
 .It
-Novell NE2100
+.Tn AMD Am53C974/Am79C970/Am79C974 PCnet-PCI
 .It
-Novell NE32-VL
+.Tn AMD Am79C970A PCnet-PCI II
 .It
-Isolan BICC
+.Tn AMD Am79C971 PCnet-FAST
 .It
-Digital DEPCA
+.Tn AMD Am79C972 PCnet-FAST+
 .It
-Hewlett Packard Vectra 486/66XM
+.Tn AMD Am79C973/Am79C975 PCnet-FAST III
 .It
-Hewlett Packard Vectra XU
+.Tn AMD Am79C976 PCnet-PRO
 .It
-Diamond HomeFree
+.Tn AMD Am79C978 PCnet-Home
+.El
+.Pp
+The
+.Nm
+driver supports the following media types with these chip sets:
+.Pp
+.Bl -tag -width xxxxxxxxxxxxxxxxxxxx
+.It autoselect
+Enable autoselection of the media type.
+.It 10baseT/UTP
+Select UTP media.
+.It 10base5/AUI
+Select AUI/BNC media.
+.El
+.Pp
+The following media option is supported with these media types:
+.Pp
+.Bl -tag -width xxxxxxxxxxxxxxxxxxxx
+.It full-duplex
+Select full duplex operation.
 .El
+.Pp
+Note that unlike the
+.Xr pcn 4
+driver, the
+.Nm
+driver does not support selecting 100Mbps (Fast Ethernet) media types.
+.Pp
+For further information on configuring media types and options, see
+.Xr ifconfig 8 .
 .Sh DIAGNOSTICS
 .Bl -diag
-.It "lnc%d: Framing error"
-A framing error occurred.  This means a CRC error also occurred.
-This caused the driver to drop the packet that contained the framing error.
-.It "lnc%d: Receive CRC error
-The received Ethernet frame failed the CRC checksum.
-This caused the driver to drop the packet that failed the checksum.
-.It "lnc%d: Packet dropped, no mbufs"
-The driver ran out of mbuf's.  This may suggest a resource problem.
-.It "lnc%d: Couldn't allocate memory for NIC"
-This is a fatal error.  The driver will not attach to the card under this
-circumstance.
-.It "lnc%d: Memory allocated above 16Mb limit"
-ISA and ESIA cards require bounce buffers for DMA transfers above 16mb.
-The Am7990 and Am79C960 only have 24 address lines and so can only access
-the lower 16Mb of physical memory.  The
+.It "lnc%d: overflow"
+More packets came in from the Ethernet than there was space in the
+.Tn LANCE
+receive buffers.
+Packets were missed.
+.It "lnc%d: receive buffer error"
+The
+.Tn LANCE
+ran out of buffer space, packet dropped.
+.It "lnc%d: lost carrier"
+The Ethernet carrier disappeared during an attempt to transmit.
+The
+.Tn LANCE
+will finish transmitting the current packet,
+but will not automatically retry transmission if there is a collision.
+.It "lnc%d: excessive collisions, tdr %d"
+The Ethernet was extremely busy or jammed,
+outbound packets were dropped after 16 attempts to retransmit.
+.Pp
+TDR
+is the abbreviation of
+.Qq Time Domain Reflectometry .
+The optionally reported TDR value is an internal counter of the interval
+between the start of a transmission and the occurrence of a collision.
+This value can be used to determine the distance from the Ethernet tap to
+the point on the Ethernet cable that is shorted or open (unterminated).
+.It "lnc%d: dropping chained buffer"
+A packet did not fit into a single receive buffer and was dropped.
+Since the
 .Nm
-driver assumes the memory it allocates is within the lower 16Mb range.
-This is not a very valid assumption but there's nothing that can be done
-about it yet.
-For shared memory NICs this isn't relevant.
-.It "lnc%d: Device timeout -- Resetting"
-The device has stopped responding to the network, or there is a problem with
-the network connection (cable).   Make sure the network connection in use
-is the same one the card is configured for.
-.It "lnc%d: Transmit late collision  -- Net error?"
-.It "lnc%d: Loss of carrier during transmit -- Net error?"
-.It "lnc%d: Transmit of packet failed after 16 attempts -- TDR = %d"
-.It "lnc%d: Heartbeat error -- SQE test failed"
-.It "lnc%d: Babble error - more than 1519 bytes transmitted"
-.It "lnc%d: Missed packet -- no receive buffer"
-.It "lnc%d: Memory error  -- Resetting"
-.It "lnc%d: Couldn't get mbuf for transmit packet -- Resetting"
-.It "lnc%d: Receive buffer error"
-.It "lnc%d: Receive overflow error"
-.It "lnc%d: Receive interrupt with buffer still owned by controller -- Resetting"
-.It "lnc%d: Receive interrupt but not start of packet -- Resetting"
-.It "lnc%d: Start of packet found before end of previous in receive ring -- Resetting"
-.It "lnc%d: End of received packet not found -- Resetting"
-.It "lnc%d: Transmit interrupt with buffer still owned by controller -- Resetting"
-.It "lnc%d: Transmit interrupt but not start of packet -- Resetting"
-.It "lnc%d: Start of packet found before end of previous in transmit ring -- Resetting"
-.It "lnc%d: End of transmitted packet not found -- Resetting"
-.It "lnc%d: Transmit buffer error -- Resetting"
-.It "lnc%d: Transmit underflow error -- Resetting"
+driver allocates buffers large enough to receive maximum sized Ethernet
+packets, this means some other station on the LAN transmitted a packet
+larger than allowed by the Ethernet standard.
+.It "lnc%d: transmit buffer error"
+The
+.Tn LANCE
+ran out of buffer space before finishing the transmission of a packet.
+If this error occurs, the driver software has a bug.
+.It "lnc%d: underflow"
+The
+.Tn LANCE
+ran out of buffer space before finishing the transmission of a packet.
+If this error occurs, the driver software has a bug.
+.It "lnc%d: controller failed to initialize"
+Driver failed to start the
+.Tn LANCE .
+This is potentially a hardware failure.
+.It "lnc%d: memory error"
+RAM failed to respond within the timeout when the
+.Tn LANCE
+wanted to read or write it.
+This is potentially a hardware failure.
+.It "lnc%d: receiver disabled"
+The receiver of the
+.Tn LANCE
+was turned off due to an error.
+.It "lnc%d: transmitter disabled"
+The transmitter of the
+.Tn LANCE
+was turned off due to an error.
 .El
 .Sh SEE ALSO
 .Xr arp 4 ,
+.Xr intro 4 ,
 .Xr netintro 4 ,
-.Xr ng_ether 4 ,
+.Xr pcn 4 ,
+.Xr vlan 4 ,
 .Xr ifconfig 8
 .Sh HISTORY
 The
 .Nm
-device driver first appeared in
-.Fx 2.2 .
+driver first appeared in
+.Fx 2.2 ,
+it was replaced in
+.Dx 1.5
+with the
+.Xr le 4
+driver from
+.Fx 6.1
+which was in turn ported from
+.Nx .
+The
+.Nx
+driver was derived from the
+.Xr le 4 driver in
+.Bx 4.4 .
 .Sh AUTHORS
 .An -nosplit
 The
 .Nm
-device driver was written by
-.An Paul Richards .
-Support for the AMD PCHome phone-line based network added by
-.An Robert Watson .
-This manual page was written by
-.An David E. O'Brien .
-.Sh BUGS
-This driver has the potential of being the most verbose of any of the
-Ethernet device drivers.
+driver was ported to
+.Fx
+by
+.An "Marius Strobl" Aq marius@FreeBSD.org
+and later ported to
+.Dx
+by
+.An "Bill Marquette" Aq bill.marquette@gmail.com .
+.\" .Sh BUGS
+.\" The Am7990 Revision C chips have a bug which causes garbage to be inserted
+.\" in front of the received packet occasionally.
+.\" The work-around is to ignore packets with an invalid destination address
+.\" (garbage will usually not match), by double-checking the destination
+.\" address of every packet in the driver.
+.\" This work-around can be enabled with the
+.\" .Dv LANCE_REVC_BUG
+.\" kernel option.
+.\" .Pp
+.\" When
+.\" .Dv LANCE_REVC_BUG
+.\" is enabled, the
+.\" .Nm
+.\" driver executes one or two calls to an inline Ethernet address comparison
+.\" function for every received packet.
+.\" There is one comparison for each unicast packet, and two comparisons for
+.\" each broadcast packet.
+.\" .Pp
+.\" In summary, the cost of the LANCE_REVC_BUG option is:
+.\" .Bl -enum -compact
+.\" .It
+.\" loss of multicast support, and
+.\" .It
+.\" eight extra
+.\" .Tn CPU
+.\" instructions per received packet, sometimes sixteen, depending on both the
+.\" processor, and the type of packet.
+.\" .El
+.\" .Pp
+.\" Alas, the Am7990 chip is so old that
+.\" .Tn AMD
+.\" has
+.\" .Qq de-archived
+.\" the production information about it; pending a search elsewhere, we do not
+.\" know how to identify the revision C chip from the date codes.
index 00f4571..6c12253 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $
-# $DragonFly: src/sys/conf/files,v 1.130 2006/06/25 11:02:37 corecode Exp $
+# $DragonFly: src/sys/conf/files,v 1.131 2006/07/07 14:16:29 sephe Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -1036,9 +1036,6 @@ dev/serial/cy/cy_pci.c            optional cy pci
 dev/netif/dc/if_dc.c           optional dc
 dev/netif/de/if_de.c           optional de
 dev/netif/en_pci/if_en_pci.c   optional en pci
-dev/netif/lnc/if_lnc.c         optional lnc
-dev/netif/lnc/if_lnc_isa.c     optional lnc isa
-dev/netif/lnc/if_lnc_pci.c     optional lnc pci
 dev/netif/pcn/if_pcn.c         optional pcn
 dev/netif/mn/if_mn.c           optional mn
 dev/netif/re/if_re.c           optional re
@@ -1161,6 +1158,11 @@ dev/netif/aue/if_aue.c           optional aue
 dev/netif/axe/if_axe.c         optional axe
 dev/netif/cue/if_cue.c         optional cue
 dev/netif/kue/if_kue.c         optional kue
+dev/netif/lnc/am7990.c         optional lnc
+dev/netif/lnc/am79900.c                optional lnc
+dev/netif/lnc/if_lnc_isa.c     optional lnc isa
+dev/netif/lnc/if_lnc_pci.c     optional lnc pci
+dev/netif/lnc/lance.c          optional lnc
 dev/netif/rue/if_rue.c         optional rue
 bus/isa/isa_if.m               optional isa
 bus/isa/isa_common.c           optional isa
index 07bff79..fef90c9 100644 (file)
@@ -1,7 +1,7 @@
-# $DragonFly: src/sys/dev/netif/lnc/Makefile,v 1.2 2005/07/28 00:06:10 joerg Exp $
+# $DragonFly: src/sys/dev/netif/lnc/Makefile,v 1.3 2006/07/07 14:16:29 sephe Exp $
  
 KMOD    = if_lnc
-SRCS    = if_lnc.c if_lnc_isa.c if_lnc_pci.c
+SRCS    = lance.c if_lnc_isa.c if_lnc_pci.c am7990.c am79900.c 
 SRCS    += device_if.h bus_if.h pci_if.h isa_if.h opt_inet.h
   
 .include <bsd.kmod.mk>
diff --git a/sys/dev/netif/lnc/am7990.c b/sys/dev/netif/lnc/am7990.c
new file mode 100644 (file)
index 0000000..ca37b7f
--- /dev/null
@@ -0,0 +1,619 @@
+/*     $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $     */
+/*     $FreeBSD: src/sys/dev/le/am7990.c,v 1.3 2006/05/16 21:04:01 marius Exp $        */
+/*     $DragonFly: src/sys/dev/netif/lnc/am7990.c,v 1.1 2006/07/07 14:16:29 sephe Exp $        */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_var.h>
+#include <net/ifq_var.h>
+
+#include <machine/bus.h>
+
+#include <dev/netif/lnc/lancereg.h>
+#include <dev/netif/lnc/lancevar.h>
+#include <dev/netif/lnc/am7990reg.h>
+#include <dev/netif/lnc/am7990var.h>
+
+static void    am7990_meminit(struct lance_softc *);
+static void    am7990_rint(struct lance_softc *);
+static void    am7990_tint(struct lance_softc *);
+static void    am7990_start_locked(struct lance_softc *sc);
+
+#ifdef LEDEBUG
+static void    am7990_recv_print(struct lance_softc *, int);
+static void    am7990_xmit_print(struct lance_softc *, int);
+#endif
+
+int
+am7990_config(struct am7990_softc *sc, const char* name, int unit)
+{
+       int error, mem;
+
+       sc->lsc.sc_meminit = am7990_meminit;
+       sc->lsc.sc_start_locked = am7990_start_locked;
+
+       error = lance_config(&sc->lsc, name, unit);
+       if (error != 0)
+               return (error);
+
+       mem = 0;
+       sc->lsc.sc_initaddr = mem;
+       mem += sizeof(struct leinit);
+       sc->lsc.sc_rmdaddr = mem;
+       mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
+       sc->lsc.sc_tmdaddr = mem;
+       mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
+       sc->lsc.sc_rbufaddr = mem;
+       mem += LEBLEN * sc->lsc.sc_nrbuf;
+       sc->lsc.sc_tbufaddr = mem;
+       mem += LEBLEN * sc->lsc.sc_ntbuf;
+
+       if (mem > sc->lsc.sc_memsize)
+               panic("%s: memsize", __func__);
+
+       lance_attach(&sc->lsc);
+
+       return (0);
+}
+
+void
+am7990_detach(struct am7990_softc *sc)
+{
+
+       ether_ifdetach(sc->lsc.ifp);
+}
+
+/*
+ * Set up the initialization block and the descriptor rings.
+ */
+static void
+am7990_meminit(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct leinit init;
+       struct lermd rmd;
+       struct letmd tmd;
+       u_long a;
+       int bix;
+
+       if (ifp->if_flags & IFF_PROMISC)
+               init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
+       else
+               init.init_mode = LE_MODE_NORMAL;
+
+       init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
+       init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
+       init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
+       lance_setladrf(sc, init.init_ladrf);
+
+       sc->sc_last_rd = 0;
+       sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
+
+       a = sc->sc_addr + LE_RMDADDR(sc, 0);
+       init.init_rdra = a;
+       init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
+
+       a = sc->sc_addr + LE_TMDADDR(sc, 0);
+       init.init_tdra = a;
+       init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
+
+       (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
+
+       /*
+        * Set up receive ring descriptors.
+        */
+       for (bix = 0; bix < sc->sc_nrbuf; bix++) {
+               a = sc->sc_addr + LE_RBUFADDR(sc, bix);
+               rmd.rmd0 = a;
+               rmd.rmd1_hadr = a >> 16;
+               rmd.rmd1_bits = LE_R1_OWN;
+               rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
+               rmd.rmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
+                   sizeof(rmd));
+       }
+
+       /*
+        * Set up transmit ring descriptors.
+        */
+       for (bix = 0; bix < sc->sc_ntbuf; bix++) {
+               a = sc->sc_addr + LE_TBUFADDR(sc, bix);
+               tmd.tmd0 = a;
+               tmd.tmd1_hadr = a >> 16;
+               tmd.tmd1_bits = 0;
+               tmd.tmd2 = LE_XMD2_ONES;
+               tmd.tmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
+                   sizeof(tmd));
+       }
+}
+
+static void
+am7990_rint(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct mbuf *m;
+       struct lermd rmd;
+       int bix, rp;
+#if defined(LANCE_REVC_BUG)
+       struct ether_header *eh;
+       /* Make sure this is short-aligned, for ether_cmp(). */
+       static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
+#endif
+
+       bix = sc->sc_last_rd;
+
+       /* Process all buffers with valid data. */
+       for (;;) {
+               rp = LE_RMDADDR(sc, bix);
+               (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
+
+               if (rmd.rmd1_bits & LE_R1_OWN)
+                       break;
+
+               m = NULL;
+               if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
+                   (LE_R1_STP | LE_R1_ENP)) {
+                       if (rmd.rmd1_bits & LE_R1_ERR) {
+#ifdef LEDEBUG
+                               if (rmd.rmd1_bits & LE_R1_ENP) {
+                                       if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
+                                               if (rmd.rmd1_bits & LE_R1_FRAM)
+                                                       if_printf(ifp,
+                                                           "framing error\n");
+                                               if (rmd.rmd1_bits & LE_R1_CRC)
+                                                       if_printf(ifp,
+                                                           "crc mismatch\n");
+                                       }
+                               } else
+                                       if (rmd.rmd1_bits & LE_R1_OFLO)
+                                               if_printf(ifp, "overflow\n");
+#endif
+                               if (rmd.rmd1_bits & LE_R1_BUFF)
+                                       if_printf(ifp,
+                                           "receive buffer error\n");
+                       } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
+                           (LE_R1_STP | LE_R1_ENP))
+                               if_printf(ifp, "dropping chained buffer\n");
+               } else {
+#ifdef LEDEBUG
+                       if (sc->sc_flags & LE_DEBUG)
+                               am7990_recv_print(sc, bix);
+#endif
+                       /* Pull the packet off the interface. */
+                       m = lance_get(sc, LE_RBUFADDR(sc, bix),
+                           (int)rmd.rmd3 - ETHER_CRC_LEN);
+               }
+
+               rmd.rmd1_bits = LE_R1_OWN;
+               rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
+               rmd.rmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
+
+               if (++bix == sc->sc_nrbuf)
+                       bix = 0;
+
+               if (m != NULL) {
+                       ifp->if_ipackets++;
+
+#ifdef LANCE_REVC_BUG
+                       /*
+                        * The old LANCE (Rev. C) chips have a bug which
+                        * causes garbage to be inserted in front of the
+                        * received packet. The workaround is to ignore
+                        * packets with an invalid destination address
+                        * (garbage will usually not match).
+                        * Of course, this precludes multicast support...
+                        */
+                       eh = mtod(m, struct ether_header *);
+                       if (memcmp(eh->ether_dhost, sc->sc_enaddr,
+                                  ETHER_ADDR_LEN) &&
+                           memcmp(eh->ether_dhost, etherbroadcastaddr,
+                                  ETHER_ADDR_LEN)) {
+                               m_freem(m);
+                               continue;
+                       }
+#endif
+
+                       /* Pass the packet up. */
+                       (*ifp->if_input)(ifp, m);
+               } else
+                       ifp->if_ierrors++;
+       }
+
+       sc->sc_last_rd = bix;
+}
+
+static void
+am7990_tint(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct letmd tmd;
+       int bix;
+
+       bix = sc->sc_first_td;
+
+       for (;;) {
+               if (sc->sc_no_td <= 0)
+                       break;
+
+               (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
+                   sizeof(tmd));
+
+#ifdef LEDEBUG
+               if (sc->sc_flags & LE_DEBUG)
+                       if_printf(ifp, "trans tmd: "
+                           "ladr %04x, hadr %02x, flags %02x, "
+                           "bcnt %04x, mcnt %04x\n",
+                           tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
+                           tmd.tmd2, tmd.tmd3);
+#endif
+
+               if (tmd.tmd1_bits & LE_T1_OWN)
+                       break;
+
+               ifp->if_flags &= ~IFF_OACTIVE;
+
+               if (tmd.tmd1_bits & LE_T1_ERR) {
+                       if (tmd.tmd3 & LE_T3_BUFF)
+                               if_printf(ifp, "transmit buffer error\n");
+                       else if (tmd.tmd3 & LE_T3_UFLO)
+                               if_printf(ifp, "underflow\n");
+                       if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
+                               lance_init_locked(sc);
+                               return;
+                       }
+                       if (tmd.tmd3 & LE_T3_LCAR) {
+#if 0
+                               if (sc->sc_flags & LE_CARRIER)
+                                       if_link_state_change(ifp,
+                                           LINK_STATE_DOWN);
+#endif
+                               sc->sc_flags &= ~LE_CARRIER;
+                               if (sc->sc_nocarrier)
+                                       (*sc->sc_nocarrier)(sc);
+                               else
+                                       if_printf(ifp, "lost carrier\n");
+                       }
+                       if (tmd.tmd3 & LE_T3_LCOL)
+                               ifp->if_collisions++;
+                       if (tmd.tmd3 & LE_T3_RTRY) {
+#ifdef LEDEBUG
+                               if_printf(ifp, "excessive collisions, tdr %d\n",
+                                   tmd.tmd3 & LE_T3_TDR_MASK);
+#endif
+                               ifp->if_collisions += 16;
+                       }
+                       ifp->if_oerrors++;
+               } else {
+                       if (tmd.tmd1_bits & LE_T1_ONE)
+                               ifp->if_collisions++;
+                       else if (tmd.tmd1_bits & LE_T1_MORE)
+                               /* Real number is unknown. */
+                               ifp->if_collisions += 2;
+                       ifp->if_opackets++;
+               }
+
+               if (++bix == sc->sc_ntbuf)
+                       bix = 0;
+
+               --sc->sc_no_td;
+       }
+
+       sc->sc_first_td = bix;
+
+       ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0;
+}
+
+/*
+ * Controller interrupt
+ */
+void
+am7990_intr(void *arg)
+{
+       struct lance_softc *sc = arg;
+       struct ifnet *ifp = sc->ifp;
+       uint16_t isr;
+
+       if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
+               ifp->if_ierrors++;
+               lance_init_locked(sc);
+               return;
+       }
+
+       isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
+#if defined(LEDEBUG) && LEDEBUG > 1
+       if (sc->sc_flags & LE_DEBUG)
+               if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
+#endif
+       if ((isr & LE_C0_INTR) == 0) {
+               return;
+       }
+
+       /*
+        * Clear interrupt source flags and turn off interrupts. If we
+        * don't clear these flags before processing their sources we
+        * could completely miss some interrupt events as the NIC can
+        * change these flags while we're in this handler. We turn off
+        * interrupts so we don't get another RX interrupt while still
+        * processing the previous one in ifp->if_input() with the
+        * driver lock dropped.
+        */
+       (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
+           LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
+
+       if (isr & LE_C0_ERR) {
+               if (isr & LE_C0_BABL) {
+#ifdef LEDEBUG
+                       if_printf(ifp, "babble\n");
+#endif
+                       ifp->if_oerrors++;
+               }
+#if 0
+               if (isr & LE_C0_CERR) {
+                       if_printf(ifp, "collision error\n");
+                       ifp->if_collisions++;
+               }
+#endif
+               if (isr & LE_C0_MISS) {
+#ifdef LEDEBUG
+                       if_printf(ifp, "missed packet\n");
+#endif
+                       ifp->if_ierrors++;
+               }
+               if (isr & LE_C0_MERR) {
+                       if_printf(ifp, "memory error\n");
+                       lance_init_locked(sc);
+                       return;
+               }
+       }
+
+       if ((isr & LE_C0_RXON) == 0) {
+               if_printf(ifp, "receiver disabled\n");
+               ifp->if_ierrors++;
+               lance_init_locked(sc);
+               return;
+       }
+       if ((isr & LE_C0_TXON) == 0) {
+               if_printf(ifp, "transmitter disabled\n");
+               ifp->if_oerrors++;
+               lance_init_locked(sc);
+               return;
+       }
+
+       /*
+        * Pretend we have carrier; if we don't this will be cleared shortly.
+        */
+#if 0
+       if (!(sc->sc_flags & LE_CARRIER))
+               if_link_state_change(ifp, LINK_STATE_UP);
+#endif
+       sc->sc_flags |= LE_CARRIER;
+
+       if (isr & LE_C0_RINT)
+               am7990_rint(sc);
+       if (isr & LE_C0_TINT)
+               am7990_tint(sc);
+
+       /* Enable interrupts again. */
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
+
+       if (!ifq_is_empty(&ifp->if_snd))
+               am7990_start_locked(sc);
+
+}
+
+/*
+ * Set up output on interface.
+ * Get another datagram to send off of the interface queue, and map it to the
+ * interface before starting the output.
+ */
+static void
+am7990_start_locked(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct letmd tmd;
+       struct mbuf *m;
+       int bix, enq, len, rp;
+
+       if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
+           IFF_RUNNING)
+               return;
+
+       bix = sc->sc_last_td;
+       enq = 0;
+
+       for (; sc->sc_no_td < sc->sc_ntbuf &&
+           !ifq_is_empty(&ifp->if_snd);) {
+               m = ifq_poll(&ifp->if_snd);
+               rp = LE_TMDADDR(sc, bix);
+               (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
+
+               if (tmd.tmd1_bits & LE_T1_OWN) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       if_printf(ifp,
+                           "missing buffer, no_td = %d, last_td = %d\n",
+                           sc->sc_no_td, sc->sc_last_td);
+               }
+
+               ifq_dequeue(&ifp->if_snd, m);
+               if (m == 0)
+                       break;
+
+               /*
+                * If BPF is listening on this interface, let it see the
+                * packet before we commit it to the wire.
+                */
+               BPF_MTAP(ifp, m);
+
+               /*
+                * Copy the mbuf chain into the transmit buffer.
+                */
+               len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
+
+#ifdef LEDEBUG
+               if (len > ETHERMTU + ETHER_HDR_LEN)
+                       if_printf(ifp, "packet length %d\n", len);
+#endif
+
+               /*
+                * Init transmit registers, and set transmit start flag.
+                */
+               tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
+               tmd.tmd2 = -len | LE_XMD2_ONES;
+               tmd.tmd3 = 0;
+
+               (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
+
+#ifdef LEDEBUG
+               if (sc->sc_flags & LE_DEBUG)
+                       am7990_xmit_print(sc, bix);
+#endif
+
+               (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
+               enq++;
+
+               if (++bix == sc->sc_ntbuf)
+                       bix = 0;
+
+               if (++sc->sc_no_td == sc->sc_ntbuf) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       break;
+               }
+       }
+
+       sc->sc_last_td = bix;
+
+       if (enq > 0)
+               ifp->if_timer = 5;
+}
+
+#ifdef LEDEBUG
+static void
+am7990_recv_print(struct lance_softc *sc, int no)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct ether_header eh;
+       struct lermd rmd;
+       uint16_t len;
+
+       (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
+       len = rmd.rmd3;
+       if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
+       if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
+       if_printf(ifp,
+           "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
+           rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
+       if (len - ETHER_CRC_LEN >= sizeof(eh)) {
+               (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
+               if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
+               printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
+                   ntohs(eh.ether_type));
+       }
+}
+
+static void
+am7990_xmit_print(struct lance_softc *sc, int no)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct ether_header eh;
+       struct letmd tmd;
+       uint16_t len;
+
+       (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
+       len = -tmd.tmd2;
+       if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
+       if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
+       if_printf(ifp,
+           "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
+           tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
+       if (len >= sizeof(eh)) {
+               (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
+               if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
+               printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
+                   ntohs(eh.ether_type));
+       }
+}
+#endif /* LEDEBUG */
diff --git a/sys/dev/netif/lnc/am79900.c b/sys/dev/netif/lnc/am79900.c
new file mode 100644 (file)
index 0000000..a963577
--- /dev/null
@@ -0,0 +1,656 @@
+/*     $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $       */
+/*     $FreeBSD: src/sys/dev/le/am79900.c,v 1.3 2006/05/16 21:04:01 marius Exp $       */
+/*     $DragonFly: src/sys/dev/netif/lnc/am79900.c,v 1.1 2006/07/07 14:16:29 sephe Exp $       */
+
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+/*-
+ * Copyright (c) 1998
+ *     Matthias Drochner.  All rights reserved.
+ * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_var.h>
+#include <net/ifq_var.h>
+
+#include <machine/bus.h>
+
+#include <dev/netif/lnc/lancereg.h>
+#include <dev/netif/lnc/lancevar.h>
+#include <dev/netif/lnc/am79900reg.h>
+#include <dev/netif/lnc/am79900var.h>
+
+static void    am79900_meminit(struct lance_softc *);
+static void    am79900_rint(struct lance_softc *);
+static void    am79900_tint(struct lance_softc *);
+static void    am79900_start_locked(struct lance_softc *sc);
+
+#ifdef LEDEBUG
+static void    am79900_recv_print(struct lance_softc *, int);
+static void    am79900_xmit_print(struct lance_softc *, int);
+#endif
+
+int
+am79900_config(struct am79900_softc *sc, const char* name, int unit)
+{
+       int error, mem;
+
+       sc->lsc.sc_meminit = am79900_meminit;
+       sc->lsc.sc_start_locked = am79900_start_locked;
+
+       error = lance_config(&sc->lsc, name, unit);
+       if (error != 0)
+               return (error);
+
+       mem = 0;
+       sc->lsc.sc_initaddr = mem;
+       mem += sizeof(struct leinit);
+       sc->lsc.sc_rmdaddr = mem;
+       mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
+       sc->lsc.sc_tmdaddr = mem;
+       mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
+       sc->lsc.sc_rbufaddr = mem;
+       mem += LEBLEN * sc->lsc.sc_nrbuf;
+       sc->lsc.sc_tbufaddr = mem;
+       mem += LEBLEN * sc->lsc.sc_ntbuf;
+
+       if (mem > sc->lsc.sc_memsize)
+               panic("%s: memsize", __func__);
+
+       lance_attach(&sc->lsc);
+
+       return (0);
+}
+
+void
+am79900_detach(struct am79900_softc *sc)
+{
+
+       ether_ifdetach(sc->lsc.ifp);
+}
+
+/*
+ * Set up the initialization block and the descriptor rings.
+ */
+static void
+am79900_meminit(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct leinit init;
+       struct lermd rmd;
+       struct letmd tmd;
+       u_long a;
+       int bix;
+
+       if (ifp->if_flags & IFF_PROMISC)
+               init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM);
+       else
+               init.init_mode = LE_HTOLE32(LE_MODE_NORMAL);
+
+       init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) |
+           ((ffs(sc->sc_nrbuf) - 1) << 20));
+
+       init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] |
+           (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) |
+           (sc->sc_enaddr[3] << 24));
+       init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] |
+           (sc->sc_enaddr[5] << 8));
+       lance_setladrf(sc, init.init_ladrf);
+
+       sc->sc_last_rd = 0;
+       sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
+
+       a = sc->sc_addr + LE_RMDADDR(sc, 0);
+       init.init_rdra = LE_HTOLE32(a);
+
+       a = sc->sc_addr + LE_TMDADDR(sc, 0);
+       init.init_tdra = LE_HTOLE32(a);
+
+       (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
+
+       /*
+        * Set up receive ring descriptors.
+        */
+       for (bix = 0; bix < sc->sc_nrbuf; bix++) {
+               a = sc->sc_addr + LE_RBUFADDR(sc, bix);
+               rmd.rmd0 = LE_HTOLE32(a);
+               rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
+                   (-LEBLEN & 0xfff));
+               rmd.rmd2 = 0;
+               rmd.rmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
+                   sizeof(rmd));
+       }
+
+       /*
+        * Set up transmit ring descriptors.
+        */
+       for (bix = 0; bix < sc->sc_ntbuf; bix++) {
+               a = sc->sc_addr + LE_TBUFADDR(sc, bix);
+               tmd.tmd0 = LE_HTOLE32(a);
+               tmd.tmd1 = LE_HTOLE32(LE_T1_ONES);
+               tmd.tmd2 = 0;
+               tmd.tmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
+                   sizeof(tmd));
+       }
+}
+
+static void
+am79900_rint(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct mbuf *m;
+       struct lermd rmd;
+       uint32_t rmd1;
+       int bix, rp;
+#if defined(__i386__) && !defined(PC98)
+       struct ether_header *eh;
+#endif
+
+       bix = sc->sc_last_rd;
+
+       /* Process all buffers with valid data. */
+       for (;;) {
+               rp = LE_RMDADDR(sc, bix);
+               (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
+
+               rmd1 = LE_LE32TOH(rmd.rmd1);
+               if (rmd1 & LE_R1_OWN)
+                       break;
+
+               m = NULL;
+               if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
+                   (LE_R1_STP | LE_R1_ENP)){
+                       if (rmd1 & LE_R1_ERR) {
+#ifdef LEDEBUG
+                               if (rmd1 & LE_R1_ENP) {
+                                       if ((rmd1 & LE_R1_OFLO) == 0) {
+                                               if (rmd1 & LE_R1_FRAM)
+                                                       if_printf(ifp,
+                                                           "framing error\n");
+                                               if (rmd1 & LE_R1_CRC)
+                                                       if_printf(ifp,
+                                                           "crc mismatch\n");
+                                       }
+                               } else
+                                       if (rmd1 & LE_R1_OFLO)
+                                               if_printf(ifp, "overflow\n");
+#endif
+                               if (rmd1 & LE_R1_BUFF)
+                                       if_printf(ifp,
+                                           "receive buffer error\n");
+                       } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) !=
+                           (LE_R1_STP | LE_R1_ENP))
+                               if_printf(ifp, "dropping chained buffer\n");
+               } else {
+#ifdef LEDEBUG
+                       if (sc->sc_flags & LE_DEBUG)
+                               am79900_recv_print(sc, bix);
+#endif
+                       /* Pull the packet off the interface. */
+                       m = lance_get(sc, LE_RBUFADDR(sc, bix),
+                           (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN);
+               }
+
+               rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
+                   (-LEBLEN & 0xfff));
+               rmd.rmd2 = 0;
+               rmd.rmd3 = 0;
+               (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
+
+               if (++bix == sc->sc_nrbuf)
+                       bix = 0;
+
+               if (m != NULL) {
+                       ifp->if_ipackets++;
+
+#ifdef __i386__
+                       /*
+                        * The VMware LANCE does not present IFF_SIMPLEX
+                        * behavior on multicast packets. Thus drop the
+                        * packet if it is from ourselves.
+                        */
+                       eh = mtod(m, struct ether_header *);
+                       if (memcmp(eh->ether_shost, sc->sc_enaddr,
+                                  ETHER_ADDR_LEN) == 0) {
+                               m_freem(m);
+                               continue;
+                       }
+#endif
+
+                       /* Pass the packet up. */
+                       (*ifp->if_input)(ifp, m);
+               } else
+                       ifp->if_ierrors++;
+       }
+
+       sc->sc_last_rd = bix;
+}
+
+static void
+am79900_tint(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct letmd tmd;
+       uint32_t tmd1, tmd2;
+       int bix;
+
+       bix = sc->sc_first_td;
+
+       for (;;) {
+               if (sc->sc_no_td <= 0)
+                       break;
+
+               (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
+                   sizeof(tmd));
+
+               tmd1 = LE_LE32TOH(tmd.tmd1);
+
+#ifdef LEDEBUG
+               if (sc->sc_flags & LE_DEBUG)
+                       if_printf(ifp, "trans tmd: "
+                           "adr %08x, flags/blen %08x\n",
+                           LE_LE32TOH(tmd.tmd0), tmd1);
+#endif
+
+               if (tmd1 & LE_T1_OWN)
+                       break;
+
+               ifp->if_flags &= ~IFF_OACTIVE;
+
+               if (tmd1 & LE_T1_ERR) {
+                       tmd2 = LE_LE32TOH(tmd.tmd2);
+                       if (tmd2 & LE_T2_BUFF)
+                               if_printf(ifp, "transmit buffer error\n");
+                       else if (tmd2 & LE_T2_UFLO)
+                               if_printf(ifp, "underflow\n");
+                       if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) {
+                               lance_init_locked(sc);
+                               return;
+                       }
+                       if (tmd2 & LE_T2_LCAR) {
+#if 0
+                               if (sc->sc_flags & LE_CARRIER)
+                                       if_link_state_change(ifp,
+                                           LINK_STATE_DOWN);
+#endif
+                               sc->sc_flags &= ~LE_CARRIER;
+                               if (sc->sc_nocarrier)
+                                       (*sc->sc_nocarrier)(sc);
+                               else
+                                       if_printf(ifp, "lost carrier\n");
+                       }
+                       if (tmd2 & LE_T2_LCOL)
+                               ifp->if_collisions++;
+                       if (tmd2 & LE_T2_RTRY) {
+#ifdef LEDEBUG
+                               if_printf(ifp, "excessive collisions\n");
+#endif
+                               ifp->if_collisions += 16;
+                       }
+                       ifp->if_oerrors++;
+               } else {
+                       if (tmd1 & LE_T1_ONE)
+                               ifp->if_collisions++;
+                       else if (tmd1 & LE_T1_MORE)
+                               /* Real number is unknown. */
+                               ifp->if_collisions += 2;
+                       ifp->if_opackets++;
+               }
+
+               if (++bix == sc->sc_ntbuf)
+                       bix = 0;
+
+               --sc->sc_no_td;
+       }
+
+       sc->sc_first_td = bix;
+
+       ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0;
+}
+
+/*
+ * Controller interrupt
+ */
+void
+am79900_intr(void *arg)
+{
+       struct lance_softc *sc = arg;
+       struct ifnet *ifp = sc->ifp;
+       uint16_t isr;
+
+       if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
+               ifp->if_ierrors++;
+               lance_init_locked(sc);
+               return;
+       }
+
+       isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
+#if defined(LEDEBUG) && LEDEBUG > 1
+       if (sc->sc_flags & LE_DEBUG)
+               if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
+#endif
+       if ((isr & LE_C0_INTR) == 0) {
+               return;
+       }
+
+       /*
+        * Clear interrupt source flags and turn off interrupts. If we
+        * don't clear these flags before processing their sources we
+        * could completely miss some interrupt events as the NIC can
+        * change these flags while we're in this handler. We turn off
+        * interrupts so we don't get another RX interrupt while still
+        * processing the previous one in ifp->if_input() with the
+        * driver lock dropped.
+        */
+       (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
+           LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
+
+       if (isr & LE_C0_ERR) {
+               if (isr & LE_C0_BABL) {
+#ifdef LEDEBUG
+                       if_printf(ifp, "babble\n");
+#endif
+                       ifp->if_oerrors++;
+               }
+#if 0
+               if (isr & LE_C0_CERR) {
+                       if_printf(ifp, "collision error\n");
+                       ifp->if_collisions++;
+               }
+#endif
+               if (isr & LE_C0_MISS) {
+#ifdef LEDEBUG
+                       if_printf(ifp, "missed packet\n");
+#endif
+                       ifp->if_ierrors++;
+               }
+               if (isr & LE_C0_MERR) {
+                       if_printf(ifp, "memory error\n");
+                       lance_init_locked(sc);
+                       return;
+               }
+       }
+
+       if ((isr & LE_C0_RXON) == 0) {
+               if_printf(ifp, "receiver disabled\n");
+               ifp->if_ierrors++;
+               lance_init_locked(sc);
+               return;
+       }
+       if ((isr & LE_C0_TXON) == 0) {
+               if_printf(ifp, "transmitter disabled\n");
+               ifp->if_oerrors++;
+               lance_init_locked(sc);
+               return;
+       }
+
+       /*
+        * Pretend we have carrier; if we don't this will be cleared shortly.
+        */
+#if 0
+       if (!(sc->sc_flags & LE_CARRIER))
+               if_link_state_change(ifp, LINK_STATE_UP);
+#endif
+       sc->sc_flags |= LE_CARRIER;
+
+       if (isr & LE_C0_RINT)
+               am79900_rint(sc);
+       if (isr & LE_C0_TINT)
+               am79900_tint(sc);
+
+       /* Enable interrupts again. */
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
+
+       if (!ifq_is_empty(&ifp->if_snd))
+               am79900_start_locked(sc);
+
+}
+
+/*
+ * Set up output on interface.
+ * Get another datagram to send off of the interface queue, and map it to the
+ * interface before starting the output.
+ */
+static void
+am79900_start_locked(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct letmd tmd;
+       struct mbuf *m;
+       int bix, enq, len, rp;
+
+       if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
+           IFF_RUNNING)
+               return;
+
+       bix = sc->sc_last_td;
+       enq = 0;
+
+       for (; sc->sc_no_td < sc->sc_ntbuf &&
+           !ifq_is_empty(&ifp->if_snd);) {
+               m = ifq_poll(&ifp->if_snd);
+               rp = LE_TMDADDR(sc, bix);
+               (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
+
+               if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       if_printf(ifp,
+                           "missing buffer, no_td = %d, last_td = %d\n",
+                           sc->sc_no_td, sc->sc_last_td);
+               }
+
+               ifq_dequeue(&ifp->if_snd, m);
+               if (m == 0)
+                       break;
+
+               /*
+                * If BPF is listening on this interface, let it see the packet
+                * before we commit it to the wire.
+                */
+               BPF_MTAP(ifp, m);
+
+               /*
+                * Copy the mbuf chain into the transmit buffer.
+                */
+               len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
+
+#ifdef LEDEBUG
+               if (len > ETHERMTU + ETHER_HDR_LEN)
+                       if_printf(ifp, "packet length %d\n", len);
+#endif
+
+               /*
+                * Init transmit registers, and set transmit start flag.
+                */
+               tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP |
+                   LE_T1_ONES | (-len & 0xfff));
+               tmd.tmd2 = 0;
+               tmd.tmd3 = 0;
+
+               (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
+
+#ifdef LEDEBUG
+               if (sc->sc_flags & LE_DEBUG)
+                       am79900_xmit_print(sc, bix);
+#endif
+
+               (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
+               enq++;
+
+               if (++bix == sc->sc_ntbuf)
+                       bix = 0;
+
+               if (++sc->sc_no_td == sc->sc_ntbuf) {
+                       ifp->if_flags |= IFF_OACTIVE;
+                       break;
+               }
+       }
+
+       sc->sc_last_td = bix;
+
+       if (enq > 0)
+               ifp->if_timer = 5;
+}
+
+#ifdef LEDEBUG
+static void
+am79900_recv_print(struct lance_softc *sc, int no)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct ether_header eh;
+       struct lermd rmd;
+       uint16_t len;
+
+       (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
+       len = LE_LE32TOH(rmd.rmd2) & 0xfff;
+       if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
+       if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
+       if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0),
+           LE_LE32TOH(rmd.rmd1));
+       if (len - ETHER_CRC_LEN >= sizeof(eh)) {
+               (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
+               if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
+               printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
+                   ntohs(eh.ether_type));
+       }
+}
+
+static void
+am79900_xmit_print(struct lance_softc *sc, int no)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct ether_header eh;
+       struct letmd tmd;
+       uint16_t len;
+
+       (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
+       len = -(LE_LE32TOH(tmd.tmd1) & 0xfff);
+       if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
+       if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
+       if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0),
+           LE_LE32TOH(tmd.tmd1));
+       if (len >= sizeof(eh)) {
+               (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
+               if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
+               printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
+                   ntohs(eh.ether_type));
+       }
+}
+#endif /* LEDEBUG */
diff --git a/sys/dev/netif/lnc/am79900reg.h b/sys/dev/netif/lnc/am79900reg.h
new file mode 100644 (file)
index 0000000..b7f15d9
--- /dev/null
@@ -0,0 +1,157 @@
+/*     $NetBSD: am79900reg.h,v 1.8 2005/12/11 12:21:25 christos Exp $  */
+/*     $FreeBSD: src/sys/dev/le/am79900reg.h,v 1.1 2006/01/31 14:48:58 marius Exp $    */
+/*     $DragonFly: src/sys/dev/netif/lnc/am79900reg.h,v 1.1 2006/07/07 14:16:29 sephe Exp $    */
+
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_lereg.h  8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _DEV_LE_AM79900REG_H_
+#define        _DEV_LE_AM79900REG_H_
+
+/*
+ * Receive message descriptor
+ */
+struct lermd {
+       uint32_t        rmd0;
+       uint32_t        rmd1;
+       uint32_t        rmd2;
+       int32_t         rmd3;
+};
+
+/*
+ * Transmit message descriptor
+ */
+struct letmd {
+       uint32_t        tmd0;
+       uint32_t        tmd1;
+       uint32_t        tmd2;
+       int32_t         tmd3;
+};
+
+/*
+ * Initialization block
+ */
+struct leinit {
+       uint32_t        init_mode;      /* +0x0000 */
+       uint32_t        init_padr[2];   /* +0x0002 */
+       uint16_t        init_ladrf[4];  /* +0x0008 */
+       uint32_t        init_rdra;      /* +0x0010 */
+       uint32_t        init_tdra;      /* +0x0014 */
+       int32_t         pad;            /* Pad to 8 ints. */
+};
+
+/* Receive message descriptor 1 (rmd1_bits) */
+#define        LE_R1_OWN       (1U << 31)      /* LANCE owns the packet */
+#define        LE_R1_ERR       (1U << 30)      /* error summary */
+#define        LE_R1_FRAM      (1U << 29)      /* framing error */
+#define        LE_R1_OFLO      (1U << 28)      /* overflow error */
+#define        LE_R1_CRC       (1U << 27)      /* CRC error */
+#define        LE_R1_BUFF      (1U << 26)      /* buffer error */
+#define        LE_R1_STP       (1U << 25)      /* start of packet */
+#define        LE_R1_ENP       (1U << 24)      /* end of packet */
+#define        LE_R1_ONES      (0xfU << 12)    /* must be ones */
+#define        LE_R1_BCNT_MASK (0xfff)         /* byte count mask */
+
+#define        LE_R1_BITS \
+    "\20\40OWN\37ERR\36FRAM\35OFLO\34CRC\33BUFF\32STP\31ENP"
+
+/* Transmit message descriptor 1 (tmd1_bits) */
+#define        LE_T1_OWN       (1U << 31)      /* LANCE owns the packet */
+#define        LE_T1_ERR       (1U << 30)      /* error summary */
+#define        LE_T1_ADD_FCS   (1U << 29)      /* add FCS (PCnet-PCI) */
+#define        LE_T1_NO_FCS    (1U << 29)      /* no FCS (ILACC) */
+#define        LE_T1_MORE      (1U << 28)      /* multiple collisions */
+#define        LE_T1_LTINT     (1U << 28)      /* transmit interrupt (if LTINTEN) */
+#define        LE_T1_ONE       (1U << 27)      /* single collision */
+#define        LE_T1_DEF       (1U << 26)      /* deferred transmit */
+#define        LE_T1_STP       (1U << 25)      /* start of packet */
+#define        LE_T1_ENP       (1U << 24)      /* end of packet */
+#define        LE_T1_ONES      (0xfU << 12)    /* must be ones */
+#define        LE_T1_BCNT_MASK (0xfff)         /* byte count mask */
+
+#define        LE_T1_BITS \
+    "\20\40OWN\37ERR\36RES\35MORE\34ONE\33DEF\32STP\31ENP"
+
+/* Transmit message descriptor 3 (tmd3) */
+#define        LE_T2_BUFF      (1U << 31)      /* buffer error */
+#define        LE_T2_UFLO      (1U << 30)      /* underflow error */
+#define        LE_T2_EXDEF     (1U << 29)      /* excessive defferral */
+#define        LE_T2_LCOL      (1U << 28)      /* late collision */
+#define        LE_T2_LCAR      (1U << 27)      /* loss of carrier */
+#define        LE_T2_RTRY      (1U << 26)      /* retry error */
+#if 0
+#define        LE_T3_TDR_MASK  0x03ff          /* time domain reflectometry counter */
+#endif
+
+#define        LE_T3_BITS \
+    "\12\40BUFF\37UFLO\35LCOL\34LCAR\33RTRY"
+
+#endif /* !_DEV_LE_AM7990REG_H_ */
diff --git a/sys/dev/netif/lnc/am79900var.h b/sys/dev/netif/lnc/am79900var.h
new file mode 100644 (file)
index 0000000..367f7ab
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: am79900var.h,v 1.4 2005/12/11 12:21:25 christos Exp $  */
+/*     $FreeBSD: src/sys/dev/le/am79900var.h,v 1.1 2006/01/31 14:48:58 marius Exp $    */
+/*     $DragonFly: src/sys/dev/netif/lnc/am79900var.h,v 1.1 2006/07/07 14:16:29 sephe Exp $    */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _DEV_LE_AM79900VAR_H_
+#define        _DEV_LE_AM79900VAR_H_
+
+/*
+ * Ethernet software status per device.
+ *
+ * NOTE: this structure MUST be the first element in machine-dependent
+ * le_softc structures!  This is designed SPECIFICALLY to make it possible
+ * to simply cast a "void *" to "struct le_softc *" or to
+ * "struct am79900_softc *".  Among other things, this saves a lot of hair
+ * in the interrupt handlers.
+ */
+struct am79900_softc {
+       struct lance_softc lsc;
+};
+
+int    am79900_config(struct am79900_softc *, const char*, int);
+void   am79900_detach(struct am79900_softc *);
+void   am79900_intr(void *);
+
+#endif /* _DEV_LE_AM79900VAR_H_ */
diff --git a/sys/dev/netif/lnc/am7990reg.h b/sys/dev/netif/lnc/am7990reg.h
new file mode 100644 (file)
index 0000000..9a7cb56
--- /dev/null
@@ -0,0 +1,190 @@
+/*     $NetBSD: am7990reg.h,v 1.11 2005/12/11 12:21:25 christos Exp $  */
+/*     $FreeBSD: src/sys/dev/le/am7990reg.h,v 1.1 2006/01/31 14:48:58 marius Exp $     */
+/*     $DragonFly: src/sys/dev/netif/lnc/am7990reg.h,v 1.1 2006/07/07 14:16:29 sephe Exp $     */
+
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_lereg.h  8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _DEV_LE_AM7990REG_H_
+#define        _DEV_LE_AM7990REG_H_
+
+/*
+ * Receive message descriptor
+ */
+struct lermd {
+       uint16_t rmd0;
+#if BYTE_ORDER == BIG_ENDIAN
+       uint8_t  rmd1_bits;
+       uint8_t  rmd1_hadr;
+#else
+       uint8_t  rmd1_hadr;
+       uint8_t  rmd1_bits;
+#endif
+       int16_t  rmd2;
+       uint16_t rmd3;
+} __packed;
+
+/*
+ * Transmit message descriptor
+ */
+struct letmd {
+       uint16_t tmd0;
+#if BYTE_ORDER == BIG_ENDIAN
+       uint8_t  tmd1_bits;
+       uint8_t  tmd1_hadr;
+#else
+       uint8_t  tmd1_hadr;
+       uint8_t  tmd1_bits;
+#endif
+       int16_t  tmd2;
+       uint16_t tmd3;
+} __packed;
+
+/*
+ * Initialization block
+ */
+struct leinit {
+       uint16_t init_mode;             /* +0x0000 */
+       uint16_t init_padr[3];          /* +0x0002 */
+       uint16_t init_ladrf[4];         /* +0x0008 */
+       uint16_t init_rdra;             /* +0x0010 */
+       uint16_t init_rlen;             /* +0x0012 */
+       uint16_t init_tdra;             /* +0x0014 */
+       uint16_t init_tlen;             /* +0x0016 */
+       int16_t  pad0[4];               /* Pad to 16 shorts. */
+} __packed;
+
+/* Receive message descriptor 1 (rmd1_bits) */
+#define        LE_R1_OWN       0x80            /* LANCE owns the packet */
+#define        LE_R1_ERR       0x40            /* error summary */
+#define        LE_R1_FRAM      0x20            /* framing error */
+#define        LE_R1_OFLO      0x10            /* overflow error */
+#define        LE_R1_CRC       0x08            /* CRC error */
+#define        LE_R1_BUFF      0x04            /* buffer error */
+#define        LE_R1_STP       0x02            /* start of packet */
+#define        LE_R1_ENP       0x01            /* end of packet */
+
+#define        LE_R1_BITS \
+    "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
+
+/* Transmit message descriptor 1 (tmd1_bits) */
+#define        LE_T1_OWN       0x80            /* LANCE owns the packet */
+#define        LE_T1_ERR       0x40            /* error summary */
+#define        LE_T1_MORE      0x10            /* multiple collisions */
+#define        LE_T1_ONE       0x08            /* single collision */
+#define        LE_T1_DEF       0x04            /* deferred transmit */
+#define        LE_T1_STP       0x02            /* start of packet */
+#define        LE_T1_ENP       0x01            /* end of packet */
+
+#define        LE_T1_BITS \
+    "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
+
+/* Transmit message descriptor 3 (tmd3) */
+#define        LE_T3_BUFF      0x8000          /* buffer error */
+#define        LE_T3_UFLO      0x4000          /* underflow error */
+#define        LE_T3_LCOL      0x1000          /* late collision */
+#define        LE_T3_LCAR      0x0800          /* loss of carrier */
+#define        LE_T3_RTRY      0x0400          /* retry error */
+#define        LE_T3_TDR_MASK  0x03ff          /* time domain reflectometry counter */
+
+#define        LE_XMD2_ONES    0xf000
+
+#define        LE_T3_BITS \
+    "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"
+
+/*
+ * PCnet-ISA defines which are not available on LANCE 7990.
+ */
+
+/* (ISA) Bus Configuration Registers */
+#define        LE_BCR_MSRDA    0x0000
+#define        LE_BCR_MSWRA    0x0001
+#define        LE_BCR_MC       0x0002
+#define        LE_BCR_LED1     0x0005
+#define        LE_BCR_LED2     0x0006
+#define        LE_BCR_LED3     0x0007
+
+/* Bus configurations bits (MC) */
+#define        LE_MC_EADISEL   0x0008          /* EADI selection */
+#define        LE_MC_AWAKE     0x0004          /* auto-wake */
+#define        LE_MC_ASEL      0x0002          /* auto selection */
+#define        LE_MC_XMAUSEL   0x0001          /* external MAU selection */
+
+/* LED bis (LED[123]) */
+#define        LE_LED_LEDOUT   0x8000
+#define        LE_LED_PSE      0x0080
+#define        LE_LED_XMTE     0x0010
+#define        LE_LED_PVPE     0x0008
+#define        LE_LED_PCVE     0x0004
+#define        LE_LED_JABE     0x0002
+#define        LE_LED_COLE     0x0001
+
+#endif /* !_DEV_LE_AM7990REG_H_ */
diff --git a/sys/dev/netif/lnc/am7990var.h b/sys/dev/netif/lnc/am7990var.h
new file mode 100644 (file)
index 0000000..652edeb
--- /dev/null
@@ -0,0 +1,62 @@
+/*     $NetBSD: am7990var.h,v 1.23 2005/12/11 12:21:25 christos Exp $  */
+/*     $FreeBSD: src/sys/dev/le/am7990var.h,v 1.1 2006/01/31 14:48:58 marius Exp $     */
+/*     $DragonFly: src/sys/dev/netif/lnc/am7990var.h,v 1.1 2006/07/07 14:16:29 sephe Exp $     */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _DEV_LE_AM7990VAR_H_
+#define        _DEV_LE_AM7990VAR_H_
+
+/*
+ * Ethernet software status per device.
+ *
+ * NOTE: this structure MUST be the first element in machine-dependent
+ * le_softc structures!  This is designed SPECIFICALLY to make it possible
+ * to simply cast a "void *" to "struct le_softc *" or to
+ * "struct am7990_softc *".  Among other things, this saves a lot of hair
+ * in the interrupt handlers.
+ */
+struct am7990_softc {
+       struct lance_softc lsc;
+};
+
+int    am7990_config(struct am7990_softc *, const char*, int);
+void   am7990_detach(struct am7990_softc *);
+void   am7990_intr(void *);
+
+#endif /* !_DEV_LE_AM7990VAR_H_ */
diff --git a/sys/dev/netif/lnc/if_lnc.c b/sys/dev/netif/lnc/if_lnc.c
deleted file mode 100644 (file)
index 15fe2f7..0000000
+++ /dev/null
@@ -1,1534 +0,0 @@
-/*-
- * Copyright (c) 1994-2000
- *     Paul Richards.  All rights reserved.
- *
- * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
- * 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.
- * 3. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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: src/sys/dev/lnc/if_lnc.c,v 1.89 2001/07/04 13:00:19 nyan Exp $
- * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lnc.c,v 1.25 2005/12/11 01:54:08 swildner Exp $
- */
-
-/*
-#define DIAGNOSTIC
-#define DEBUG
- *
- * TODO ----
- *
- * Check all the XXX comments -- some of them are just things I've left
- * unfinished rather than "difficult" problems that were hacked around.
- *
- * Check log settings.
- *
- * Check how all the arpcom flags get set and used.
- *
- * Re-inline and re-static all routines after debugging.
- *
- * Remember to assign iobase in SHMEM probe routines.
- *
- * Replace all occurences of LANCE-controller-card etc in prints by the name
- * strings of the appropriate type -- nifty window dressing
- *
- * Add DEPCA support -- mostly done.
- *
- */
-
-#include "opt_inet.h"
-
-/* Some defines that should really be in generic locations */
-#define FCS_LEN 4
-#define MULTICAST_FILTER_LEN 8
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/syslog.h>
-#include <sys/serialize.h>
-#include <sys/thread2.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
-#include <sys/rman.h>
-
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <net/ifq_var.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-
-#include <net/bpf.h>
-
-#include <machine/md_var.h>
-
-#include <dev/netif/lnc/if_lncvar.h>
-#include <dev/netif/lnc/if_lncreg.h>
-
-DECLARE_DUMMY_MODULE(if_lnc);
-
-devclass_t lnc_devclass;
-
-static char const * const nic_ident[] = {
-       "Unknown",
-       "BICC",
-       "NE2100",
-       "DEPCA",
-       "CNET98S",      /* PC-98 */
-};
-
-static char const * const ic_ident[] = {
-       "Unknown",
-       "LANCE",
-       "C-LANCE",
-       "PCnet-ISA",
-       "PCnet-ISA+",
-       "PCnet-ISA II",
-       "PCnet-32 VL-Bus",
-       "PCnet-PCI",
-       "PCnet-PCI II",
-       "PCnet-FAST",
-       "PCnet-FAST+",
-       "PCnet-Home",
-};
-
-static void lnc_setladrf(struct lnc_softc *sc);
-static void lnc_reset(struct lnc_softc *sc);
-static void lnc_free_mbufs(struct lnc_softc *sc);
-static __inline int alloc_mbuf_cluster(struct lnc_softc *sc,
-                                           struct host_ring_entry *desc);
-static __inline struct mbuf *chain_mbufs(struct lnc_softc *sc,
-                                             int start_of_packet,
-                                             int pkt_len);
-static __inline struct mbuf *mbuf_packet(struct lnc_softc *sc,
-                                             int start_of_packet,
-                                             int pkt_len);
-static void    lnc_rint(struct lnc_softc *sc);
-static void    lnc_tint(struct lnc_softc *sc);
-
-static void lnc_init(void *);
-static __inline int mbuf_to_buffer(struct mbuf *m, char *buffer);
-static __inline struct mbuf *chain_to_cluster(struct mbuf *m);
-static void lnc_start(struct ifnet *ifp);
-static int lnc_ioctl(struct ifnet *ifp, u_long command, caddr_t data,
-                    struct ucred *);
-static void lnc_watchdog(struct ifnet *ifp);
-#ifdef DEBUG
-void lnc_dump_state(struct lnc_softc *sc);
-void mbuf_dump_chain(struct mbuf *m);
-#endif
-
-u_short
-read_csr(struct lnc_softc *sc, u_short port)
-{
-       lnc_outw(sc->rap, port);
-       return (lnc_inw(sc->rdp));
-}
-
-void
-write_csr(struct lnc_softc *sc, u_short port, u_short val)
-{
-       lnc_outw(sc->rap, port);
-       lnc_outw(sc->rdp, val);
-}
-
-static __inline void
-write_bcr(struct lnc_softc *sc, u_short port, u_short val)
-{
-       lnc_outw(sc->rap, port);
-       lnc_outw(sc->bdp, val);
-}
-
-static __inline u_short
-read_bcr(struct lnc_softc *sc, u_short port)
-{
-       lnc_outw(sc->rap, port);
-       return (lnc_inw(sc->bdp));
-}
-
-int
-lance_probe(struct lnc_softc *sc)
-{
-       write_csr(sc, CSR0, STOP);
-
-       if ((lnc_inw(sc->rdp) & STOP) && ! (read_csr(sc, CSR3))) {
-               /*
-                * Check to see if it's a C-LANCE. For the LANCE the INEA bit
-                * cannot be set while the STOP bit is. This restriction is
-                * removed for the C-LANCE.
-                */
-               write_csr(sc, CSR0, INEA);
-               if (read_csr(sc, CSR0) & INEA)
-                       return (C_LANCE);
-               else
-                       return (LANCE);
-       } else
-               return (UNKNOWN);
-}
-
-static __inline u_long
-ether_crc(const u_char *ether_addr)
-{
-#define POLYNOMIAL           0xEDB88320UL
-    u_char i, j, addr;
-    u_int crc = 0xFFFFFFFFUL;
-
-    for (i = 0; i < ETHER_ADDR_LEN; i++) {
-       addr = *ether_addr++;
-       for (j = 0; j < MULTICAST_FILTER_LEN; j++) {
-           crc = (crc >> 1) ^ (((crc ^ addr) & 1) ? POLYNOMIAL : 0);   
-           addr >>= 1;
-       }
-    }
-    return crc;
-#undef POLYNOMIAL
-}
-
-/*
- * Set up the logical address filter for multicast packets
- */
-static __inline void
-lnc_setladrf(struct lnc_softc *sc)
-{
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       struct ifmultiaddr *ifma;
-       u_long index;
-       int i;
-
-       if (sc->flags & IFF_ALLMULTI) {
-           for (i=0; i < MULTICAST_FILTER_LEN; i++)
-               sc->init_block->ladrf[i] = 0xFF;
-           return;
-       }
-
-       /*
-        * For each multicast address, calculate a crc for that address and
-        * then use the high order 6 bits of the crc as a hash code where
-        * bits 3-5 select the byte of the address filter and bits 0-2 select
-        * the bit within that byte.
-        */
-
-       bzero(sc->init_block->ladrf, MULTICAST_FILTER_LEN);
-       LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
-               if (ifma->ifma_addr->sa_family != AF_LINK)
-                       continue;
-
-               index = ether_crc(LLADDR((struct sockaddr_dl *)ifma->ifma_addr))
-                               >> 26;
-               sc->init_block->ladrf[index >> 3] |= 1 << (index & 7);
-       }
-}
-
-void
-lnc_stop(struct lnc_softc *sc)
-{
-       write_csr(sc, CSR0, STOP);
-}
-
-static void
-lnc_reset(struct lnc_softc *sc)
-{
-       lnc_init(sc);
-}
-
-static void
-lnc_free_mbufs(struct lnc_softc *sc)
-{
-       int i;
-
-       /*
-        * We rely on other routines to keep the buff.mbuf field valid. If
-        * it's not NULL then we assume it points to an allocated mbuf.
-        */
-
-       for (i = 0; i < NDESC(sc->nrdre); i++)
-               if ((sc->recv_ring + i)->buff.mbuf)
-                       m_free((sc->recv_ring + i)->buff.mbuf);
-
-       for (i = 0; i < NDESC(sc->ntdre); i++)
-               if ((sc->trans_ring + i)->buff.mbuf)
-                       m_free((sc->trans_ring + i)->buff.mbuf);
-
-       if (sc->mbuf_count)
-               m_freem(sc->mbufs);
-}
-
-static __inline int
-alloc_mbuf_cluster(struct lnc_softc *sc, struct host_ring_entry *desc)
-{
-       struct mds *md = desc->md;
-       struct mbuf *m=0;
-       int addr;
-
-       /* Try and get cluster off local cache */
-       if (sc->mbuf_count) {
-               sc->mbuf_count--;
-               m = sc->mbufs;
-               sc->mbufs = m->m_next;
-               /* XXX m->m_data = m->m_ext.ext_buf;*/
-       } else {
-               m = m_getcl(MB_DONTWAIT, MT_DATA, 0);
-               if (m == NULL)
-                       return (1);
-       }
-
-       desc->buff.mbuf = m;
-       addr = kvtop(m->m_data);
-       md->md0 = addr;
-       md->md1= ((addr >> 16) & 0xff) | OWN;
-       md->md2 = -(short)(MCLBYTES - sizeof(struct pkthdr));
-       md->md3 = 0;
-       return(0);
-}
-
-static __inline struct mbuf *
-chain_mbufs(struct lnc_softc *sc, int start_of_packet, int pkt_len)
-{
-       struct mbuf *head, *m;
-       struct host_ring_entry *desc;
-
-       /*
-        * Turn head into a pkthdr mbuf --
-        * assumes a pkthdr type mbuf was
-        * allocated to the descriptor
-        * originally.
-        */
-
-       desc = sc->recv_ring + start_of_packet;
-
-       head = desc->buff.mbuf;
-       head->m_flags |= M_PKTHDR;
-       bzero(&head->m_pkthdr, sizeof(head->m_pkthdr));
-
-       m = head;
-       do {
-               m = desc->buff.mbuf;
-               m->m_len = min((MCLBYTES - sizeof(struct pkthdr)), pkt_len);
-               pkt_len -= m->m_len;
-               if (alloc_mbuf_cluster(sc, desc))
-                       return((struct mbuf *)NULL);
-               INC_MD_PTR(start_of_packet, sc->nrdre)
-               desc = sc->recv_ring + start_of_packet;
-               m->m_next = desc->buff.mbuf;
-       } while (start_of_packet != sc->recv_next);
-
-       m->m_next = 0;
-       return(head);
-}
-
-static __inline struct mbuf *
-mbuf_packet(struct lnc_softc *sc, int start_of_packet, int pkt_len)
-{
-
-       struct host_ring_entry *start;
-       struct mbuf *head,*m,*m_prev;
-       char *data,*mbuf_data;
-       short blen;
-       int amount;
-
-       /* Get a pkthdr mbuf for the start of packet */
-       MGETHDR(head, MB_DONTWAIT, MT_DATA);
-       if (!head) {
-               LNCSTATS(drop_packet)
-               return(0);
-       }
-
-       m = head;
-       m->m_len = 0;
-       start = sc->recv_ring + start_of_packet;
-       /*blen = -(start->md->md2);*/
-       blen = RECVBUFSIZE; /* XXX More PCnet-32 crap */
-       data = start->buff.data;
-       mbuf_data = m->m_data;
-
-       while (start_of_packet != sc->recv_next) {
-               /*
-                * If the data left fits in a single buffer then set
-                * blen to the size of the data left.
-                */
-               if (pkt_len < blen)
-                       blen = pkt_len;
-
-               /*
-                * amount is least of data in current ring buffer and
-                * amount of space left in current mbuf.
-                */
-               amount = min(blen, M_TRAILINGSPACE(m));
-               if (amount == 0) {
-                       /* mbuf must be empty */
-                       m_prev = m;
-                       m = m_getl(pkt_len, MB_DONTWAIT, MT_DATA, 0, NULL);
-                       if (m == NULL) {
-                               m_freem(head);
-                               return (0);
-                       }
-                       m->m_len = 0;
-                       m_prev->m_next = m;
-                       amount = min(blen, M_TRAILINGSPACE(m));
-                       mbuf_data = m->m_data;
-               }
-               bcopy(data, mbuf_data, amount);
-               blen -= amount;
-               pkt_len -= amount;
-               m->m_len += amount;
-               data += amount;
-               mbuf_data += amount;
-
-               if (blen == 0) {
-                       start->md->md1 &= HADR;
-                       start->md->md1 |= OWN;
-                       start->md->md2 = -RECVBUFSIZE; /* XXX - shouldn't be necessary */
-                       INC_MD_PTR(start_of_packet, sc->nrdre)
-                       start = sc->recv_ring + start_of_packet;
-                       data = start->buff.data;
-                       /*blen = -(start->md->md2);*/
-                       blen = RECVBUFSIZE; /* XXX More PCnet-32 crap */
-               }
-       }
-       return(head);
-}
-
-
-static void
-lnc_rint(struct lnc_softc *sc)
-{
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       struct host_ring_entry *next, *start;
-       int start_of_packet;
-       struct mbuf *head;
-       struct ether_header *eh;
-       int lookahead;
-       int flags;
-       int pkt_len;
-
-       /*
-        * The LANCE will issue a RINT interrupt when the ownership of the
-        * last buffer of a receive packet has been relinquished by the LANCE.
-        * Therefore, it can be assumed that a complete packet can be found
-        * before hitting buffers that are still owned by the LANCE, if not
-        * then there is a bug in the driver that is causing the descriptors
-        * to get out of sync.
-        */
-
-#ifdef DIAGNOSTIC
-       if ((sc->recv_ring + sc->recv_next)->md->md1 & OWN) {
-               int unit = ifp->if_dunit;
-               log(LOG_ERR, "lnc%d: Receive interrupt with buffer still owned by controller -- Resetting\n", unit);
-               lnc_reset(sc);
-               return;
-       }
-       if (!((sc->recv_ring + sc->recv_next)->md->md1 & STP)) {
-               int unit = ifp->if_dunit;
-               log(LOG_ERR, "lnc%d: Receive interrupt but not start of packet -- Resetting\n", unit);
-               lnc_reset(sc);
-               return;
-       }
-#endif
-
-       lookahead = 0;
-       next = sc->recv_ring + sc->recv_next;
-       while ((flags = next->md->md1) & STP) {
-
-               /* Make a note of the start of the packet */
-               start_of_packet = sc->recv_next;
-
-               /*
-                * Find the end of the packet. Even if not data chaining,
-                * jabber packets can overrun into a second descriptor.
-                * If there is no error, then the ENP flag is set in the last
-                * descriptor of the packet. If there is an error then the ERR
-                * flag will be set in the descriptor where the error occured.
-                * Therefore, to find the last buffer of a packet we search for
-                * either ERR or ENP.
-                */
-
-               if (!(flags & (ENP | MDERR))) {
-                       do {
-                               INC_MD_PTR(sc->recv_next, sc->nrdre)
-                               next = sc->recv_ring + sc->recv_next;
-                               flags = next->md->md1;
-                       } while (!(flags & (STP | OWN | ENP | MDERR)));
-
-                       if (flags & STP) {
-                               int unit = ifp->if_dunit;
-                               log(LOG_ERR, "lnc%d: Start of packet found before end of previous in receive ring -- Resetting\n", unit);
-                               lnc_reset(sc);
-                               return;
-                       }
-                       if (flags & OWN) {
-                               if (lookahead) {
-                                       /*
-                                        * Looked ahead into a packet still
-                                        * being received
-                                        */
-                                       sc->recv_next = start_of_packet;
-                                       break;
-                               } else {
-                                       int unit = ifp->if_dunit;
-                                       log(LOG_ERR, "lnc%d: End of received packet not found-- Resetting\n", unit);
-                                       lnc_reset(sc);
-                                       return;
-                               }
-                       }
-               }
-
-               pkt_len = (next->md->md3 & MCNT) - FCS_LEN;
-
-               /* Move pointer onto start of next packet */
-               INC_MD_PTR(sc->recv_next, sc->nrdre)
-               next = sc->recv_ring + sc->recv_next;
-
-               if (flags & MDERR) {
-                       int unit = ifp->if_dunit;
-                       if (flags & RBUFF) {
-                               LNCSTATS(rbuff)
-                               log(LOG_ERR, "lnc%d: Receive buffer error\n", unit);
-                       }
-                       if (flags & OFLO) {
-                               /* OFLO only valid if ENP is not set */
-                               if (!(flags & ENP)) {
-                                       LNCSTATS(oflo)
-                                       log(LOG_ERR, "lnc%d: Receive overflow error \n", unit);
-                               }
-                       } else if (flags & ENP) {
-                           if ((ifp->if_flags & IFF_PROMISC)==0) {
-                               /*
-                                * FRAM and CRC are valid only if ENP
-                                * is set and OFLO is not.
-                                */
-                               if (flags & FRAM) {
-                                       LNCSTATS(fram)
-                                       log(LOG_ERR, "lnc%d: Framing error\n", unit);
-                                       /*
-                                        * FRAM is only set if there's a CRC
-                                        * error so avoid multiple messages
-                                        */
-                               } else if (flags & CRC) {
-                                       LNCSTATS(crc)
-                                       log(LOG_ERR, "lnc%d: Receive CRC error\n", unit);
-                               }
-                           }
-                       }
-
-                       /* Drop packet */
-                       LNCSTATS(rerr)
-                       ifp->if_ierrors++;
-                       while (start_of_packet != sc->recv_next) {
-                               start = sc->recv_ring + start_of_packet;
-                               start->md->md2 = -RECVBUFSIZE; /* XXX - shouldn't be necessary */
-                               start->md->md1 &= HADR;
-                               start->md->md1 |= OWN;
-                               INC_MD_PTR(start_of_packet, sc->nrdre)
-                       }
-               } else { /* Valid packet */
-
-                       ifp->if_ipackets++;
-
-
-                       if (sc->nic.mem_mode == DMA_MBUF)
-                               head = chain_mbufs(sc, start_of_packet, pkt_len);
-                       else
-                               head = mbuf_packet(sc, start_of_packet, pkt_len);
-
-                       if (head) {
-                               /*
-                                * First mbuf in packet holds the
-                                * ethernet and packet headers
-                                */
-                               head->m_pkthdr.rcvif = ifp;
-                               head->m_pkthdr.len = pkt_len ;
-                               eh = mtod(head, struct ether_header *);
-
-                               /*
-                                * vmware ethernet hardware emulation loops
-                                * packets back to itself, violates IFF_SIMPLEX.
-                                * drop it if it is from myself.
-                               */
-                               if (bcmp(eh->ether_shost,
-                                     sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) == 0) {
-                                   m_freem(head);
-                               } else {
-                                       ifp->if_input(ifp, head);
-                               }
-                       } else {
-                               int unit = ifp->if_dunit;
-                               log(LOG_ERR,"lnc%d: Packet dropped, no mbufs\n",unit);
-                               LNCSTATS(drop_packet)
-                       }
-               }
-
-               lookahead++;
-       }
-
-       /*
-        * At this point all completely received packets have been processed
-        * so clear RINT since any packets that have arrived while we were in
-        * here have been dealt with.
-        */
-
-       lnc_outw(sc->rdp, RINT | INEA);
-}
-
-static void
-lnc_tint(struct lnc_softc *sc)
-{
-       struct host_ring_entry *next, *start;
-       int start_of_packet;
-       int lookahead;
-
-       /*
-        * If the driver is reset in this routine then we return immediately to
-        * the interrupt driver routine. Any interrupts that have occured
-        * since the reset will be dealt with there. sc->trans_next
-        * should point to the start of the first packet that was awaiting
-        * transmission after the last transmit interrupt was dealt with. The
-        * LANCE should have relinquished ownership of that descriptor before
-        * the interrupt. Therefore, sc->trans_next should point to a
-        * descriptor with STP set and OWN cleared. If not then the driver's
-        * pointers are out of sync with the LANCE, which signifies a bug in
-        * the driver. Therefore, the following two checks are really
-        * diagnostic, since if the driver is working correctly they should
-        * never happen.
-        */
-
-#ifdef DIAGNOSTIC
-       if ((sc->trans_ring + sc->trans_next)->md->md1 & OWN) {
-               int unit = sc->arpcom.ac_if.if_dunit;
-               log(LOG_ERR, "lnc%d: Transmit interrupt with buffer still owned by controller -- Resetting\n", unit);
-               lnc_reset(sc);
-               return;
-       }
-#endif
-
-
-       /*
-        * The LANCE will write the status information for the packet it just
-        * tried to transmit in one of two places. If the packet was
-        * transmitted successfully then the status will be written into the
-        * last descriptor of the packet. If the transmit failed then the
-        * status will be written into the descriptor that was being accessed
-        * when the error occured and all subsequent descriptors in that
-        * packet will have been relinquished by the LANCE.
-        *
-        * At this point we know that sc->trans_next points to the start
-        * of a packet that the LANCE has just finished trying to transmit.
-        * We now search for a buffer with either ENP or ERR set.
-        */
-
-       lookahead = 0;
-
-       do {
-               start_of_packet = sc->trans_next;
-               next = sc->trans_ring + sc->trans_next;
-
-#ifdef DIAGNOSTIC
-       if (!(next->md->md1 & STP)) {
-               int unit = sc->arpcom.ac_if.if_dunit;
-               log(LOG_ERR, "lnc%d: Transmit interrupt but not start of packet -- Resetting\n", unit);
-               lnc_reset(sc);
-               return;
-       }
-#endif
-
-               /*
-                * Find end of packet.
-                */
-
-               if (!(next->md->md1 & (ENP | MDERR))) {
-                       do {
-                               INC_MD_PTR(sc->trans_next, sc->ntdre)
-                               next = sc->trans_ring + sc->trans_next;
-                       } while (!(next->md->md1 & (STP | OWN | ENP | MDERR)));
-
-                       if (next->md->md1 & STP) {
-                               int unit = sc->arpcom.ac_if.if_dunit;
-                               log(LOG_ERR, "lnc%d: Start of packet found before end of previous in transmit ring -- Resetting\n", unit);
-                               lnc_reset(sc);
-                               return;
-                       }
-                       if (next->md->md1 & OWN) {
-                               if (lookahead) {
-                                       /*
-                                        * Looked ahead into a packet still
-                                        * being transmitted
-                                        */
-                                       sc->trans_next = start_of_packet;
-                                       break;
-                               } else {
-                                       int unit = sc->arpcom.ac_if.if_dunit;
-                                       log(LOG_ERR, "lnc%d: End of transmitted packet not found -- Resetting\n", unit);
-                                       lnc_reset(sc);
-                                       return;
-                               }
-                       }
-               }
-               /*
-                * Check for ERR first since other flags are irrelevant if an
-                * error occurred.
-                */
-               if (next->md->md1 & MDERR) {
-
-                       int unit = sc->arpcom.ac_if.if_dunit;
-
-                       LNCSTATS(terr)
-                               sc->arpcom.ac_if.if_oerrors++;
-
-                       if (next->md->md3 & LCOL) {
-                               LNCSTATS(lcol)
-                               log(LOG_ERR, "lnc%d: Transmit late collision  -- Net error?\n", unit);
-                               sc->arpcom.ac_if.if_collisions++;
-                               /*
-                                * Clear TBUFF since it's not valid when LCOL
-                                * set
-                                */
-                               next->md->md3 &= ~TBUFF;
-                       }
-                       if (next->md->md3 & LCAR) {
-                               LNCSTATS(lcar)
-                               log(LOG_ERR, "lnc%d: Loss of carrier during transmit -- Net error?\n", unit);
-                       }
-                       if (next->md->md3 & RTRY) {
-                               LNCSTATS(rtry)
-                               log(LOG_ERR, "lnc%d: Transmit of packet failed after 16 attempts -- TDR = %d\n", unit, ((sc->trans_ring + sc->trans_next)->md->md3 & TDR));
-                               sc->arpcom.ac_if.if_collisions += 16;
-                               /*
-                                * Clear TBUFF since it's not valid when RTRY
-                                * set
-                                */
-                               next->md->md3 &= ~TBUFF;
-                       }
-                       /*
-                        * TBUFF is only valid if neither LCOL nor RTRY are set.
-                        * We need to check UFLO after LCOL and RTRY so that we
-                        * know whether or not TBUFF is valid. If either are
-                        * set then TBUFF will have been cleared above. A
-                        * UFLO error will turn off the transmitter so we
-                        * have to reset.
-                        *
-                        */
-
-                       if (next->md->md3 & UFLO) {
-                               LNCSTATS(uflo)
-                               /*
-                                * If an UFLO has occured it's possibly due
-                                * to a TBUFF error
-                                */
-                               if (next->md->md3 & TBUFF) {
-                                       LNCSTATS(tbuff)
-                                       log(LOG_ERR, "lnc%d: Transmit buffer error -- Resetting\n", unit);
-                               } else
-                                       log(LOG_ERR, "lnc%d: Transmit underflow error -- Resetting\n", unit);
-                               lnc_reset(sc);
-                               return;
-                       }
-                       do {
-                               INC_MD_PTR(sc->trans_next, sc->ntdre)
-                               next = sc->trans_ring + sc->trans_next;
-                       } while (!(next->md->md1 & STP) && (sc->trans_next != sc->next_to_send));
-
-               } else {
-                       /*
-                        * Since we check for ERR first then if we get here
-                        * the packet was transmitted correctly. There may
-                        * still have been non-fatal errors though.
-                        * Don't bother checking for DEF, waste of time.
-                        */
-
-                       sc->arpcom.ac_if.if_opackets++;
-
-                       if (next->md->md1 & MORE) {
-                               LNCSTATS(more)
-                               sc->arpcom.ac_if.if_collisions += 2;
-                       }
-
-                       /*
-                        * ONE is invalid if LCOL is set. If LCOL was set then
-                        * ERR would have also been set and we would have
-                        * returned from lnc_tint above. Therefore we can
-                        * assume if we arrive here that ONE is valid.
-                        *
-                        */
-
-                       if (next->md->md1 & ONE) {
-                               LNCSTATS(one)
-                               sc->arpcom.ac_if.if_collisions++;
-                       }
-                       INC_MD_PTR(sc->trans_next, sc->ntdre)
-                       next = sc->trans_ring + sc->trans_next;
-               }
-
-               /*
-                * Clear descriptors and free any mbufs.
-                */
-
-               do {
-                       start = sc->trans_ring + start_of_packet;
-                       start->md->md1 &= HADR;
-                       if (sc->nic.mem_mode == DMA_MBUF) {
-                               /* Cache clusters on a local queue */
-                               if ((start->buff.mbuf->m_flags & M_EXT) && (sc->mbuf_count < MBUF_CACHE_LIMIT)) {
-                                       if (sc->mbuf_count) {
-                                               start->buff.mbuf->m_next = sc->mbufs;
-                                               sc->mbufs = start->buff.mbuf;
-                                       } else
-                                               sc->mbufs = start->buff.mbuf;
-                                       sc->mbuf_count++;
-                                       start->buff.mbuf = 0;
-                               } else {
-                                       m_free(start->buff.mbuf);
-                                       start->buff.mbuf = NULL;
-                               }
-                       }
-                       sc->pending_transmits--;
-                       INC_MD_PTR(start_of_packet, sc->ntdre)
-               }while (start_of_packet != sc->trans_next);
-
-               /*
-                * There's now at least one free descriptor
-                * in the ring so indicate that we can accept
-                * more packets again.
-                */
-
-               sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
-
-               lookahead++;
-
-       } while (sc->pending_transmits && !(next->md->md1 & OWN));
-
-       /*
-        * Clear TINT since we've dealt with all
-        * the completed transmissions.
-        */
-
-       lnc_outw(sc->rdp, TINT | INEA);
-}
-
-int
-lnc_attach_common(device_t dev)
-{
-       lnc_softc_t *sc = device_get_softc(dev);
-       struct ifnet *ifp = &sc->arpcom.ac_if;
-       int i;
-       int skip;
-
-       switch (sc->nic.ident) {
-       case BICC:
-       case CNET98S:
-               skip = 2;
-               break;
-       default:
-               skip = 1;
-               break;
-       }
-
-       /* Set default mode */
-       sc->nic.mode = NORMAL;
-
-       /* Fill in arpcom structure entries */
-
-       ifp->if_softc = sc;
-       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-       ifp->if_timer = 0;
-       ifp->if_start = lnc_start;
-       ifp->if_ioctl = lnc_ioctl;
-       ifp->if_watchdog = lnc_watchdog;
-       ifp->if_init = lnc_init;
-       ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
-       ifq_set_ready(&ifp->if_snd);
-
-       /* Extract MAC address from PROM */
-       for (i = 0; i < ETHER_ADDR_LEN; i++)
-               sc->arpcom.ac_enaddr[i] = lnc_inb(i * skip);
-
-       /*
-        * XXX -- should check return status of if_attach
-        */
-
-       ether_ifattach(&sc->arpcom.ac_if, sc->arpcom.ac_enaddr, NULL);
-
-       if (sc->nic.ic == LANCE || sc->nic.ic == C_LANCE)
-               if_printf(ifp, "%s (%s)", nic_ident[sc->nic.ident],
-                         ic_ident[sc->nic.ic]);
-       else
-               if_printf(ifp, "%s\n", ic_ident[sc->nic.ic]);
-
-       return (1);
-}
-
-static void
-lnc_init(void *xsc)
-{
-       struct lnc_softc *sc = xsc;
-       int i;
-       char *lnc_mem;
-
-       crit_enter();
-
-       /* Shut down interface */
-       lnc_stop(sc);
-       sc->arpcom.ac_if.if_flags |= IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; /* XXX??? */
-
-       /*
-        * This sets up the memory area for the controller. Memory is set up for
-        * the initialisation block (12 words of contiguous memory starting
-        * on a word boundary),the transmit and receive ring structures (each
-        * entry is 4 words long and must start on a quadword boundary) and
-        * the data buffers.
-        *
-        * The alignment tests are particularly paranoid.
-        */
-
-       sc->recv_next = 0;
-       sc->trans_ring = sc->recv_ring + NDESC(sc->nrdre);
-       sc->trans_next = 0;
-
-       if (sc->nic.mem_mode == SHMEM)
-               lnc_mem = (char *) sc->nic.iobase;
-       else
-               lnc_mem = (char *) (sc->trans_ring + NDESC(sc->ntdre));
-
-       lnc_mem = (char *)(((int)lnc_mem + 1) & ~1);
-       sc->init_block = (struct init_block *) ((int) lnc_mem & ~1);
-       lnc_mem = (char *) (sc->init_block + 1);
-       lnc_mem = (char *)(((int)lnc_mem + 7) & ~7);
-
-       /* Initialise pointers to descriptor entries */
-       for (i = 0; i < NDESC(sc->nrdre); i++) {
-               (sc->recv_ring + i)->md = (struct mds *) lnc_mem;
-               lnc_mem += sizeof(struct mds);
-       }
-       for (i = 0; i < NDESC(sc->ntdre); i++) {
-               (sc->trans_ring + i)->md = (struct mds *) lnc_mem;
-               lnc_mem += sizeof(struct mds);
-       }
-
-       /* Initialise the remaining ring entries */
-
-       if (sc->nic.mem_mode == DMA_MBUF) {
-
-               sc->mbufs = 0;
-               sc->mbuf_count = 0;
-
-               /* Free previously allocated mbufs */
-               if (sc->flags & LNC_INITIALISED)
-                       lnc_free_mbufs(sc);
-
-
-               for (i = 0; i < NDESC(sc->nrdre); i++) {
-                       if (alloc_mbuf_cluster(sc, sc->recv_ring+i)) {
-                               log(LOG_ERR, "Initialisation failed -- no mbufs\n");
-                               crit_exit();
-                               return;
-                       }
-               }
-
-               for (i = 0; i < NDESC(sc->ntdre); i++) {
-                       (sc->trans_ring + i)->buff.mbuf = 0;
-                       (sc->trans_ring + i)->md->md0 = 0;
-                       (sc->trans_ring + i)->md->md1 = 0;
-                       (sc->trans_ring + i)->md->md2 = 0;
-                       (sc->trans_ring + i)->md->md3 = 0;
-               }
-       } else {
-               for (i = 0; i < NDESC(sc->nrdre); i++) {
-                       (sc->recv_ring + i)->md->md0 = kvtop(lnc_mem);
-                       (sc->recv_ring + i)->md->md1 = ((kvtop(lnc_mem) >> 16) & 0xff) | OWN;
-                       (sc->recv_ring + i)->md->md2 = -RECVBUFSIZE;
-                       (sc->recv_ring + i)->md->md3 = 0;
-                       (sc->recv_ring + i)->buff.data = lnc_mem;
-                       lnc_mem += RECVBUFSIZE;
-               }
-               for (i = 0; i < NDESC(sc->ntdre); i++) {
-                       (sc->trans_ring + i)->md->md0 = kvtop(lnc_mem);
-                       (sc->trans_ring + i)->md->md1 = ((kvtop(lnc_mem) >> 16) & 0xff);
-                       (sc->trans_ring + i)->md->md2 = 0;
-                       (sc->trans_ring + i)->md->md3 = 0;
-                       (sc->trans_ring + i)->buff.data = lnc_mem;
-                       lnc_mem += TRANSBUFSIZE;
-               }
-       }
-
-       sc->next_to_send = 0;
-
-       /* Set up initialisation block */
-
-       sc->init_block->mode = sc->nic.mode;
-
-       for (i = 0; i < ETHER_ADDR_LEN; i++)
-               sc->init_block->padr[i] = sc->arpcom.ac_enaddr[i];
-
-       lnc_setladrf(sc);
-
-       sc->init_block->rdra = kvtop(sc->recv_ring->md);
-       sc->init_block->rlen = ((kvtop(sc->recv_ring->md) >> 16) & 0xff) | (sc->nrdre << 13);
-       sc->init_block->tdra = kvtop(sc->trans_ring->md);
-       sc->init_block->tlen = ((kvtop(sc->trans_ring->md) >> 16) & 0xff) | (sc->ntdre << 13);
-
-
-       /* Set flags to show that the memory area is valid */
-       sc->flags |= LNC_INITIALISED;
-
-       sc->pending_transmits = 0;
-
-       /* Give the LANCE the physical address of the initialisation block */
-
-       if (sc->nic.ic == PCnet_Home) {
-               u_short media;
-               /* Set PHY_SEL to HomeRun */
-               media = read_bcr(sc, BCR49);
-               media &= ~3;
-               media |= 1;
-               write_bcr(sc, BCR49, media);
-       }
-
-       write_csr(sc, CSR1, kvtop(sc->init_block));
-       write_csr(sc, CSR2, (kvtop(sc->init_block) >> 16) & 0xff);
-
-       /*
-        * Depending on which controller this is, CSR3 has different meanings.
-        * For the Am7990 it controls DMA operations, for the Am79C960 it
-        * controls interrupt masks and transmitter algorithms. In either
-        * case, none of the flags are set.
-        *
-        */
-
-       write_csr(sc, CSR3, 0);
-
-       /* Let's see if it starts */
-/*
-printf("Enabling lnc interrupts\n");
-       sc->arpcom.ac_if.if_timer = 10;
-       write_csr(sc, CSR0, INIT|INEA);
-*/
-
-       /*
-        * Now that the initialisation is complete there's no reason to
-        * access anything except CSR0, so we leave RAP pointing there
-        * so we can just access RDP from now on, saving an outw each
-        * time.
-        */
-
-       write_csr(sc, CSR0, INIT);
-       for(i=0; i < 1000; i++)
-               if (read_csr(sc, CSR0) & IDON)
-                       break;
-
-       if (read_csr(sc, CSR0) & IDON) {
-               /*
-                * Enable interrupts, start the LANCE, mark the interface as
-                * running and transmit any pending packets.
-                */
-               write_csr(sc, CSR0, STRT | INEA);
-               sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
-               sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
-               lnc_start(&sc->arpcom.ac_if);
-       } else
-               log(LOG_ERR, "%s: Initialisation failed\n", 
-                   sc->arpcom.ac_if.if_xname);
-
-       crit_exit();
-}
-
-/*
- * The interrupt flag (INTR) will be set and provided that the interrupt enable
- * flag (INEA) is also set, the interrupt pin will be driven low when any of
- * the following occur:
- *
- * 1) Completion of the initialisation routine (IDON). 2) The reception of a
- * packet (RINT). 3) The transmission of a packet (TINT). 4) A transmitter
- * timeout error (BABL). 5) A missed packet (MISS). 6) A memory error (MERR).
- *
- * The interrupt flag is cleared when all of the above conditions are cleared.
- *
- * If the driver is reset from this routine then it first checks to see if any
- * interrupts have ocurred since the reset and handles them before returning.
- * This is because the NIC may signify a pending interrupt in CSR0 using the
- * INTR flag even if a hardware interrupt is currently inhibited (at least I
- * think it does from reading the data sheets). We may as well deal with
- * these pending interrupts now rather than get the overhead of another
- * hardware interrupt immediately upon returning from the interrupt handler.
- *
- */
-
-void
-lncintr(void *arg)
-{
-       lnc_softc_t *sc = arg;
-       int unit = sc->arpcom.ac_if.if_dunit;
-       u_short csr0;
-
-       /*
-        * INEA is the only bit that can be cleared by writing a 0 to it so
-        * we have to include it in any writes that clear other flags.
-        */
-
-       while ((csr0 = lnc_inw(sc->rdp)) & INTR) {
-
-               /*
-                * Clear interrupt flags early to avoid race conditions. The
-                * controller can still set these flags even while we're in
-                * this interrupt routine. If the flag is still set from the
-                * event that caused this interrupt any new events will
-                * be missed.
-                */
-
-               lnc_outw(sc->rdp, csr0);
-               /*lnc_outw(sc->rdp, IDON | CERR | BABL | MISS | MERR | RINT | TINT | INEA);*/
-
-#ifdef notyet
-               if (csr0 & IDON) {
-printf("IDON\n");
-                       sc->arpcom.ac_if.if_timer = 0;
-                       write_csr(sc, CSR0, STRT | INEA);
-                       sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
-                       sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
-                       lnc_start(&sc->arpcom.ac_if);
-                       continue;
-               }
-#endif
-
-               if (csr0 & ERR) {
-                       if (csr0 & CERR) {
-                               log(LOG_ERR, "lnc%d: Heartbeat error -- SQE test failed\n", unit);
-                               LNCSTATS(cerr)
-                       }
-                       if (csr0 & BABL) {
-                               log(LOG_ERR, "lnc%d: Babble error - more than 1519 bytes transmitted\n", unit);
-                               LNCSTATS(babl)
-                               sc->arpcom.ac_if.if_oerrors++;
-                       }
-                       if (csr0 & MISS) {
-                               log(LOG_ERR, "lnc%d: Missed packet -- no receive buffer\n", unit);
-                               LNCSTATS(miss)
-                               sc->arpcom.ac_if.if_ierrors++;
-                       }
-                       if (csr0 & MERR) {
-                               log(LOG_ERR, "lnc%d: Memory error  -- Resetting\n", unit);
-                               LNCSTATS(merr)
-                               lnc_reset(sc);
-                               continue;
-                       }
-               }
-               if (csr0 & RINT) {
-                       LNCSTATS(rint)
-                       lnc_rint(sc);
-               }
-               if (csr0 & TINT) {
-                       LNCSTATS(tint)
-                       sc->arpcom.ac_if.if_timer = 0;
-                       lnc_tint(sc);
-               }
-
-               /*
-                * If there's room in the transmit descriptor ring then queue
-                * some more transmit packets.
-                */
-
-               if (!(sc->arpcom.ac_if.if_flags & IFF_OACTIVE))
-                       lnc_start(&sc->arpcom.ac_if);
-       }
-}
-
-static __inline int
-mbuf_to_buffer(struct mbuf *m, char *buffer)
-{
-
-       int len=0;
-
-       for( ; m; m = m->m_next) {
-               bcopy(mtod(m, caddr_t), buffer, m->m_len);
-               buffer += m->m_len;
-               len += m->m_len;
-       }
-
-       return(len);
-}
-
-static __inline struct mbuf *
-chain_to_cluster(struct mbuf *m)
-{
-       struct mbuf *new;
-
-       new = m_getcl(MB_DONTWAIT, MT_DATA, 0);
-       if (new == NULL)
-               return (0);
-       new->m_len = mbuf_to_buffer(m, new->m_data);
-       m_freem(m);
-       return (new);
-}
-
-/*
- * IFF_OACTIVE and IFF_RUNNING are checked in ether_output so it's redundant
- * to check them again since we wouldn't have got here if they were not
- * appropriately set. This is also called from lnc_init and lncintr but the
- * flags should be ok at those points too.
- */
-
-static void
-lnc_start(struct ifnet *ifp)
-{
-
-       struct lnc_softc *sc = ifp->if_softc;
-       struct host_ring_entry *desc;
-       int tmp;
-       int end_of_packet;
-       struct mbuf *head, *m;
-       int len, chunk;
-       int addr;
-       int no_entries_needed;
-
-       do {
-               head = ifq_dequeue(&sc->arpcom.ac_if.if_snd, NULL);
-               if (head == NULL)
-                       return;
-
-               if (sc->nic.mem_mode == DMA_MBUF) {
-
-                       no_entries_needed = 0;
-                       for (m=head; m; m = m->m_next)
-                               no_entries_needed++;
-
-                       /*
-                        * We try and avoid bcopy as much as possible
-                        * but there are two cases when we use it.
-                        *
-                        * 1) If there are not enough free entries in the ring
-                        * to hold each mbuf in the chain then compact the
-                        * chain into a single cluster.
-                        *
-                        * 2) The Am7990 and Am79C90 must not have less than
-                        * 100 bytes in the first descriptor of a chained
-                        * packet so it's necessary to shuffle the mbuf
-                        * contents to ensure this.
-                        */
-
-
-                       if (no_entries_needed > (NDESC(sc->ntdre) - sc->pending_transmits)) {
-                               if (!(head = chain_to_cluster(head))) {
-                                       log(LOG_ERR, "%s: Couldn't get mbuf for transmit packet -- Resetting \n ",ifp->if_xname);
-                                       lnc_reset(sc);
-                                       return;
-                               }
-                       } else if ((sc->nic.ic == LANCE) || (sc->nic.ic == C_LANCE)) {
-                               if ((head->m_len < 100) && (head->m_next)) {
-                                       len = 100 - head->m_len;
-                                       if (M_TRAILINGSPACE(head) < len) {
-                                               /*
-                                                * Move data to start of data
-                                                * area. We assume the first
-                                                * mbuf has a packet header
-                                                * and is not a cluster.
-                                                */
-                                               bcopy((caddr_t)head->m_data, (caddr_t)head->m_pktdat, head->m_len);
-                                               head->m_data = head->m_pktdat;
-                                       }
-                                       m = head->m_next;
-                                       while (m && (len > 0)) {
-                                               chunk = min(len, m->m_len);
-                                               bcopy(mtod(m, caddr_t), mtod(head, caddr_t) + head->m_len, chunk);
-                                               len -= chunk;
-                                               head->m_len += chunk;
-                                               m->m_len -= chunk;
-                                               m->m_data += chunk;
-                                               if (m->m_len <= 0) {
-                                                       m = m_free(m);
-                                                       head->m_next = m;
-                                               }
-                                       }
-                               }
-                       }
-
-                       tmp = sc->next_to_send;
-
-                       /*
-                        * On entering this loop we know that tmp points to a
-                        * descriptor with a clear OWN bit.
-                        */
-
-                       desc = sc->trans_ring + tmp;
-                       len = ETHER_MIN_LEN;
-                       for (m = head; m; m = m->m_next) {
-                               desc->buff.mbuf = m;
-                               addr = kvtop(m->m_data);
-                               desc->md->md0 = addr;
-                               desc->md->md1 = ((addr >> 16) & 0xff);
-                               desc->md->md3 = 0;
-                               desc->md->md2 = -m->m_len;
-                               sc->pending_transmits++;
-                               len -= m->m_len;
-
-                               INC_MD_PTR(tmp, sc->ntdre)
-                               desc = sc->trans_ring + tmp;
-                       }
-
-                       end_of_packet = tmp;
-                       DEC_MD_PTR(tmp, sc->ntdre)
-                       desc = sc->trans_ring + tmp;
-                       desc->md->md1 |= ENP;
-
-                       if (len > 0)
-                               desc->md->md2 -= len;
-
-                       /*
-                        * Set OWN bits in reverse order, otherwise the Lance
-                        * could start sending the packet before all the
-                        * buffers have been relinquished by the host.
-                        */
-
-                       while (tmp != sc->next_to_send) {
-                               desc->md->md1 |= OWN;
-                               DEC_MD_PTR(tmp, sc->ntdre)
-                               desc = sc->trans_ring + tmp;
-                       }
-                       sc->next_to_send = end_of_packet;
-                       desc->md->md1 |= STP | OWN;
-               } else {
-                       sc->pending_transmits++;
-                       desc = sc->trans_ring + sc->next_to_send;
-                       len = mbuf_to_buffer(head, desc->buff.data);
-                       desc->md->md3 = 0;
-                       desc->md->md2 = -max(len, ETHER_MIN_LEN - ETHER_CRC_LEN);
-                       desc->md->md1 |= OWN | STP | ENP;
-                       INC_MD_PTR(sc->next_to_send, sc->ntdre)
-               }
-
-               /* Force an immediate poll of the transmit ring */
-               lnc_outw(sc->rdp, TDMD | INEA);
-
-               /*
-                * Set a timer so if the buggy Am7990.h shuts
-                * down we can wake it up.
-                */
-
-               ifp->if_timer = 2;
-
-               BPF_MTAP(&sc->arpcom.ac_if, head);
-
-               if (sc->nic.mem_mode != DMA_MBUF)
-                       m_freem(head);
-
-       } while (sc->pending_transmits < NDESC(sc->ntdre));
-
-       /*
-        * Transmit ring is full so set IFF_OACTIVE
-        * since we can't buffer any more packets.
-        */
-
-       sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
-       LNCSTATS(trans_ring_full)
-}
-
-static int
-lnc_ioctl(struct ifnet * ifp, u_long command, caddr_t data, struct ucred *cr)
-{
-
-       struct lnc_softc *sc = ifp->if_softc;
-       int error = 0;
-
-       crit_enter();
-
-       switch (command) {
-       case SIOCSIFFLAGS:
-#ifdef DEBUG
-               if (ifp->if_flags & IFF_DEBUG)
-                       sc->lnc_debug = 1;
-               else
-                       sc->lnc_debug = 0;
-#endif
-               if (ifp->if_flags & IFF_PROMISC) {
-                       if (!(sc->nic.mode & PROM)) {
-                               sc->nic.mode |= PROM;
-                               lnc_init(sc);
-                       }
-               } else if (sc->nic.mode & PROM) {
-                       sc->nic.mode &= ~PROM;
-                       lnc_init(sc);
-               }
-
-               if ((ifp->if_flags & IFF_ALLMULTI) &&
-                   !(sc->flags & LNC_ALLMULTI)) {
-                       sc->flags |= LNC_ALLMULTI;
-                       lnc_init(sc);
-               } else if (!(ifp->if_flags & IFF_ALLMULTI) &&
-                           (sc->flags & LNC_ALLMULTI)) {
-                       sc->flags &= ~LNC_ALLMULTI;
-                       lnc_init(sc);
-               }
-
-               if ((ifp->if_flags & IFF_UP) == 0 &&
-                   (ifp->if_flags & IFF_RUNNING) != 0) {
-                       /*
-                        * If interface is marked down and it is running,
-                        * then stop it.
-                        */
-                       lnc_stop(sc);
-                       ifp->if_flags &= ~IFF_RUNNING;
-               } else if ((ifp->if_flags & IFF_UP) != 0 &&
-                          (ifp->if_flags & IFF_RUNNING) == 0) {
-                       /*
-                        * If interface is marked up and it is stopped, then
-                        * start it.
-                        */
-                       lnc_init(sc);
-               }
-               break;
-       case SIOCADDMULTI:
-       case SIOCDELMULTI:
-               lnc_init(sc);
-               error = 0;
-               break;
-       default:
-                error = ether_ioctl(ifp, command, data);
-                break;
-       }
-
-       crit_exit();
-
-       return error;
-}
-
-static void
-lnc_watchdog(struct ifnet *ifp)
-{
-       log(LOG_ERR, "%s: Device timeout -- Resetting\n", ifp->if_xname);
-       ifp->if_oerrors++;
-       lnc_reset(ifp->if_softc);
-}
-
-#ifdef DEBUG
-void
-lnc_dump_state(struct lnc_softc *sc)
-{
-       int             i;
-
-       printf("\nDriver/NIC [%d] state dump\n", sc->arpcom.ac_if.if_dunit);
-       printf("Memory access mode: %b\n", sc->nic.mem_mode, MEM_MODES);
-       printf("Host memory\n");
-       printf("-----------\n");
-
-       printf("Receive ring: base = %p, next = %p\n",
-           (void *)sc->recv_ring, (void *)(sc->recv_ring + sc->recv_next));
-       for (i = 0; i < NDESC(sc->nrdre); i++)
-               printf("\t%d:%p md = %p buff = %p\n",
-                   i, (void *)(sc->recv_ring + i),
-                   (void *)(sc->recv_ring + i)->md,
-                   (void *)(sc->recv_ring + i)->buff.data);
-
-       printf("Transmit ring: base = %p, next = %p\n",
-           (void *)sc->trans_ring, (void *)(sc->trans_ring + sc->trans_next));
-       for (i = 0; i < NDESC(sc->ntdre); i++)
-               printf("\t%d:%p md = %p buff = %p\n",
-                   i, (void *)(sc->trans_ring + i),
-                   (void *)(sc->trans_ring + i)->md,
-                   (void *)(sc->trans_ring + i)->buff.data);
-       printf("Lance memory (may be on host(DMA) or card(SHMEM))\n");
-       printf("Init block = %p\n", (void *)sc->init_block);
-       printf("\tmode = %b rlen:rdra = %x:%x tlen:tdra = %x:%x\n",
-           sc->init_block->mode, INIT_MODE, sc->init_block->rlen,
-         sc->init_block->rdra, sc->init_block->tlen, sc->init_block->tdra);
-       printf("Receive descriptor ring\n");
-       for (i = 0; i < NDESC(sc->nrdre); i++)
-               printf("\t%d buffer = 0x%x%x, BCNT = %d,\tMCNT = %u,\tflags = %b\n",
-                   i, ((sc->recv_ring + i)->md->md1 & HADR),
-                   (sc->recv_ring + i)->md->md0,
-                   -(short) (sc->recv_ring + i)->md->md2,
-                   (sc->recv_ring + i)->md->md3,
-                   (((sc->recv_ring + i)->md->md1 & ~HADR) >> 8), RECV_MD1);
-       printf("Transmit descriptor ring\n");
-       for (i = 0; i < NDESC(sc->ntdre); i++)
-               printf("\t%d buffer = 0x%x%x, BCNT = %d,\tflags = %b %b\n",
-                   i, ((sc->trans_ring + i)->md->md1 & HADR),
-                   (sc->trans_ring + i)->md->md0,
-                   -(short) (sc->trans_ring + i)->md->md2,
-                   ((sc->trans_ring + i)->md->md1 >> 8), TRANS_MD1,
-                   ((sc->trans_ring + i)->md->md3 >> 10), TRANS_MD3);
-       printf("\nnext_to_send = %x\n", sc->next_to_send);
-       printf("\n CSR0 = %b CSR1 = %x CSR2 = %x CSR3 = %x\n\n",
-           read_csr(sc, CSR0), CSR0_FLAGS, read_csr(sc, CSR1),
-           read_csr(sc, CSR2), read_csr(sc, CSR3));
-
-       /* Set RAP back to CSR0 */
-       lnc_outw(sc->rap, CSR0);
-}
-
-void
-mbuf_dump_chain(struct mbuf * m)
-{
-
-#define MBUF_FLAGS \
-       "\20\1M_EXT\2M_PKTHDR\3M_EOR\4UNKNOWN\5M_BCAST\6M_MCAST"
-
-       if (!m)
-               log(LOG_DEBUG, "m == NULL\n");
-       do {
-               log(LOG_DEBUG, "m = %p\n", (void *)m);
-               log(LOG_DEBUG, "m_hdr.mh_next = %p\n",
-                   (void *)m->m_hdr.mh_next);
-               log(LOG_DEBUG, "m_hdr.mh_nextpkt = %p\n",
-                   (void *)m->m_hdr.mh_nextpkt);
-               log(LOG_DEBUG, "m_hdr.mh_len = %d\n", m->m_hdr.mh_len);
-               log(LOG_DEBUG, "m_hdr.mh_data = %p\n",
-                   (void *)m->m_hdr.mh_data);
-               log(LOG_DEBUG, "m_hdr.mh_type = %d\n", m->m_hdr.mh_type);
-               log(LOG_DEBUG, "m_hdr.mh_flags = %b\n", m->m_hdr.mh_flags,
-                   MBUF_FLAGS);
-               if (!(m->m_hdr.mh_flags & (M_PKTHDR | M_EXT)))
-                       log(LOG_DEBUG, "M_dat.M_databuf = %p\n",
-                           (void *)m->M_dat.M_databuf);
-               else {
-                       if (m->m_hdr.mh_flags & M_PKTHDR) {
-                               log(LOG_DEBUG, "M_dat.MH.MH_pkthdr.len = %d\n",
-                                   m->M_dat.MH.MH_pkthdr.len);
-                               log(LOG_DEBUG,
-                                   "M_dat.MH.MH_pkthdr.rcvif = %p\n",
-                                   (void *)m->M_dat.MH.MH_pkthdr.rcvif);
-                               if (!(m->m_hdr.mh_flags & M_EXT))
-                                       log(LOG_DEBUG,
-                                           "M_dat.MH.MH_dat.MH_databuf = %p\n",
-                                       (void *)m->M_dat.MH.MH_dat.MH_databuf);
-                       }
-                       if (m->m_hdr.mh_flags & M_EXT) {
-                               log(LOG_DEBUG,
-                                   "M_dat.MH.MH_dat.MH_ext.ext_buff %p\n",
-                                   (void *)m->M_dat.MH.MH_dat.MH_ext.ext_buf);
-                               log(LOG_DEBUG,
-                                   "M_dat.MH.MH_dat.MH_ext.ext_free %p\n",
-                                   (void *)m->M_dat.MH.MH_dat.MH_ext.ext_free);
-                               log(LOG_DEBUG,
-                                   "M_dat.MH.MH_dat.MH_ext.ext_size %d\n",
-                                   m->M_dat.MH.MH_dat.MH_ext.ext_size);
-                       }
-               }
-       } while ((m = m->m_next) != NULL);
-}
-#endif
diff --git a/sys/dev/netif/lnc/if_lnc.h b/sys/dev/netif/lnc/if_lnc.h
deleted file mode 100644 (file)
index de8259f..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*-
- * Copyright (c) 1994-1998
- *      Paul Richards.  All rights reserved.
- *
- * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Paul Richards.
- * 4. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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: src/sys/i386/isa/if_lnc.h,v 1.14.2.1 2000/06/18 08:03:51 gj Exp $
- * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lnc.h,v 1.3 2005/09/01 00:18:24 swildner Exp $
- */
-
-#include <i386/isa/ic/Am7990.h>
-
-/*
- * Initialize multicast address hashing registers to accept
- * all multicasts (only used when in promiscuous mode)
- */
-#define MULTI_INIT_ADDR 0xff
-
-#define NORMAL 0
-
-#define NRDRE 3
-#define NTDRE 3
-#define RECVBUFSIZE 1518       /* Packet size rounded to dword boundary */
-#define TRANSBUFSIZE 1518
-#define MBUF_CACHE_LIMIT 0
-
-#define MEM_SLEW 8
-
-/* LNC Flags */
-#define LNC_INITIALISED 1
-#define LNC_ALLMULTI 2
-
-/* BICC port addresses */
-#define BICC_IOSIZE    16
-#define BICC_RDP     0x0c        /* Register Data Port */
-#define BICC_RAP     0x0e        /* Register Address Port */
-
-/* NE2100 port addresses */
-#define NE2100_IOSIZE  24
-#define PCNET_RDP    0x10        /* Register Data Port */
-#define PCNET_RAP    0x12        /* Register Address Port */
-#define PCNET_RESET  0x14
-#define PCNET_BDP    0x16
-#define PCNET_VSW    0x18
-
-/* DEPCA port addresses */
-#define DEPCA_IOSIZE   16
-#define DEPCA_CTRL   0x00        /* NIC Control and status register */
-#define DEPCA_RDP    0x04        /* Register Data Port */
-#define DEPCA_RAP    0x06        /* Register Address Port */
-#define DEPCA_ADP    0x0c
-
-/* DEPCA specific defines */
-#define DEPCA_ADDR_ROM_SIZE 32
-
-/* Chip types */
-#define LANCE           1        /* Am7990   */
-#define C_LANCE         2        /* Am79C90  */
-#define PCnet_ISA       3        /* Am79C960 */
-#define PCnet_ISAplus   4        /* Am79C961 */
-#define PCnet_ISA_II    5        /* Am79C961A */
-#define PCnet_32        6        /* Am79C965 */
-#define PCnet_PCI       7        /* Am79C970 */
-#define PCnet_PCI_II    8        /* Am79C970A */
-#define PCnet_FAST      9        /* Am79C971 */
-#define PCnet_FASTplus  10       /* Am79C972 */
-#define PCnet_Home     11       /* Am79C978 */
-
-
-/* CSR88-89: Chip ID masks */
-#define AMD_MASK  0x003
-#define PART_MASK 0xffff
-#define Am79C960  0x0003
-#define Am79C961  0x2260
-#define Am79C961A 0x2261
-#define Am79C965  0x2430
-#define Am79C970  0x0242
-#define Am79C970A 0x2621
-#define Am79C971  0x2623
-#define Am79C972  0x2624
-#define Am79C973  0x2625
-#define Am79C978  0x2626
-
-/* Board types */
-#define UNKNOWN         0
-#define BICC            1
-#define NE2100          2
-#define DEPCA           3
-
-/* mem_mode values */
-#define DMA_FIXED       1
-#define DMA_MBUF        2
-#define SHMEM           4
-
-#define MEM_MODES \
-       "\20\3SHMEM\2DMA_MBUF\1DMA_FIXED"
-
-#define CSR0_FLAGS \
-       "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\
-           \10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
-
-#define INIT_MODE \
-       "\20\20PROM\07INTL\06DRTY\05COLL\04DTCR\03LOOP\02DTX\01DRX"
-
-#define RECV_MD1 \
-       "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
-
-#define TRANS_MD1 \
-       "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
-
-#define TRANS_MD3 \
-       "\20\6BUFF\5UFLO\4RES\3LCOL\2LCAR\1RTRY"
-
-struct nic_info {
-       int ident;         /* Type of card */
-       int ic;            /* Type of ic, Am7990, Am79C960 etc. */
-       int mem_mode;
-       int iobase;
-       int mode;          /* Mode setting at initialization */
-};
-
-struct host_ring_entry {
-       struct mds *md;
-       union {
-               struct mbuf *mbuf;
-               char *data;
-       }buff;
-};
-
-#ifdef LNC_KEEP_STATS
-#define LNCSTATS_STRUCT \
-       struct lnc_stats { \
-               int idon; \
-               int rint; \
-               int tint; \
-               int cerr; \
-               int babl; \
-               int miss; \
-               int merr; \
-               int rxoff; \
-               int txoff; \
-               int terr; \
-               int lcol; \
-               int lcar; \
-               int tbuff; \
-               int def; \
-               int more; \
-               int one; \
-               int uflo; \
-               int rtry; \
-               int rerr; \
-               int fram; \
-               int oflo; \
-               int crc; \
-               int rbuff; \
-               int drop_packet; \
-               int trans_ring_full; \
-       } lnc_stats;
-#define LNCSTATS(X) ++(sc->lnc_stats.X);
-#else
-#define LNCSTATS_STRUCT
-#define LNCSTATS(X)
-#endif
-
-#define NDESC(len2) (1 << len2)
-
-#define INC_MD_PTR(ptr, no_entries) \
-       if (++ptr >= NDESC(no_entries)) \
-               ptr = 0;
-
-#define DEC_MD_PTR(ptr, no_entries) \
-       if (--ptr < 0) \
-               ptr = NDESC(no_entries) - 1;
-
-#define RECV_NEXT (sc->recv_ring->base + sc->recv_next)
-#define TRANS_NEXT (sc->trans_ring->base + sc->trans_next)
index 988c93c..2883e39 100644 (file)
@@ -1,24 +1,67 @@
-/*
- * Copyright (c) 1994-2000
- *     Paul Richards. All rights reserved.
+/*     $NetBSD: if_le_isa.c,v 1.41 2005/12/24 20:27:41 perry Exp $     */
+/*     $FreeBSD: src/sys/dev/le/if_le_isa.c,v 1.1 2006/05/17 21:25:22 marius Exp $     */
+/*     $DragonFly: src/sys/dev/netif/lnc/if_lnc_isa.c,v 1.9 2006/07/07 14:16:29 sephe Exp $    */
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
  *
  * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
+ *    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.
- * 3. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 PAUL RICHARDS BE LIABLE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/lnc/if_lnc_isa.c,v 1.12 2001/07/04 13:00:19 nyan Exp $
- * $DragonFly: src/sys/dev/netif/lnc/if_lnc_isa.c,v 1.8 2005/12/31 14:07:59 sephe Exp $
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/endian.h>
 #include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/socket.h>
-#include <sys/serialize.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/resource.h>
 #include <sys/rman.h>
-#include <sys/thread2.h>
+#include <sys/socket.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
+#include <net/if_media.h>
 #include <net/if_arp.h>
 
+#include <machine/bus.h>
+#include <machine/resource.h>
+
 #include <bus/isa/isavar.h>
 
-#include <dev/netif/lnc/if_lncvar.h>
-#include <dev/netif/lnc/if_lncreg.h>
+#include <dev/netif/lnc/lancereg.h>
+#include <dev/netif/lnc/lancevar.h>
+#include <dev/netif/lnc/am7990var.h>
+
+#define        LE_ISA_MEMSIZE  (16*1024)
+#define        PCNET_RDP       0x10
+#define        PCNET_RAP       0x12
+
+struct le_isa_softc {
+       struct am7990_softc     sc_am7990;      /* glue to MI code */
+
+       bus_size_t              sc_rap;         /* offsets to LANCE... */
+       bus_size_t              sc_rdp;         /* ...registers */
+
+       int                     sc_rrid;
+       struct resource         *sc_rres;
+       bus_space_tag_t         sc_regt;
+       bus_space_handle_t      sc_regh;
 
-static int     lnc_isa_detach(device_t);
+       int                     sc_drid;
+       struct resource         *sc_dres;
 
-static struct isa_pnp_id lnc_pnp_ids[] = {
-       {0,     NULL}
+       int                     sc_irid;
+       struct resource         *sc_ires;
+       void                    *sc_ih;
+
+       bus_dma_tag_t           sc_pdmat;
+       bus_dma_tag_t           sc_dmat;
+       bus_dmamap_t            sc_dmam;
 };
 
-static int
-lnc_legacy_probe(device_t dev)
-{
-       struct lnc_softc *sc = device_get_softc(dev);
+static device_probe_t le_isa_probe;
+static device_attach_t le_isa_attach;
+static device_detach_t le_isa_detach;
+static device_resume_t le_isa_resume;
+static device_suspend_t le_isa_suspend;
+
+static device_method_t le_isa_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         le_isa_probe),
+       DEVMETHOD(device_attach,        le_isa_attach),
+       DEVMETHOD(device_detach,        le_isa_detach),
+       /* We can just use the suspend method here. */
+       DEVMETHOD(device_shutdown,      le_isa_suspend),
+       DEVMETHOD(device_suspend,       le_isa_suspend),
+       DEVMETHOD(device_resume,        le_isa_resume),
 
-       sc->portrid = 0;
-       sc->portres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid,
-           RF_ACTIVE);
+       { 0, 0 }
+};
 
-       if (! sc->portres) {
-               device_printf(dev, "Failed to allocate I/O ports\n");
-               return (ENXIO);
-       }
+DEFINE_CLASS_0(lnc, le_isa_driver, le_isa_methods, sizeof(struct le_isa_softc));
+DRIVER_MODULE(lnc, isa, le_isa_driver, le_devclass, 0, 0);
+MODULE_DEPEND(lnc, ether, 1, 1, 1);
+
+struct le_isa_param {
+       const char      *name;
+       u_long          iosize;
+       bus_size_t      rap;
+       bus_size_t      rdp;
+       bus_size_t      macstart;
+       int             macstride;
+} static const le_isa_params[] = {
+       { "BICC Isolan", 24, 0xe, 0xc, 0, 2 },
+       { "Novell NE2100", 16, 0x12, 0x10, 0, 1 }
+};
 
-       sc->lnc_btag = rman_get_bustag(sc->portres);
-       sc->lnc_bhandle = rman_get_bushandle(sc->portres);
+static struct isa_pnp_id le_isa_ids[] = {
+       { 0x0322690e, "Cabletron E2200 Single Chip" },  /* CSI2203 */
+       { 0x0110490a, "Boca LANCard Combo" },           /* BRI1001 */
+       { 0x0100a60a, "Melco Inc. LGY-IV" },            /* BUF0001 */
+       { 0xd880d041, "Novell NE2100" },                /* PNP80D8 */
+       { 0x0082d041, "Cabletron E2100 Series DNI" },   /* PNP8200 */
+       { 0x3182d041, "AMD AM1500T/AM2100" },           /* PNP8231 */
+       { 0x8c82d041, "AMD PCnet-ISA" },                /* PNP828C */
+       { 0x8d82d041, "AMD PCnet-32" },                 /* PNP828D */
+       { 0xcefaedfe, "Racal InterLan EtherBlaster" },  /* _WMFACE */
+       { 0, NULL }
+};
 
-       /*
-        * There isn't any way to determine if a NIC is a BICC. Basically, if
-        * the lance probe succeeds using the i/o addresses of the BICC then
-        * we assume it's a BICC.
-        *
-        */
-       sc->rap = BICC_RAP;
-       sc->rdp = BICC_RDP;
-       sc->nic.mem_mode = DMA_FIXED;
-       /* XXX Should set BICC_IOSIZE et al somewhere to alloc
-          resources correctly */
-
-       if ((sc->nic.ic = lance_probe(sc))) {
-               device_set_desc(dev, "BICC Isolan");
-               sc->nic.ident = BICC;
-               lnc_isa_detach(dev);
-               return (0);
-       } else {
-           /* It's not a BICC so try the standard NE2100 ports */
-           sc->rap = PCNET_RAP;
-           sc->rdp = PCNET_RDP;
-           if ((sc->nic.ic = lance_probe(sc))) {
-               sc->nic.ident = NE2100;
-               device_set_desc(dev, "NE2100");
-               lnc_isa_detach(dev);
-               return (0);
-           } else {
-               lnc_isa_detach(dev);
-               return (ENXIO);
-           }
-       }
+static void le_isa_wrcsr(struct lance_softc *, uint16_t, uint16_t);
+static uint16_t le_isa_rdcsr(struct lance_softc *, uint16_t);
+static bus_dmamap_callback_t le_isa_dma_callback;
+static int le_isa_probe_legacy(device_t, const struct le_isa_param *);
+
+static void
+le_isa_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
+{
+       struct le_isa_softc *lesc = (struct le_isa_softc *)sc;
+
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rdp, val);
 }
 
-static int
-lnc_isa_probe(device_t dev)
+static uint16_t
+le_isa_rdcsr(struct lance_softc *sc, uint16_t port)
 {
-       int pnp;
+       struct le_isa_softc *lesc = (struct le_isa_softc *)sc;
 
-       pnp = ISA_PNP_PROBE(device_get_parent(dev), dev, lnc_pnp_ids);
-       if (pnp == ENOENT) {
-               /* It's not a PNP card, see if we support it by probing it */
-               return (lnc_legacy_probe(dev));
-       } else if (pnp == ENXIO) {
-               return (ENXIO);
-       } else {
-               /* Found PNP card we support */
-               return (0);
-       }
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, lesc->sc_rap, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, lesc->sc_rdp));
 }
 
 static void
-lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
+le_isa_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
 {
-       /* Do nothing */
-       return;
+       struct lance_softc *sc = (struct lance_softc *)xsc;
+
+       if (error != 0)
+               return;
+       KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
+       sc->sc_addr = segs[0].ds_addr;
 }
 
 static int
-lnc_isa_attach(device_t dev)
+le_isa_probe_legacy(device_t dev, const struct le_isa_param *leip)
 {
-       lnc_softc_t *sc = device_get_softc(dev);
-       int error = 0;
-       bus_size_t lnc_mem_size;
-
-       /*
-        * The probe routines can allocate resources and to make our
-        * live easier, bzero the softc now.
-        */
-       bzero(sc, sizeof(*sc));
+       struct le_isa_softc *lesc;
+       struct lance_softc *sc;
+       int error;
 
-       sc->portrid = 0;
-       sc->portres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->portrid,
-           RF_ACTIVE);
+       lesc = device_get_softc(dev);
+       sc = &lesc->sc_am7990.lsc;
 
-       if (!sc->portres) {
-               device_printf(dev, "Failed to allocate I/O ports\n");
+       lesc->sc_rrid = 0;
+       lesc->sc_rres = bus_alloc_resource(dev, SYS_RES_IOPORT, &lesc->sc_rrid,
+           0, ~0, leip->iosize, RF_ACTIVE);
+       if (lesc->sc_rres == NULL)
+               return (ENXIO);
+       lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
+       lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
+       lesc->sc_rap = leip->rap;
+       lesc->sc_rdp = leip->rdp;
+
+       /* Stop the chip and put it in a known state. */
+       le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP);
+       DELAY(100);
+       if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) {
                error = ENXIO;
                goto fail;
        }
+       le_isa_wrcsr(sc, LE_CSR3, 0);
+       error = 0;
 
-       sc->drqrid = 0;
-       sc->drqres = bus_alloc_resource_any(dev, SYS_RES_DRQ, &sc->drqrid,
-           RF_ACTIVE);
+ fail:
+       bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
+       return (error);
+}
 
-       if (!sc->drqres) {
-               device_printf(dev, "Failed to allocate DMA channel\n");
-               error = ENXIO;
-               goto fail;
+static int
+le_isa_probe(device_t dev)
+{
+       int i;
+
+       switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) {
+       case 0:
+               return (-20);
+       case ENOENT:
+               for (i = 0; i < sizeof(le_isa_params) /
+                   sizeof(le_isa_params[0]); i++) {
+                       if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) {
+                               device_set_desc(dev, le_isa_params[i].name);
+                               return (-20);
+                       }
+               }
+               /* FALLTHROUGH */
+       case ENXIO:
+       default:
+               return (ENXIO);
        }
+}
 
-       if (isa_get_irq(dev) == -1)
-               bus_set_resource(dev, SYS_RES_IRQ, 0, 10, 1);
-
-       sc->irqrid = 0;
-       sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
-           RF_ACTIVE);
-
-       if (! sc->irqres) {
-               device_printf(dev, "Failed to allocate irq\n");
+static int
+le_isa_attach(device_t dev)
+{
+       struct le_isa_softc *lesc;
+       struct lance_softc *sc;
+       bus_size_t macstart, rap, rdp;
+       int error, i, macstride;
+
+       lesc = device_get_softc(dev);
+       sc = &lesc->sc_am7990.lsc;
+
+       lesc->sc_rrid = 0;
+       switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) {
+       case 0:
+               lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+                   &lesc->sc_rrid, RF_ACTIVE);
+               rap = PCNET_RAP;
+               rdp = PCNET_RDP;
+               macstart = 0;
+               macstride = 1;
+               break;
+       case ENOENT:
+               for (i = 0; i < sizeof(le_isa_params) /
+                   sizeof(le_isa_params[0]); i++) {
+                       if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) {
+                               lesc->sc_rres = bus_alloc_resource(dev,
+                                   SYS_RES_IOPORT, &lesc->sc_rrid, 0, ~0,
+                                   le_isa_params[i].iosize, RF_ACTIVE);
+                               rap = le_isa_params[i].rap;
+                               rdp = le_isa_params[i].rdp;
+                               macstart = le_isa_params[i].macstart;
+                               macstride = le_isa_params[i].macstride;
+                               goto found;
+                       }
+               }
+               /* FALLTHROUGH */
+       case ENXIO:
+       default:
+               device_printf(dev, "cannot determine chip\n");
                error = ENXIO;
-               goto fail;
+               goto fail_mtx;
        }
 
-       /* XXX temp setting for nic */
-       sc->nic.mem_mode = DMA_FIXED;
-       sc->nrdre  = NRDRE;
-       sc->ntdre  = NTDRE;
-
-       if (sc->nic.ident == NE2100) {
-           sc->rap = PCNET_RAP;
-           sc->rdp = PCNET_RDP;
-           sc->bdp = PCNET_BDP;
-       } else {
-           sc->rap = BICC_RAP;
-           sc->rdp = BICC_RDP;
+ found:
+       if (lesc->sc_rres == NULL) {
+               device_printf(dev, "cannot allocate registers\n");
+               error = ENXIO;
+               goto fail_mtx;
+       }
+       lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
+       lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
+       lesc->sc_rap = rap;
+       lesc->sc_rdp = rdp;
+
+       lesc->sc_drid = 0;
+       if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ,
+           &lesc->sc_drid, RF_ACTIVE)) == NULL) {
+               device_printf(dev, "cannot allocate DMA channel\n");
+               error = ENXIO;
+               goto fail_rres;
        }
 
-       /* Create a DMA tag describing the ring memory we need */
-
-       lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) *
-                        sizeof(struct host_ring_entry));
-
-       lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) +
-                       (NDESC(sc->ntdre) * TRANSBUFSIZE);
-
-       error = bus_dma_tag_create(NULL,                /* parent */
-                                  4,                   /* alignement */
-                                  0,                   /* boundary */
-                                  BUS_SPACE_MAXADDR_24BIT,     /* lowaddr */
-                                  BUS_SPACE_MAXADDR,   /* highaddr */
-                                  NULL, NULL,          /* filter, filterarg */
-                                  lnc_mem_size,        /* segsize */
-                                  1,                   /* nsegments */
-                                  BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
-                                  BUS_DMA_ALLOCNOW,    /* flags */
-                                  &sc->dmat);
-
-       if (error) {
-               device_printf(dev, "Can't create DMA tag\n");
-               goto fail;
+       lesc->sc_irid = 0;
+       if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+           &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+               device_printf(dev, "cannot allocate interrupt\n");
+               error = ENXIO;
+               goto fail_dres;
        }
 
-       error = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring,
-                              BUS_DMA_WAITOK, &sc->dmamap);
+       error = bus_dma_tag_create(
+           NULL,                       /* parent */
+           1, 0,                       /* alignment, boundary */
+           BUS_SPACE_MAXADDR_24BIT,    /* lowaddr */
+           BUS_SPACE_MAXADDR,          /* highaddr */
+           NULL, NULL,                 /* filter, filterarg */
+           BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
+           0,                          /* nsegments */
+           BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
+           BUS_DMA_WAITOK,             /* flags */
+           &lesc->sc_pdmat);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate parent DMA tag\n");
+               goto fail_ires;
+       }
 
-       if (error) {
-               device_printf(dev, "Couldn't allocate memory\n");
-               goto fail;
+       sc->sc_memsize = LE_ISA_MEMSIZE;
+       /*
+        * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte
+        * aligned and the ring descriptors must be 8-byte aligned.
+        */
+       error = bus_dma_tag_create(
+           lesc->sc_pdmat,             /* parent */
+           8, 0,                       /* alignment, boundary */
+           BUS_SPACE_MAXADDR_24BIT,    /* lowaddr */
+           BUS_SPACE_MAXADDR,          /* highaddr */
+           NULL, NULL,                 /* filter, filterarg */
+           sc->sc_memsize,             /* maxsize */
+           1,                          /* nsegments */
+           sc->sc_memsize,             /* maxsegsize */
+           BUS_DMA_WAITOK,             /* flags */
+           &lesc->sc_dmat);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate buffer DMA tag\n");
+               goto fail_pdtag;
        }
 
-       error = bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring,
-                               lnc_mem_size, lnc_alloc_callback,
-                               sc->recv_ring, 0);
+       error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
+           BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate DMA buffer memory\n");
+               goto fail_dtag;
+       }
 
-       if (error) {
-               device_printf(dev, "Couldn't load DMA map\n");
-               goto fail;
+       sc->sc_addr = 0;
+       error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
+           sc->sc_memsize, le_isa_dma_callback, sc, 0);
+       if (error != 0 || sc->sc_addr == 0) {
+                device_printf(dev, "cannot load DMA buffer map\n");
+               goto fail_dmem;
        }
 
-       isa_dmacascade(rman_get_start(sc->drqres));
+       isa_dmacascade(rman_get_start(lesc->sc_dres));
 
-       /* Call generic attach code */
-       if (! lnc_attach_common(dev)) {
-               device_printf(dev, "Generic attach code failed\n");
-               error = ENXIO;
-               goto fail;
+       sc->sc_flags = 0;
+       sc->sc_conf3 = 0;
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        */
+       for (i = 0; i < sizeof(sc->sc_enaddr); i++)
+               sc->sc_enaddr[i] =  bus_space_read_1(lesc->sc_regt,
+                   lesc->sc_regh, macstart + i * macstride);
+
+       sc->sc_copytodesc = lance_copytobuf_contig;
+       sc->sc_copyfromdesc = lance_copyfrombuf_contig;
+       sc->sc_copytobuf = lance_copytobuf_contig;
+       sc->sc_copyfrombuf = lance_copyfrombuf_contig;
+       sc->sc_zerobuf = lance_zerobuf_contig;
+
+       sc->sc_rdcsr = le_isa_rdcsr;
+       sc->sc_wrcsr = le_isa_wrcsr;
+       sc->sc_hwreset = NULL;
+       sc->sc_hwinit = NULL;
+       sc->sc_hwintr = NULL;
+       sc->sc_nocarrier = NULL;
+       sc->sc_mediachange = NULL;
+       sc->sc_mediastatus = NULL;
+       sc->sc_supmedia = NULL;
+
+       error = am7990_config(&lesc->sc_am7990, device_get_name(dev),
+           device_get_unit(dev));
+       if (error != 0) {
+               device_printf(dev, "cannot attach Am7990\n");
+               goto fail_dmap;
        }
 
-       error = bus_setup_intr(dev, sc->irqres, INTR_NETSAFE, lncintr,
-                              sc, &sc->intrhand, 
-                              sc->arpcom.ac_if.if_serializer);
-       if (error) {
-               device_printf(dev, "Failed to setup irq handler\n");
-               ether_ifdetach(&sc->arpcom.ac_if);
-               goto fail;
+       error = bus_setup_intr(dev, lesc->sc_ires, INTR_NETSAFE | INTR_MPSAFE,
+           am7990_intr, sc, &lesc->sc_ih, sc->ifp->if_serializer);
+       if (error != 0) {
+               device_printf(dev, "cannot set up interrupt\n");
+               goto fail_am7990;
        }
 
        return (0);
 
-fail:
-       lnc_isa_detach(dev);
-       return(error);
+ fail_am7990:
+       am7990_detach(&lesc->sc_am7990);
+ fail_dmap:
+       bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
+ fail_dmem:
+       bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
+ fail_dtag:
+       bus_dma_tag_destroy(lesc->sc_dmat);
+ fail_pdtag:
+       bus_dma_tag_destroy(lesc->sc_pdmat);
+ fail_ires:
+       bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
+ fail_dres:
+       bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres);
+ fail_rres:
+       bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
+ fail_mtx:
+       return (error);
 }
 
 static int
-lnc_isa_detach(device_t dev)
+le_isa_detach(device_t dev)
 {
-       lnc_softc_t *sc = device_get_softc(dev);
+       struct le_isa_softc *lesc;
+       struct lance_softc *sc;
+
+       lesc = device_get_softc(dev);
+       sc = &lesc->sc_am7990.lsc;
 
        if (device_is_attached(dev)) {
-               lwkt_serialize_enter(sc->arpcom.ac_if.if_serializer);
-               lnc_stop(sc);
-               bus_teardown_intr(dev, sc->irqres, sc->intrhand);
-               lwkt_serialize_exit(sc->arpcom.ac_if.if_serializer);
+               lwkt_serialize_enter(sc->ifp->if_serializer);
+               lance_stop(sc);
+               bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
+               lwkt_serialize_exit(sc->ifp->if_serializer);
 
-               ether_ifdetach(&sc->arpcom.ac_if);
+               am7990_detach(&lesc->sc_am7990);
        }
 
-       if (sc->irqres)
-               bus_release_resource(dev, SYS_RES_IRQ, sc->irqrid, sc->irqres);
-       if (sc->portres)
-               bus_release_resource(dev, SYS_RES_IOPORT,
-                                    sc->portrid, sc->portres);
-       if (sc->drqres)
-               bus_release_resource(dev, SYS_RES_DRQ, sc->drqrid, sc->drqres);
-       if (sc->dmamap) {
-               bus_dmamap_unload(sc->dmat, sc->dmamap);
-               bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap);
+       if (lesc->sc_ires)
+               bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
+       if (lesc->sc_dres)
+               bus_release_resource(dev, SYS_RES_DRQ, lesc->sc_drid, lesc->sc_dres);
+       if (lesc->sc_rres)
+               bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
+       if (lesc->sc_dmam) {
+               bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
+               bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
        }
-       if (sc->dmat)
-               bus_dma_tag_destroy(sc->dmat);
+       if (lesc->sc_dmat)
+               bus_dma_tag_destroy(lesc->sc_dmat);
+       if (lesc->sc_pdmat)
+               bus_dma_tag_destroy(lesc->sc_pdmat);
 
        return (0);
 }
 
-static device_method_t lnc_isa_methods[] = {
-/*     DEVMETHOD(device_identify,      lnc_isa_identify), */
-       DEVMETHOD(device_probe,         lnc_isa_probe),
-       DEVMETHOD(device_attach,        lnc_isa_attach),
-       DEVMETHOD(device_detach,        lnc_isa_detach),
-#ifdef notyet
-       DEVMETHOD(device_suspend,       lnc_isa_suspend),
-       DEVMETHOD(device_resume,        lnc_isa_resume),
-       DEVMETHOD(device_shutdown,      lnc_isa_shutdown),
-#endif
-       { 0, 0 }
-};
+static int
+le_isa_suspend(device_t dev)
+{
+       struct le_isa_softc *lesc;
 
-static driver_t lnc_isa_driver = {
-       "lnc",
-       lnc_isa_methods,
-       sizeof(struct lnc_softc),
-};
+       lesc = device_get_softc(dev);
+
+       lance_suspend(&lesc->sc_am7990.lsc);
+
+       return (0);
+}
+
+static int
+le_isa_resume(device_t dev)
+{
+       struct le_isa_softc *lesc;
+
+       lesc = device_get_softc(dev);
 
-DRIVER_MODULE(if_lnc, isa, lnc_isa_driver, lnc_devclass, 0, 0);
+       lance_resume(&lesc->sc_am7990.lsc);
+
+       return (0);
+}
index 120e32a..0ec1800 100644 (file)
@@ -1,24 +1,68 @@
-/*
- * Copyright (c) 1994-2000
- *     Paul Richards. All rights reserved.
+/*     $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $  */
+/*     $FreeBSD: src/sys/dev/le/if_le_pci.c,v 1.4 2006/06/05 15:14:14 marius Exp $     */
+/*     $DragonFly: src/sys/dev/netif/lnc/if_lnc_pci.c,v 1.10 2006/07/07 14:16:29 sephe Exp $   */
+
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
  *
  * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
+ *    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.
- * 3. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 PAUL RICHARDS BE LIABLE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS 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)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/lnc/if_lnc_pci.c,v 1.25 2001/07/04 13:00:19 nyan Exp $
- * $DragonFly: src/sys/dev/netif/lnc/if_lnc_pci.c,v 1.9 2005/12/31 14:07:59 sephe Exp $
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/socket.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/serialize.h>
-
-#include <machine/bus.h>
-#include <machine/resource.h>
 #include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/resource.h>
 #include <sys/rman.h>
-
-#include <sys/thread2.h>
+#include <sys/socket.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
+#include <net/if_media.h>
 #include <net/if_arp.h>
 
+#include <machine/bus.h>
+#include <machine/resource.h>
+
 #include <bus/pci/pcireg.h>
 #include <bus/pci/pcivar.h>
 
-#include <dev/netif/lnc/if_lncreg.h>
-#include <dev/netif/lnc/if_lncvar.h>
+#include <dev/netif/lnc/lancereg.h>
+#include <dev/netif/lnc/lancevar.h>
+#include <dev/netif/lnc/am79900var.h>
 
-#define AMD_VENDOR_ID 0x1022
-#define PCI_DEVICE_ID_PCNet_PCI        0x2000
-#define PCI_DEVICE_ID_PCHome_PCI 0x2001
+#define        AMD_VENDOR      0x1022
+#define        AMD_PCNET_PCI   0x2000
+#define        AMD_PCNET_HOME  0x2001
+#define        PCNET_MEMSIZE   (32*1024)
+#define        PCNET_PCI_RDP   0x10
+#define        PCNET_PCI_RAP   0x12
+#define        PCNET_PCI_BDP   0x16
 
-#define LNC_PROBE_PRIORITY -1
+#define LNC_PROBE_PRIORITY -100
 
-static int     lnc_pci_detach(device_t);
+struct le_pci_softc {
+       struct am79900_softc    sc_am79900;     /* glue to MI code */
 
-static int
-lnc_pci_probe(device_t dev)
+       int                     sc_rrid;
+       struct resource         *sc_rres;
+       bus_space_tag_t         sc_regt;
+       bus_space_handle_t      sc_regh;
+
+       int                     sc_irid;
+       struct resource         *sc_ires;
+       void                    *sc_ih;
+
+       bus_dma_tag_t           sc_pdmat;
+       bus_dma_tag_t           sc_dmat;
+       bus_dmamap_t            sc_dmam;
+};
+
+static device_probe_t le_pci_probe;
+static device_attach_t le_pci_attach;
+static device_detach_t le_pci_detach;
+static device_resume_t le_pci_resume;
+static device_suspend_t le_pci_suspend;
+
+static device_method_t le_pci_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         le_pci_probe),
+       DEVMETHOD(device_attach,        le_pci_attach),
+       DEVMETHOD(device_detach,        le_pci_detach),
+       /* We can just use the suspend method here. */
+       DEVMETHOD(device_shutdown,      le_pci_suspend),
+       DEVMETHOD(device_suspend,       le_pci_suspend),
+       DEVMETHOD(device_resume,        le_pci_resume),
+
+       { 0, 0 }
+};
+
+DEFINE_CLASS_0(lnc, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc));
+DRIVER_MODULE(lnc, pci, le_pci_driver, le_devclass, 0, 0);
+MODULE_DEPEND(lnc, ether, 1, 1, 1);
+
+static const int le_home_supmedia[] = {
+       IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0)
+};
+
+static const int le_pci_supmedia[] = {
+       IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
+       IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0),
+       IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
+       IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0),
+       IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0),
+       IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0)
+};
+
+static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t);
+static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t);
+static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t);
+static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t);
+static int le_pci_mediachange(struct lance_softc *);
+static void le_pci_hwreset(struct lance_softc *);
+static bus_dmamap_callback_t le_pci_dma_callback;
+
+static void
+le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val)
 {
-       if (pci_get_vendor(dev) != AMD_VENDOR_ID)
-               return (ENXIO);
+       struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
 
-       switch(pci_get_device(dev)) {
-       case PCI_DEVICE_ID_PCNet_PCI:
-               device_set_desc(dev, "PCNet/PCI Ethernet adapter");
-               return(LNC_PROBE_PRIORITY);
-               break;
-       case PCI_DEVICE_ID_PCHome_PCI:
-               device_set_desc(dev, "PCHome/PCI Ethernet adapter");
-               return(LNC_PROBE_PRIORITY);
-               break;
-       default:
-               return (ENXIO);
-               break;
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP, val);
+}
+
+static uint16_t
+le_pci_rdbcr(struct lance_softc *sc, uint16_t port)
+{
+       struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
+
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP));
+}
+
+static void
+le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
+{
+       struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
+
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val);
+}
+
+static uint16_t
+le_pci_rdcsr(struct lance_softc *sc, uint16_t port)
+{
+       struct le_pci_softc *lesc = (struct le_pci_softc *)sc;
+
+       bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port);
+       bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2,
+           BUS_SPACE_BARRIER_WRITE);
+       return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP));
+}
+
+static int
+le_pci_mediachange(struct lance_softc *sc)
+{
+       struct ifmedia *ifm = &sc->sc_media;
+       uint16_t reg;
+
+       if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
+               return (EINVAL);
+
+       if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1)
+               le_pci_wrbcr(sc, LE_BCR49,
+                   (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1);
+       else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO)
+               le_pci_wrbcr(sc, LE_BCR2,
+                   le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL);
+       else {
+               le_pci_wrbcr(sc, LE_BCR2,
+                   le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL);
+
+               reg = le_pci_rdcsr(sc, LE_CSR15);
+               reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK);
+               if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T)
+                       reg |= LE_C15_PORTSEL(LE_PORTSEL_10T);
+               else
+                       reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI);
+               le_pci_wrcsr(sc, LE_CSR15, reg);
        }
-       return (ENXIO);
+
+       reg = le_pci_rdbcr(sc, LE_BCR9);
+       if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) {
+               reg |= LE_B9_FDEN;
+               /*
+                * Allow FDX on AUI only if explicitly chosen,
+                * not in autoselect mode.
+                */
+               if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5)
+                       reg |= LE_B9_AUIFD;
+               else
+                       reg &= ~LE_B9_AUIFD;
+       } else
+               reg &= ~LE_B9_FDEN;
+       le_pci_wrbcr(sc, LE_BCR9, reg);
+
+       return (0);
+}
+
+static void
+le_pci_hwreset(struct lance_softc *sc)
+{
+
+       /*
+        * Chip is stopped. Set software style to PCnet-PCI (32-bit).
+        * Actually, am79900.c implements ILACC support (hence its
+        * name) but unfortunately VMware does not. As far as this
+        * driver is concerned that should not make a difference
+        * though, as the settings used have the same meaning for
+        * both, ILACC and PCnet-PCI (note that there would be a
+        * difference for the ADD_FCS/NO_FCS bit if used).
+        */
+       le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_PCNETPCI2);
 }
 
 static void
-lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
+le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
 {
-       /* Do nothing */
-       return;
+       struct lance_softc *sc = (struct lance_softc *)xsc;
+
+       if (error != 0)
+               return;
+       KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
+       sc->sc_addr = segs[0].ds_addr;
 }
 
 static int
-lnc_pci_attach(device_t dev)
+le_pci_probe(device_t dev)
 {
-       lnc_softc_t *sc = device_get_softc(dev);
-       unsigned command;
-       int rid = 0;
-       int error = 0;
-       bus_size_t lnc_mem_size;
-
-       command = pci_read_config(dev, PCIR_COMMAND, 4);
-       command |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
-       pci_write_config(dev, PCIR_COMMAND, command, 4);
-
-       rid = PCIR_MAPS;
-       sc->portres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
-           RF_ACTIVE);
-
-       if (! sc->portres) {
-               device_printf(dev, "Cannot allocate I/O ports\n");
-               error = ENXIO;
-               goto fail;
+
+       if (pci_get_vendor(dev) != AMD_VENDOR)
+               return (ENXIO);
+
+       switch (pci_get_device(dev)) {
+       case AMD_PCNET_PCI:
+               device_set_desc(dev, "AMD PCnet-PCI");
+               /* Let pcn(4) win. */
+               return (LNC_PROBE_PRIORITY);
+       case AMD_PCNET_HOME:
+               device_set_desc(dev, "AMD PCnet-Home");
+               /* Let pcn(4) win. */
+               return (LNC_PROBE_PRIORITY);
+       default:
+               return (ENXIO);
        }
+}
+
+static int
+le_pci_attach(device_t dev)
+{
+       struct le_pci_softc *lesc;
+       struct lance_softc *sc;
+       int error, i;
+
+       lesc = device_get_softc(dev);
+       sc = &lesc->sc_am79900.lsc;
 
-       rid = 0;
-       sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-           RF_ACTIVE | RF_SHAREABLE);
+       pci_enable_busmaster(dev);
+       pci_enable_io(dev, PCIM_CMD_PORTEN);
 
-       if (! sc->irqres) {
-               device_printf(dev, "Cannot allocate irq\n");
+       lesc->sc_rrid = PCIR_BAR(0);
+       lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+           &lesc->sc_rrid, RF_ACTIVE);
+       if (lesc->sc_rres == NULL) {
+               device_printf(dev, "cannot allocate registers\n");
                error = ENXIO;
-               goto fail;
+               goto fail_mtx;
        }
+       lesc->sc_regt = rman_get_bustag(lesc->sc_rres);
+       lesc->sc_regh = rman_get_bushandle(lesc->sc_rres);
 
-       sc->lnc_btag = rman_get_bustag(sc->portres);
-       sc->lnc_bhandle = rman_get_bushandle(sc->portres);
-
-       /* XXX temp setting for nic */
-       sc->nic.ic = PCnet_PCI;
-       sc->nic.ident = NE2100;
-       sc->nic.mem_mode = DMA_FIXED;
-       sc->nrdre  = NRDRE;
-       sc->ntdre  = NTDRE;
-       sc->rap = PCNET_RAP;
-       sc->rdp = PCNET_RDP;
-       sc->bdp = PCNET_BDP;
-
-       /* Create a DMA tag describing the ring memory we need */
-
-       lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) *
-                        sizeof(struct host_ring_entry));
-
-       lnc_mem_size += sizeof(struct init_block) + (sizeof(struct mds) *
-                       (NDESC(sc->nrdre) + NDESC(sc->ntdre))) + MEM_SLEW;
-
-       lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) +
-                       (NDESC(sc->ntdre) * TRANSBUFSIZE);
-
-       error = bus_dma_tag_create(NULL,                /* parent */
-                                  1,                   /* alignement */
-                                  0,                   /* boundary */
-                                  BUS_SPACE_MAXADDR_24BIT,     /* lowaddr */
-                                  BUS_SPACE_MAXADDR,   /* highaddr */
-                                  NULL, NULL,          /* filter, filterarg */
-                                  lnc_mem_size,        /* segsize */
-                                  1,                   /* nsegments */
-                                  BUS_SPACE_MAXSIZE_32BIT,     /* maxsegsize */
-                                  BUS_DMA_ALLOCNOW,    /* flags */
-                                  &sc->dmat);
-
-       if (error) {
-               device_printf(dev, "Can't create DMA tag\n");
-               goto fail;
+       lesc->sc_irid = 0;
+       if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+           &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+               device_printf(dev, "cannot allocate interrupt\n");
+               error = ENXIO;
+               goto fail_rres;
        }
 
-       error = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring,
-                              BUS_DMA_WAITOK, &sc->dmamap);
-       if (error) {
-               device_printf(dev, "Couldn't allocate memory\n");
-               goto fail;
+       error = bus_dma_tag_create(
+           NULL,                       /* parent */
+           1, 0,                       /* alignment, boundary */
+           BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
+           BUS_SPACE_MAXADDR,          /* highaddr */
+           NULL, NULL,                 /* filter, filterarg */
+           BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
+           0,                          /* nsegments */
+           BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
+           BUS_DMA_WAITOK,             /* flags */
+           &lesc->sc_pdmat);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate parent DMA tag\n");
+               goto fail_ires;
        }
 
-       error = bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring,
-                               lnc_mem_size, lnc_alloc_callback,
-                               sc->recv_ring, 0);
-       if (error) {
-               device_printf(dev, "Couldn't map receive ring\n");
-               goto fail;
+       sc->sc_memsize = PCNET_MEMSIZE;
+       /*
+        * For Am79C970A, Am79C971 and Am79C978 the init block must be 2-byte
+        * aligned and the ring descriptors must be 16-byte aligned when using
+        * a 32-bit software style.
+        */
+       error = bus_dma_tag_create(
+           lesc->sc_pdmat,             /* parent */
+           16, 0,                      /* alignment, boundary */
+           BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
+           BUS_SPACE_MAXADDR,          /* highaddr */
+           NULL, NULL,                 /* filter, filterarg */
+           sc->sc_memsize,             /* maxsize */
+           1,                          /* nsegments */
+           sc->sc_memsize,             /* maxsegsize */
+           BUS_DMA_WAITOK,             /* flags */
+           &lesc->sc_dmat);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate buffer DMA tag\n");
+               goto fail_pdtag;
        }
 
-       /* Call generic attach code */
-       if (! lnc_attach_common(dev)) {
-               device_printf(dev, "Generic attach code failed\n");
-               error = ENXIO;
-               goto fail;
+       error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
+           BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
+       if (error != 0) {
+               device_printf(dev, "cannot allocate DMA buffer memory\n");
+               goto fail_dtag;
+       }
+
+       sc->sc_addr = 0;
+       error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
+           sc->sc_memsize, le_pci_dma_callback, sc, 0);
+       if (error != 0 || sc->sc_addr == 0) {
+                device_printf(dev, "cannot load DMA buffer map\n");
+               goto fail_dmem;
+       }
+
+       sc->sc_flags = LE_BSWAP;
+       sc->sc_conf3 = 0;
+
+       sc->sc_mediastatus = NULL;
+       switch (pci_get_device(dev)) {
+       case AMD_PCNET_HOME:
+               sc->sc_mediachange = le_pci_mediachange;
+               sc->sc_supmedia = le_home_supmedia;
+               sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int);
+               sc->sc_defaultmedia = le_home_supmedia[0];
+               break;
+       default:
+               sc->sc_mediachange = le_pci_mediachange;
+               sc->sc_supmedia = le_pci_supmedia;
+               sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int);
+               sc->sc_defaultmedia = le_pci_supmedia[0];
+       }
+
+       /*
+        * Extract the physical MAC address from the ROM.
+        */
+       for (i = 0; i < sizeof(sc->sc_enaddr); i++)
+               sc->sc_enaddr[i] =
+                   bus_space_read_1(lesc->sc_regt, lesc->sc_regh, i);
+
+       sc->sc_copytodesc = lance_copytobuf_contig;
+       sc->sc_copyfromdesc = lance_copyfrombuf_contig;
+       sc->sc_copytobuf = lance_copytobuf_contig;
+       sc->sc_copyfrombuf = lance_copyfrombuf_contig;
+       sc->sc_zerobuf = lance_zerobuf_contig;
+
+       sc->sc_rdcsr = le_pci_rdcsr;
+       sc->sc_wrcsr = le_pci_wrcsr;
+       sc->sc_hwreset = le_pci_hwreset;
+       sc->sc_hwinit = NULL;
+       sc->sc_hwintr = NULL;
+       sc->sc_nocarrier = NULL;
+
+       error = am79900_config(&lesc->sc_am79900, device_get_name(dev),
+           device_get_unit(dev));
+       if (error != 0) {
+               device_printf(dev, "cannot attach Am79900\n");
+               goto fail_dmap;
        }
 
-       error = bus_setup_intr(dev, sc->irqres, INTR_NETSAFE, lncintr,
-                            sc, &sc->intrhand, 
-                            sc->arpcom.ac_if.if_serializer);
-       if (error) {
-               device_printf(dev, "Cannot setup irq handler\n");
-               ether_ifdetach(&sc->arpcom.ac_if);
-               goto fail;
+       error = bus_setup_intr(dev, lesc->sc_ires, INTR_NETSAFE | INTR_MPSAFE,
+           am79900_intr, sc, &lesc->sc_ih, sc->ifp->if_serializer);
+       if (error != 0) {
+               device_printf(dev, "cannot set up interrupt\n");
+               goto fail_am79900;
        }
 
        return (0);
 
-fail:
-       lnc_pci_detach(dev);
-       return(error);
+ fail_am79900:
+       am79900_detach(&lesc->sc_am79900);
+ fail_dmap:
+       bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
+ fail_dmem:
+       bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
+ fail_dtag:
+       bus_dma_tag_destroy(lesc->sc_dmat);
+ fail_pdtag:
+       bus_dma_tag_destroy(lesc->sc_pdmat);
+ fail_ires:
+       bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
+ fail_rres:
+       bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
+ fail_mtx:
+       return (error);
 }
 
 static int
-lnc_pci_detach(device_t dev)
+le_pci_detach(device_t dev)
 {
-       lnc_softc_t *sc = device_get_softc(dev);
+       struct le_pci_softc *lesc;
+       struct lance_softc *sc;
 
+       lesc = device_get_softc(dev);
+       sc = &lesc->sc_am79900.lsc;
 
        if (device_is_attached(dev)) {
-               lwkt_serialize_enter(sc->arpcom.ac_if.if_serializer);
-               lnc_stop(sc);
-               bus_teardown_intr(dev, sc->irqres, sc->intrhand);
-               lwkt_serialize_exit(sc->arpcom.ac_if.if_serializer);
+               lwkt_serialize_enter(sc->ifp->if_serializer);
+               lance_stop(sc);
+               bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
+               lwkt_serialize_exit(sc->ifp->if_serializer);
 
-               ether_ifdetach(&sc->arpcom.ac_if);
+               am79900_detach(&lesc->sc_am79900);
        }
 
-       if (sc->irqres)
-               bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irqres);
-       if (sc->portres)
-               bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS,
-                                    sc->portres);
-
-       if (sc->dmamap) {
-               bus_dmamap_unload(sc->dmat, sc->dmamap);
-               bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap);
+       if (lesc->sc_ires)
+               bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
+       if (lesc->sc_rres)
+               bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres);
+       if (lesc->sc_dmam) {
+               bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
+               bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
        }
-       if (sc->dmat)
-               bus_dma_tag_destroy(sc->dmat);
+       if (lesc->sc_dmat)
+               bus_dma_tag_destroy(lesc->sc_dmat);
+       if (lesc->sc_pdmat)
+               bus_dma_tag_destroy(lesc->sc_pdmat);
 
        return (0);
 }
 
-static device_method_t lnc_pci_methods[] = {
-       DEVMETHOD(device_probe,         lnc_pci_probe),
-       DEVMETHOD(device_attach,        lnc_pci_attach),
-       DEVMETHOD(device_detach,        lnc_pci_detach),
-#ifdef notyet
-       DEVMETHOD(device_suspend,       lnc_pci_suspend),
-       DEVMETHOD(device_resume,        lnc_pci_resume),
-       DEVMETHOD(device_shutdown,      lnc_pci_shutdown),
-#endif
-       { 0, 0 }
-};
+static int
+le_pci_suspend(device_t dev)
+{
+       struct le_pci_softc *lesc;
 
-static driver_t lnc_pci_driver = {
-       "lnc",
-       lnc_pci_methods,
-       sizeof(struct lnc_softc),
-};
+       lesc = device_get_softc(dev);
+
+       lance_suspend(&lesc->sc_am79900.lsc);
+
+       return (0);
+}
 
-DRIVER_MODULE(if_lnc, pci, lnc_pci_driver, lnc_devclass, 0, 0);
+static int
+le_pci_resume(device_t dev)
+{
+       struct le_pci_softc *lesc;
+
+       lesc = device_get_softc(dev);
+
+       lance_resume(&lesc->sc_am79900.lsc);
+
+       return (0);
+}
diff --git a/sys/dev/netif/lnc/if_lncreg.h b/sys/dev/netif/lnc/if_lncreg.h
deleted file mode 100644 (file)
index 7084a5c..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*-
- * Copyright (c) 1994-2000
- *     Paul Richards.  All rights reserved.
- *
- * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
- * 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.
- * 3. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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: src/sys/dev/lnc/if_lncreg.h,v 1.7 2001/07/04 13:00:19 nyan Exp $
- * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lncreg.h,v 1.1 2003/12/07 19:23:39 dillon Exp $
- */
-
-/*
- * Am7990, Local Area Network Controller for Ethernet (LANCE)
- *
- * The LANCE has four Control and Status Registers(CSRs) which are accessed
- * through two bus addressable ports, the address port (RAP) and the data
- * port (RDP).
- *
- */
-
-#define CSR0   0
-#define CSR1   1
-#define CSR2   2
-#define CSR3   3
-#define CSR88  88
-#define CSR89  89
-
-#define BCR49  49
-#define BCR32  32
-#define BCR33  33
-#define BCR34  34
-
-
-/* Control and Status Register Masks */
-
-/* CSR0 */
-
-#define ERR    0x8000
-#define BABL   0x4000
-#define CERR   0x2000
-#define MISS   0x1000
-#define MERR   0x0800
-#define RINT   0x0400
-#define TINT   0x0200
-#define IDON   0x0100
-#define INTR   0x0080
-#define INEA   0x0040
-#define RXON   0x0020
-#define TXON   0x0010
-#define TDMD   0x0008
-#define STOP   0x0004
-#define STRT   0x0002
-#define INIT   0x0001
-
-/*
- * CSR3
- *
- * Bits 3-15 are reserved.
- *
- */
-
-#define BSWP   0x0004
-#define ACON   0x0002
-#define BCON   0x0001
-
-/* ISA Bus Configuration Registers */
-#define MSRDA   0x0000  /* ISACSR0: Master Mode Read Activity */
-#define MSWRA   0x0001  /* ISACSR1: Master Mode Write Activity */
-#define MC      0x0002  /* ISACSR2: Miscellaneous Configuration */
-
-#define LED1    0x0005  /* ISACSR5: LED1 Status */
-#define LED2    0x0006  /* ISACSR6: LED2 Status */
-#define LED3    0x0007  /* ISACSR7: LED3 Status */
-
-#define LED_PSE         0x0080  /* Pulse Stretcher */
-#define LED_XMTE        0x0010  /* Transmit Status */
-#define LED_RVPOLE      0x0008  /* Receive Polarity */
-#define LED_RCVE        0x0004  /* Receive Status */
-#define LED_JABE        0x0002  /* Jabber */
-#define LED_COLE        0x0001  /* Collision */
-
-/* Initialisation block */
-
-struct init_block {
-       u_short mode;           /* Mode register                        */
-       u_char  padr[6];        /* Ethernet address                     */
-       u_char  ladrf[8];       /* Logical address filter (multicast)   */
-       u_short rdra;           /* Low order pointer to receive ring    */
-       u_short rlen;           /* High order pointer and no. rings     */
-       u_short tdra;           /* Low order pointer to transmit ring   */
-       u_short tlen;           /* High order pointer and no rings      */
-};
-
-/* Initialisation Block Mode Register Masks */
-
-#define PROM      0x8000   /* Promiscuous Mode */
-#define DRCVBC    0x4000   /* Disable Receive Broadcast */
-#define DRCVPA    0x2000   /* Disable Receive Physical Address */
-#define DLNKTST        0x1000   /* Disable Link Status */
-#define DAPC      0x0800   /* Disable Automatic Polarity Correction */
-#define MENDECL   0x0400   /* MENDEC Loopback Mode */
-#define LRT       0x0200   /* Low Receive Threshold (T-MAU mode only) */
-#define TSEL      0x0200   /* Transmit Mode Select  (AUI mode only) */
-#define PORTSEL   0x0180   /* Port Select bits */
-#define INTL      0x0040   /* Internal Loopback */
-#define DRTY      0x0020   /* Disable Retry */
-#define FCOLL     0x0010   /* Force Collision */
-#define DXMTFCS   0x0008   /* Disable transmit CRC (FCS) */
-#define LOOP      0x0004   /* Loopback Enabl */
-#define DTX       0x0002   /* Disable the transmitter */
-#define DRX       0x0001   /* Disable the receiver */
-
-/*
- * Message Descriptor Structure
- *
- * Each transmit or receive descriptor ring entry (RDRE's and TDRE's)
- * is composed of 4, 16-bit, message descriptors. They contain the following
- * information.
- *
- * 1. The address of the actual message data buffer in user (host) memory.
- * 2. The length of that message buffer.
- * 3. The status information for that particular buffer. The eight most
- *    significant bits of md1 are collectively termed the STATUS of the
- *    descriptor.
- *
- * Descriptor md0 contains LADR 0-15, the low order 16 bits of the 24-bit
- * address of the actual data buffer.  Bits 0-7 of descriptor md1 contain
- * HADR, the high order 8-bits of the 24-bit data buffer address. Bits 8-15
- * of md1 contain the status flags of the buffer. Descriptor md2 contains the
- * buffer byte count in bits 0-11 as a two's complement number and must have
- * 1's written to bits 12-15. For the receive entry md3 has the Message Byte
- * Count in bits 0-11, this is the length of the received message and is valid
- * only when ERR is cleared and ENP is set. For the transmit entry it contains
- * more status information.
- *
- */
-
-struct mds {
-       u_short md0;
-       u_short md1;
-       short   md2;
-       u_short md3;
-};
-
-/* Receive STATUS flags for md1 */
-
-#define OWN    0x8000          /* Owner bit, 0=host, 1=Lance   */
-#define MDERR  0x4000          /* Error                        */
-#define FRAM   0x2000          /* Framing error error          */
-#define OFLO   0x1000          /* Silo overflow                */
-#define CRC    0x0800          /* CRC error                    */
-#define RBUFF  0x0400          /* Buffer error                 */
-#define STP    0x0200          /* Start of packet              */
-#define ENP    0x0100          /* End of packet                */
-#define HADR   0x00FF          /* High order address bits      */
-
-/* Receive STATUS flags for md2 */
-
-#define BCNT   0x0FFF          /* Size of data buffer as 2's comp. no. */
-
-/* Receive STATUS flags for md3 */
-
-#define MCNT   0x0FFF          /* Total size of data for received packet */
-
-/* Transmit STATUS flags for md1 */
-
-#define ADD_FCS        0x2000          /* Controls generation of FCS   */
-#define MORE   0x1000          /* Indicates more than one retry was needed */
-#define ONE    0x0800          /* Exactly one retry was needed */
-#define DEF    0x0400          /* Packet transmit deferred -- channel busy */
-
-/*
- * Transmit status flags for md2
- *
- * Same as for receive descriptor.
- *
- * BCNT   0x0FFF         Size of data buffer as 2's complement number.
- *
- */
-
-/* Transmit status flags for md3 */
-
-#define TBUFF  0x8000          /* Buffer error         */
-#define UFLO   0x4000          /* Silo underflow       */
-#define LCOL   0x1000          /* Late collision       */
-#define LCAR   0x0800          /* Loss of carrier      */
-#define RTRY   0x0400          /* Tried 16 times       */
-#define TDR    0x03FF          /* Time domain reflectometry */
diff --git a/sys/dev/netif/lnc/if_lncvar.h b/sys/dev/netif/lnc/if_lncvar.h
deleted file mode 100644 (file)
index 8f9d239..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*-
- * Copyright (c) 1994-1998
- *      Paul Richards.  All rights reserved.
- *
- * 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,
- *    verbatim and that no modifications are made prior to this
- *    point in the file.
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *      This product includes software developed by Paul Richards.
- * 4. The name Paul Richards may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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: src/sys/dev/lnc/if_lncvar.h,v 1.23 2001/07/04 13:00:20 nyan Exp $
- * $DragonFly: src/sys/dev/netif/lnc/Attic/if_lncvar.h,v 1.2 2005/06/13 22:55:15 joerg Exp $
- */
-
-/*
- * Initialize multicast address hashing registers to accept
- * all multicasts (only used when in promiscuous mode)
- */
-#define MULTI_INIT_ADDR 0xff
-
-#define NORMAL 0
-
-#define NRDRE 3
-#define NTDRE 3
-#define RECVBUFSIZE 1518       /* Packet size rounded to dword boundary */
-#define TRANSBUFSIZE 1518
-#define MBUF_CACHE_LIMIT 0
-
-#define MEM_SLEW 8
-
-/* LNC Flags */
-#define LNC_INITIALISED 1
-#define LNC_ALLMULTI 2
-
-/* BICC port addresses */
-#define BICC_IOSIZE    16
-#define BICC_RDP     0x0c        /* Register Data Port */
-#define BICC_RAP     0x0e        /* Register Address Port */
-
-/* NE2100 port addresses */
-#define NE2100_IOSIZE  24
-#define PCNET_RDP    0x10        /* Register Data Port */
-#define PCNET_RAP    0x12        /* Register Address Port */
-#define PCNET_RESET  0x14
-#define PCNET_BDP    0x16
-#define PCNET_VSW    0x18
-
-/* DEPCA port addresses */
-#define DEPCA_IOSIZE   16
-#define DEPCA_CTRL   0x00        /* NIC Control and status register */
-#define DEPCA_RDP    0x04        /* Register Data Port */
-#define DEPCA_RAP    0x06        /* Register Address Port */
-#define DEPCA_ADP    0x0c
-
-/* DEPCA specific defines */
-#define DEPCA_ADDR_ROM_SIZE 32
-
-/* C-NET(98)S port addresses */
-/* Notice, we can ignore fragmantation by using isa_alloc_resourcev(). */
-#define CNET98S_IOSIZE   32     
-#define CNET98S_RDP    0x10      /* Register Data Port */
-#define CNET98S_RAP    0x12      /* Register Address Port */
-#define CNET98S_RESET  0x14
-#define CNET98S_IDP    0x16
-#define CNET98S_EEPROM 0x1e
-
-/* Chip types */
-#define LANCE           1        /* Am7990   */
-#define C_LANCE         2        /* Am79C90  */
-#define PCnet_ISA       3        /* Am79C960 */
-#define PCnet_ISAplus   4        /* Am79C961 */
-#define PCnet_ISA_II    5        /* Am79C961A */
-#define PCnet_32        6        /* Am79C965 */
-#define PCnet_PCI       7        /* Am79C970 */
-#define PCnet_PCI_II    8        /* Am79C970A */
-#define PCnet_FAST      9        /* Am79C971 */
-#define PCnet_FASTplus  10       /* Am79C972 */
-#define PCnet_Home     11       /* Am79C978 */
-
-
-/* CSR88-89: Chip ID masks */
-#define AMD_MASK  0x003
-#define PART_MASK 0xffff
-#define Am79C960  0x0003
-#define Am79C961  0x2260
-#define Am79C961A 0x2261
-#define Am79C965  0x2430
-#define Am79C970  0x0242
-#define Am79C970A 0x2621
-#define Am79C971  0x2623
-#define Am79C972  0x2624
-#define Am79C973  0x2625
-#define Am79C978  0x2626
-
-/* Board types */
-#define UNKNOWN         0
-#define BICC            1
-#define NE2100          2
-#define DEPCA           3
-#define CNET98S         4      /* PC-98 */
-
-/* mem_mode values */
-#define DMA_FIXED       1
-#define DMA_MBUF        2
-#define SHMEM           4
-
-#define MEM_MODES \
-       "\20\3SHMEM\2DMA_MBUF\1DMA_FIXED"
-
-#define CSR0_FLAGS \
-       "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\
-           \10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
-
-#define INIT_MODE \
-       "\20\20PROM\07INTL\06DRTY\05COLL\04DTCR\03LOOP\02DTX\01DRX"
-
-#define RECV_MD1 \
-       "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP"
-
-#define TRANS_MD1 \
-       "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP"
-
-#define TRANS_MD3 \
-       "\20\6BUFF\5UFLO\4RES\3LCOL\2LCAR\1RTRY"
-
-#ifdef LNC_KEEP_STATS
-#define LNCSTATS_STRUCT \
-       struct lnc_stats { \
-               int idon; \
-               int rint; \
-               int tint; \
-               int cerr; \
-               int babl; \
-               int miss; \
-               int merr; \
-               int rxoff; \
-               int txoff; \
-               int terr; \
-               int lcol; \
-               int lcar; \
-               int tbuff; \
-               int def; \
-               int more; \
-               int one; \
-               int uflo; \
-               int rtry; \
-               int rerr; \
-               int fram; \
-               int oflo; \
-               int crc; \
-               int rbuff; \
-               int drop_packet; \
-               int trans_ring_full; \
-       } lnc_stats;
-#define LNCSTATS(X) ++(sc->lnc_stats.X);
-#else
-#define LNCSTATS_STRUCT
-#define LNCSTATS(X)
-#endif
-
-struct nic_info {
-       int ident;         /* Type of card */
-       int ic;            /* Type of ic, Am7990, Am79C960 etc. */
-       int mem_mode;
-       int iobase;
-       int mode;          /* Mode setting at initialization */
-};
-
-typedef struct lnc_softc {
-       struct resource *irqres;
-       int irqrid;
-       struct resource *drqres;
-       int drqrid;
-       struct resource *portres;
-       int portrid;
-       bus_space_tag_t lnc_btag;
-       bus_space_handle_t lnc_bhandle;
-       void *intrhand;
-       bus_dma_tag_t   dmat;
-       bus_dmamap_t    dmamap;
-       struct arpcom arpcom;               /* see ../../net/if_arp.h */
-       struct nic_info nic;                /* NIC specific info */
-       int nrdre;
-       struct host_ring_entry *recv_ring;  /* start of alloc'd mem */
-       int recv_next;
-       int ntdre;
-       struct host_ring_entry *trans_ring;
-       int trans_next;
-       struct init_block *init_block;      /* Initialisation block */
-       int pending_transmits;        /* No. of transmit descriptors in
-       use */
-       int next_to_send;
-       struct mbuf *mbufs;
-       int mbuf_count;
-       int flags;
-       int rap;
-       int rdp;
-       int bdp;
-       #ifdef DEBUG
-       int lnc_debug;
-       #endif
-       LNCSTATS_STRUCT
-} lnc_softc_t;
-
-struct host_ring_entry {
-       struct mds *md;
-       union {
-               struct mbuf *mbuf;
-               char *data;
-       }buff;
-};
-
-#define NDESC(len2) (1 << len2)
-
-#define INC_MD_PTR(ptr, no_entries) \
-       if (++ptr >= NDESC(no_entries)) \
-               ptr = 0;
-
-#define DEC_MD_PTR(ptr, no_entries) \
-       if (--ptr < 0) \
-               ptr = NDESC(no_entries) - 1;
-
-#define RECV_NEXT (sc->recv_ring->base + sc->recv_next)
-#define TRANS_NEXT (sc->trans_ring->base + sc->trans_next)
-
-#define lnc_inb(port) \
-       bus_space_read_1(sc->lnc_btag, sc->lnc_bhandle, (port))
-#define lnc_inw(port) \
-       bus_space_read_2(sc->lnc_btag, sc->lnc_bhandle, (port))
-#define lnc_outw(port, val) \
-       bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, (port), (val))
-
-/* Functional declarations */
-extern int lance_probe(struct lnc_softc *);
-extern int lnc_attach_common(device_t);
-extern void lnc_stop(struct lnc_softc *);
-
-extern void write_csr(struct lnc_softc *, u_short, u_short);
-extern u_short read_csr(struct lnc_softc *, u_short);
-
-/* Variable declarations */
-extern driver_intr_t lncintr; 
-extern devclass_t lnc_devclass;
diff --git a/sys/dev/netif/lnc/lance.c b/sys/dev/netif/lnc/lance.c
new file mode 100644 (file)
index 0000000..c83df33
--- /dev/null
@@ -0,0 +1,767 @@
+/*     $NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry Exp $ */
+/*     $FreeBSD: src/sys/dev/le/lance.c,v 1.2 2006/05/16 21:04:01 marius Exp $ */
+/*     $DragonFly: src/sys/dev/netif/lnc/lance.c,v 1.1 2006/07/07 14:16:29 sephe Exp $ */
+
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_le.c     8.2 (Berkeley) 11/16/93
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/ifq_var.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/vlan/if_vlan_var.h>
+
+#include <machine/bus.h>
+
+#include <dev/netif/lnc/lancereg.h>
+#include <dev/netif/lnc/lancevar.h>
+
+devclass_t le_devclass;
+
+static void lance_start(struct ifnet *);
+static void lance_init(void *);
+static void lance_watchdog(struct ifnet *);
+static int lance_mediachange(struct ifnet *);
+static void lance_mediastatus(struct ifnet *, struct ifmediareq *);
+static int lance_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
+
+int
+lance_config(struct lance_softc *sc, const char* name, int unit)
+{
+       struct ifnet *ifp;
+       int i, nbuf;
+
+       ifp = sc->ifp = &sc->sc_if;
+
+       /* Initialize ifnet structure. */
+       ifp->if_softc = sc;
+       if_initname(ifp, name, unit);
+       ifp->if_start = lance_start;
+       ifp->if_ioctl = lance_ioctl;
+       ifp->if_watchdog = lance_watchdog;
+       ifp->if_init = lance_init;
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+#ifdef LANCE_REVC_BUG
+       ifp->if_flags &= ~IFF_MULTICAST;
+#endif
+       ifp->if_baudrate = IF_Mbps(10);
+       ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
+       ifq_set_ready(&ifp->if_snd);
+
+       /* Initialize ifmedia structures. */
+       ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus);
+       if (sc->sc_supmedia != NULL) {
+               for (i = 0; i < sc->sc_nsupmedia; i++)
+                       ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 0, NULL);
+               ifmedia_set(&sc->sc_media, sc->sc_defaultmedia);
+       } else {
+               ifmedia_add(&sc->sc_media,
+                   IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0), 0, NULL);
+               ifmedia_set(&sc->sc_media,
+                   IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0));
+       }
+
+       switch (sc->sc_memsize) {
+       case 8192:
+               sc->sc_nrbuf = 4;
+               sc->sc_ntbuf = 1;
+               break;
+       case 16384:
+               sc->sc_nrbuf = 8;
+               sc->sc_ntbuf = 2;
+               break;
+       case 32768:
+               sc->sc_nrbuf = 16;
+               sc->sc_ntbuf = 4;
+               break;
+       case 65536:
+               sc->sc_nrbuf = 32;
+               sc->sc_ntbuf = 8;
+               break;
+       case 131072:
+               sc->sc_nrbuf = 64;
+               sc->sc_ntbuf = 16;
+               break;
+       case 262144:
+               sc->sc_nrbuf = 128;
+               sc->sc_ntbuf = 32;
+               break;
+       default:
+               /* weird memory size; cope with it */
+               nbuf = sc->sc_memsize / LEBLEN;
+               sc->sc_ntbuf = nbuf / 5;
+               sc->sc_nrbuf = nbuf - sc->sc_ntbuf;
+       }
+
+       if_printf(ifp, "%d receive buffers, %d transmit buffers\n",
+           sc->sc_nrbuf, sc->sc_ntbuf);
+
+       /* Make sure the chip is stopped. */
+       lance_stop(sc);
+
+       return (0);
+}
+
+void
+lance_attach(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+
+       /* Attach the interface. */
+       ether_ifattach(ifp, sc->sc_enaddr, NULL);
+
+       /* Claim 802.1q capability. */
+       ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
+       ifp->if_capabilities |= IFCAP_VLAN_MTU;
+       ifp->if_capenable |= IFCAP_VLAN_MTU;
+}
+
+void
+lance_suspend(struct lance_softc *sc)
+{
+
+       lwkt_serialize_enter(sc->ifp->if_serializer);
+       lance_stop(sc);
+       lwkt_serialize_exit(sc->ifp->if_serializer);
+}
+
+void
+lance_resume(struct lance_softc *sc)
+{
+
+       lwkt_serialize_enter(sc->ifp->if_serializer);
+       if (sc->ifp->if_flags & IFF_UP)
+               lance_init_locked(sc);
+       lwkt_serialize_exit(sc->ifp->if_serializer);
+}
+
+static void
+lance_start(struct ifnet *ifp)
+{
+       struct lance_softc *sc = ifp->if_softc;
+
+       (*sc->sc_start_locked)(sc);
+}
+
+void
+lance_stop(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+
+       /*
+        * Mark the interface down and cancel the watchdog timer.
+        */
+       ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+       ifp->if_timer = 0;
+
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
+}
+
+static void
+lance_init(void *xsc)
+{
+       struct lance_softc *sc = (struct lance_softc *)xsc;
+
+       crit_enter();
+       lance_init_locked(sc);
+       crit_exit();
+}
+
+/*
+ * Initialization of interface; set up initialization block
+ * and transmit/receive descriptor rings.
+ */
+void
+lance_init_locked(struct lance_softc *sc)
+{
+       struct ifnet *ifp = sc->ifp;
+       u_long a;
+       int timo;
+
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
+       DELAY(100);
+
+       /* Newer LANCE chips have a reset register. */
+       if (sc->sc_hwreset)
+               (*sc->sc_hwreset)(sc);
+
+       /* Set the correct byte swapping mode, etc. */
+       (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
+
+       /*
+        * Update our private copy of the Ethernet address.
+        * We NEED the copy so we can ensure its alignment!
+        */
+       memcpy(sc->sc_enaddr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
+
+       /* Set up LANCE init block. */
+       (*sc->sc_meminit)(sc);
+
+       /* Give LANCE the physical address of its init block. */
+       a = sc->sc_addr + LE_INITADDR(sc);
+       (*sc->sc_wrcsr)(sc, LE_CSR1, a & 0xffff);
+       (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
+
+       /* Try to initialize the LANCE. */
+       DELAY(100);
+       (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
+
+       /* Wait for initialization to finish. */
+       for (timo = 100000; timo; timo--)
+               if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
+                       break;
+
+       /* Set the current media. */
+       if (sc->sc_mediachange)
+               (void)(*sc->sc_mediachange)(sc);
+
+       if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
+               /* Start the LANCE. */
+               (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT);
+               ifp->if_flags |= IFF_RUNNING;
+               ifp->if_flags &= ~IFF_OACTIVE;
+               ifp->if_timer = 0;
+               (*sc->sc_start_locked)(sc);
+       } else
+               if_printf(ifp, "controller failed to initialize\n");
+
+       if (sc->sc_hwinit)
+               (*sc->sc_hwinit)(sc);
+}
+
+/*
+ * Routine to copy from mbuf chain to transmit buffer in
+ * network buffer memory.
+ */
+int
+lance_put(struct lance_softc *sc, int boff, struct mbuf *m)
+{
+       struct mbuf *n;
+       int len, tlen = 0;
+
+       for (; m; m = n) {
+               len = m->m_len;
+               if (len == 0) {
+                       n = m_free(m);
+                       m = NULL;
+                       continue;
+               }
+               (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
+               boff += len;
+               tlen += len;
+               n = m_free(m);
+               m = NULL;
+       }
+       if (tlen < LEMINSIZE) {
+               (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
+               tlen = LEMINSIZE;
+       }
+       return (tlen);
+}
+
+/*
+ * Pull data off an interface.
+ * Len is length of data, with local net header stripped.
+ * We copy the data into mbufs.  When full cluster sized units are present
+ * we copy into clusters.
+ */
+struct mbuf *
+lance_get(struct lance_softc *sc, int boff, int totlen)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct mbuf *m, *m0, *newm;
+       caddr_t newdata;
+       int len;
+
+       if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) {
+#ifdef LEDEBUG
+               if_printf(ifp, "invalid packet size %d; dropping\n", totlen);
+#endif
+               return (NULL);
+       }
+
+       MGETHDR(m0, MB_DONTWAIT, MT_DATA);
+       if (m0 == NULL)
+               return (NULL);
+       m0->m_pkthdr.rcvif = ifp;
+       m0->m_pkthdr.len = totlen;
+       len = MHLEN;
+       m = m0;
+
+       while (totlen > 0) {
+               if (totlen >= MINCLSIZE) {
+                       MCLGET(m, MB_DONTWAIT);
+                       if ((m->m_flags & M_EXT) == 0)
+                               goto bad;
+                       len = MCLBYTES;
+               }
+
+               if (m == m0) {
+                       newdata = (caddr_t)
+                           ALIGN(m->m_data + ETHER_HDR_LEN) - ETHER_HDR_LEN;
+                       len -= newdata - m->m_data;
+                       m->m_data = newdata;
+               }
+
+               m->m_len = len = min(totlen, len);
+               (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
+               boff += len;
+
+               totlen -= len;
+               if (totlen > 0) {
+                       MGET(newm, MB_DONTWAIT, MT_DATA);
+                       if (newm == 0)
+                               goto bad;
+                       len = MLEN;
+                       m = m->m_next = newm;
+               }
+       }
+
+       return (m0);
+
+ bad:
+       m_freem(m0);
+       return (NULL);
+}
+
+static void
+lance_watchdog(struct ifnet *ifp)
+{
+       struct lance_softc *sc = ifp->if_softc;
+
+       if_printf(ifp, "device timeout\n");
+       ++ifp->if_oerrors;
+       lance_init_locked(sc);
+}
+
+static int
+lance_mediachange(struct ifnet *ifp)
+{
+       struct lance_softc *sc = ifp->if_softc;
+       int error;
+
+       if (sc->sc_mediachange) {
+               error = (*sc->sc_mediachange)(sc);
+               return (error);
+       }
+       return (0);
+}
+
+static void
+lance_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+       struct lance_softc *sc = ifp->if_softc;
+
+       if (!(ifp->if_flags & IFF_UP)) {
+               return;
+       }
+
+       ifmr->ifm_status = IFM_AVALID;
+       if (sc->sc_flags & LE_CARRIER)
+               ifmr->ifm_status |= IFM_ACTIVE;
+
+       if (sc->sc_mediastatus)
+               (*sc->sc_mediastatus)(sc, ifmr);
+}
+
+/*
+ * Process an ioctl request.
+ */
+static int
+lance_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr)
+{
+       struct lance_softc *sc = ifp->if_softc;
+       struct ifreq *ifr = (struct ifreq *)data;
+       int error = 0;
+
+       crit_enter();
+
+       switch (cmd) {
+       case SIOCSIFFLAGS:
+               if (ifp->if_flags & IFF_PROMISC) {
+                       if (!(sc->sc_flags & LE_PROMISC)) {
+                               sc->sc_flags |= LE_PROMISC;
+                               lance_init_locked(sc);
+                       }
+               } else if (sc->sc_flags & LE_PROMISC) {
+                       sc->sc_flags &= ~LE_PROMISC;
+                       lance_init_locked(sc);
+               }
+
+               if ((ifp->if_flags & IFF_ALLMULTI) &&
+                   !(sc->sc_flags & LE_ALLMULTI)) {
+                       sc->sc_flags |= LE_ALLMULTI;
+                       lance_init_locked(sc);
+               } else if (!(ifp->if_flags & IFF_ALLMULTI) &&
+                   (sc->sc_flags & LE_ALLMULTI)) {
+                       sc->sc_flags &= ~LE_ALLMULTI;
+                       lance_init_locked(sc);
+               }
+
+               if (!(ifp->if_flags & IFF_UP) &&
+                   ifp->if_flags & IFF_RUNNING) {
+                       /*
+                        * If interface is marked down and it is running, then
+                        * stop it.
+                        */
+                       lance_stop(sc);
+               } else if (ifp->if_flags & IFF_UP &&
+                   !(ifp->if_flags & IFF_RUNNING)) {
+                       /*
+                        * If interface is marked up and it is stopped, then
+                        * start it.
+                        */
+                       lance_init_locked(sc);
+               }
+#ifdef LEDEBUG
+               if (ifp->if_flags & IFF_DEBUG)
+                       sc->sc_flags |= LE_DEBUG;
+               else
+                       sc->sc_flags &= ~LE_DEBUG;
+#endif
+               break;
+
+       case SIOCADDMULTI:
+       case SIOCDELMULTI:
+               /*
+                * Multicast list has changed; set the hardware filter
+                * accordingly.
+                */
+               if (ifp->if_flags & IFF_RUNNING)
+                       lance_init_locked(sc);
+               break;
+
+       case SIOCGIFMEDIA:
+       case SIOCSIFMEDIA:
+               error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
+               break;
+
+       default:
+               error = ether_ioctl(ifp, cmd, data);
+               break;
+       }
+
+       crit_exit();
+
+       return (error);
+}
+
+/*
+ * Set up the logical address filter.
+ */
+void
+lance_setladrf(struct lance_softc *sc, uint16_t *af)
+{
+       struct ifnet *ifp = sc->ifp;
+       struct ifmultiaddr *ifma;
+       uint32_t crc;
+
+       /*
+        * Set up multicast address filter by passing all multicast addresses
+        * through a crc generator, and then using the high order 6 bits as an
+        * index into the 64 bit logical address filter.  The high order bit
+        * selects the word, while the rest of the bits select the bit within
+        * the word.
+        */
+
+       if (ifp->if_flags & IFF_PROMISC || sc->sc_flags & LE_ALLMULTI) {
+               af[0] = af[1] = af[2] = af[3] = 0xffff;
+               return;
+       }
+
+       af[0] = af[1] = af[2] = af[3] = 0x0000;
+
+       LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+               if (ifma->ifma_addr->sa_family != AF_LINK)
+                       continue;
+
+               crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
+                   ifma->ifma_addr), ETHER_ADDR_LEN);
+
+               /* Just want the 6 most significant bits. */
+               crc >>= 26;
+
+               /* Set the corresponding bit in the filter. */
+               af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf));
+       }
+}
+
+/*
+ * Routines for accessing the transmit and receive buffers.
+ * The various CPU and adapter configurations supported by this
+ * driver require three different access methods for buffers
+ * and descriptors:
+ *     (1) contig (contiguous data; no padding),
+ *     (2) gap2 (two bytes of data followed by two bytes of padding),
+ *     (3) gap16 (16 bytes of data followed by 16 bytes of padding).
+ */
+
+/*
+ * contig: contiguous data with no padding.
+ *
+ * Buffers may have any alignment.
+ */
+
+void
+lance_copytobuf_contig(struct lance_softc *sc, void *from, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+
+       /*
+        * Just call memcpy() to do the work.
+        */
+       memcpy(buf + boff, from, len);
+}
+
+void
+lance_copyfrombuf_contig(struct lance_softc *sc, void *to, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+
+       /*
+        * Just call memcpy() to do the work.
+        */
+       memcpy(to, buf + boff, len);
+}
+
+void
+lance_zerobuf_contig(struct lance_softc *sc, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+
+       /*
+        * Just let memset() do the work
+        */
+       memset(buf + boff, 0, len);
+}
+
+#if 0
+/*
+ * Examples only; duplicate these and tweak (if necessary) in
+ * machine-specific front-ends.
+ */
+
+/*
+ * gap2: two bytes of data followed by two bytes of pad.
+ *
+ * Buffers must be 4-byte aligned.  The code doesn't worry about
+ * doing an extra byte.
+ */
+
+static void
+lance_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       caddr_t from = fromv;
+       volatile uint16_t *bptr;
+
+       if (boff & 0x1) {
+               /* Handle unaligned first byte. */
+               bptr = ((volatile uint16_t *)buf) + (boff - 1);
+               *bptr = (*from++ << 8) | (*bptr & 0xff);
+               bptr += 2;
+               len--;
+       } else
+               bptr = ((volatile uint16_t *)buf) + boff;
+       while (len > 1) {
+               *bptr = (from[1] << 8) | (from[0] & 0xff);
+               bptr += 2;
+               from += 2;
+               len -= 2;
+       }
+       if (len == 1)
+               *bptr = (uint16_t)*from;
+}
+
+static void
+lance_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       caddr_t to = tov;
+       volatile uint16_t *bptr;
+       uint16_t tmp;
+
+       if (boff & 0x1) {
+               /* Handle unaligned first byte. */
+               bptr = ((volatile uint16_t *)buf) + (boff - 1);
+               *to++ = (*bptr >> 8) & 0xff;
+               bptr += 2;
+               len--;
+       } else
+               bptr = ((volatile uint16_t *)buf) + boff;
+       while (len > 1) {
+               tmp = *bptr;
+               *to++ = tmp & 0xff;
+               *to++ = (tmp >> 8) & 0xff;
+               bptr += 2;
+               len -= 2;
+       }
+       if (len == 1)
+               *to = *bptr & 0xff;
+}
+
+static void
+lance_zerobuf_gap2(struct lance_softc *sc, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       volatile uint16_t *bptr;
+
+       if ((unsigned)boff & 0x1) {
+               bptr = ((volatile uint16_t *)buf) + (boff - 1);
+               *bptr &= 0xff;
+               bptr += 2;
+               len--;
+       } else
+               bptr = ((volatile uint16_t *)buf) + boff;
+       while (len > 0) {
+               *bptr = 0;
+               bptr += 2;
+               len -= 2;
+       }
+}
+
+/*
+ * gap16: 16 bytes of data followed by 16 bytes of pad.
+ *
+ * Buffers must be 32-byte aligned.
+ */
+
+static void
+lance_copytobuf_gap16(struct lance_softc *sc, void *fromv, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       caddr_t bptr, from = fromv;
+       int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               memcpy(bptr + boff, from, xfer);
+               from += xfer;
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
+}
+
+static void
+lance_copyfrombuf_gap16(struct lance_softc *sc, void *tov, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       caddr_t bptr, to = tov;
+       int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               memcpy(to, bptr + boff, xfer);
+               to += xfer;
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
+}
+
+static void
+lance_zerobuf_gap16(struct lance_softc *sc, int boff, int len)
+{
+       volatile caddr_t buf = sc->sc_mem;
+       caddr_t bptr;
+       int xfer;
+
+       bptr = buf + ((boff << 1) & ~0x1f);
+       boff &= 0xf;
+       xfer = min(len, 16 - boff);
+       while (len > 0) {
+               memset(bptr + boff, 0, xfer);
+               bptr += 32;
+               boff = 0;
+               len -= xfer;
+               xfer = min(len, 16);
+       }
+}
+#endif /* Example only */
diff --git a/sys/dev/netif/lnc/lancereg.h b/sys/dev/netif/lnc/lancereg.h
new file mode 100644 (file)
index 0000000..99ab1e2
--- /dev/null
@@ -0,0 +1,623 @@
+/*     $NetBSD: lancereg.h,v 1.12 2005/12/11 12:21:27 christos Exp $   */
+/*     $FreeBSD: src/sys/dev/le/lancereg.h,v 1.2 2006/05/16 21:04:01 marius Exp $      */
+/*     $DragonFly: src/sys/dev/netif/lnc/lancereg.h,v 1.1 2006/07/07 14:16:29 sephe Exp $      */
+
+/*-
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and Jason R. Thorpe.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ *     @(#)if_lereg.h  8.1 (Berkeley) 6/10/93
+ */
+
+/*
+ * Register description for the following Advanced Micro Devices
+ * Ethernet chips:
+ *
+ *     - Am7990 Local Area Network Controller for Ethernet (LANCE)
+ *       (and its descendent Am79c90 C-LANCE).
+ *
+ *     - Am79c900 Integrated Local Area Communications Controller (ILACC)
+ *
+ *     - Am79c960 PCnet-ISA Single-Chip Ethernet Controller for ISA
+ *
+ *     - Am79c961 PCnet-ISA+ Jumperless Single-Chip Ethernet Controller
+ *       for ISA
+ *
+ *     - Am79c961A PCnet-ISA II Jumperless Full-Duplex Single-Chip
+ *       Ethernet Controller for ISA
+ *
+ *     - Am79c965A PCnet-32 Single-Chip 32-bit Ethernet Controller
+ *       (for VESA and 486 local busses)
+ *
+ *     - Am79c970 PCnet-PCI Single-Chip Ethernet Controller for PCI
+ *       Local Bus
+ *
+ *     - Am79c970A PCnet-PCI II Single-Chip Full-Duplex Ethernet Controller
+ *       for PCI Local Bus
+ *
+ *     - Am79c971 PCnet-FAST Single-Chip Full-Duplex 10/100Mbps
+ *       Ethernet Controller for PCI Local Bus
+ *
+ *     - Am79c972 PCnet-FAST+ Enhanced 10/100Mbps PCI Ethernet Controller
+ *       with OnNow Support
+ *
+ *     - Am79c973/Am79c975 PCnet-FAST III Single-Chip 10/100Mbps PCI
+ *       Ethernet Controller with Integrated PHY
+ *
+ *     - Am79c978 PCnet-Home Single-Chip 1/10 Mbps PCI Home
+ *       Networking Controller.
+ *
+ * Initialization block, transmit descriptor, and receive descriptor
+ * formats are described in two separate files:
+ *
+ *     16-bit software model (LANCE)           am7990reg.h
+ *
+ *     32-bit software model (ILACC)           am79900reg.h
+ *
+ * Note that the vast majority of the registers described in this file
+ * belong to follow-on chips to the original LANCE.  Only CSR0-CSR3 are
+ * valid on the LANCE.
+ */
+
+#ifndef _DEV_LE_LANCEREG_H_
+#define        _DEV_LE_LANCEREG_H_
+
+#ifndef ETHER_VLAN_ENCAP_LEN
+#define ETHER_VLAN_ENCAP_LEN   4
+#endif
+
+#define        LEBLEN          (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN)
+/* LEMINSIZE should be ETHER_MIN_LEN when LE_MODE_DTCR is set. */
+#define        LEMINSIZE       (ETHER_MIN_LEN - ETHER_CRC_LEN)
+
+#define        LE_INITADDR(sc)         (sc->sc_initaddr)
+#define        LE_RMDADDR(sc, bix)     (sc->sc_rmdaddr + sizeof(struct lermd) * (bix))
+#define        LE_TMDADDR(sc, bix)     (sc->sc_tmdaddr + sizeof(struct letmd) * (bix))
+#define        LE_RBUFADDR(sc, bix)    (sc->sc_rbufaddr + LEBLEN * (bix))
+#define        LE_TBUFADDR(sc, bix)    (sc->sc_tbufaddr + LEBLEN * (bix))
+
+/*
+ * The byte count fields in descriptors are in two's complement.
+ * This macro does the conversion for us on unsigned numbers.
+ */
+#define        LE_BCNT(x)      (~(x) + 1)
+
+/*
+ * Control and Status Register addresses
+ */
+#define        LE_CSR0         0x0000          /* Control and status register */
+#define        LE_CSR1         0x0001          /* low address of init block */
+#define        LE_CSR2         0x0002          /* high address of init block */
+#define        LE_CSR3         0x0003          /* Bus master and control */
+#define        LE_CSR4         0x0004          /* Test and features control */
+#define        LE_CSR5         0x0005          /* Extended control and Interrupt 1 */
+#define        LE_CSR6         0x0006          /* Rx/Tx Descriptor table length */
+#define        LE_CSR7         0x0007          /* Extended control and interrupt 2 */
+#define        LE_CSR8         0x0008          /* Logical Address Filter 0 */
+#define        LE_CSR9         0x0009          /* Logical Address Filter 1 */
+#define        LE_CSR10        0x000a          /* Logical Address Filter 2 */
+#define        LE_CSR11        0x000b          /* Logical Address Filter 3 */
+#define        LE_CSR12        0x000c          /* Physical Address 0 */
+#define        LE_CSR13        0x000d          /* Physical Address 1 */
+#define        LE_CSR14        0x000e          /* Physical Address 2 */
+#define        LE_CSR15        0x000f          /* Mode */
+#define        LE_CSR16        0x0010          /* Initialization Block addr lower */
+#define        LE_CSR17        0x0011          /* Initialization Block addr upper */
+#define        LE_CSR18        0x0012          /* Current Rx Buffer addr lower */
+#define        LE_CSR19        0x0013          /* Current Rx Buffer addr upper */
+#define        LE_CSR20        0x0014          /* Current Tx Buffer addr lower */
+#define        LE_CSR21        0x0015          /* Current Tx Buffer addr upper */
+#define        LE_CSR22        0x0016          /* Next Rx Buffer addr lower */
+#define        LE_CSR23        0x0017          /* Next Rx Buffer addr upper */
+#define        LE_CSR24        0x0018          /* Base addr of Rx ring lower */
+#define        LE_CSR25        0x0019          /* Base addr of Rx ring upper */
+#define        LE_CSR26        0x001a          /* Next Rx Desc addr lower */
+#define        LE_CSR27        0x001b          /* Next Rx Desc addr upper */
+#define        LE_CSR28        0x001c          /* Current Rx Desc addr lower */
+#define        LE_CSR29        0x001d          /* Current Rx Desc addr upper */
+#define        LE_CSR30        0x001e          /* Base addr of Tx ring lower */
+#define        LE_CSR31        0x001f          /* Base addr of Tx ring upper */
+#define        LE_CSR32        0x0020          /* Next Tx Desc addr lower */
+#define        LE_CSR33        0x0021          /* Next Tx Desc addr upper */
+#define        LE_CSR34        0x0022          /* Current Tx Desc addr lower */
+#define        LE_CSR35        0x0023          /* Current Tx Desc addr upper */
+#define        LE_CSR36        0x0024          /* Next Next Rx Desc addr lower */
+#define        LE_CSR37        0x0025          /* Next Next Rx Desc addr upper */
+#define        LE_CSR38        0x0026          /* Next Next Tx Desc addr lower */
+#define        LE_CSR39        0x0027          /* Next Next Tx Desc adddr upper */
+#define        LE_CSR40        0x0028          /* Current Rx Byte Count */
+#define        LE_CSR41        0x0029          /* Current Rx Status */
+#define        LE_CSR42        0x002a          /* Current Tx Byte Count */
+#define        LE_CSR43        0x002b          /* Current Tx Status */
+#define        LE_CSR44        0x002c          /* Next Rx Byte Count */
+#define        LE_CSR45        0x002d          /* Next Rx Status */
+#define        LE_CSR46        0x002e          /* Tx Poll Time Counter */
+#define        LE_CSR47        0x002f          /* Tx Polling Interval */
+#define        LE_CSR48        0x0030          /* Rx Poll Time Counter */
+#define        LE_CSR49        0x0031          /* Rx Polling Interval */
+#define        LE_CSR58        0x003a          /* Software Style */
+#define        LE_CSR60        0x003c          /* Previous Tx Desc addr lower */
+#define        LE_CSR61        0x003d          /* Previous Tx Desc addr upper */
+#define        LE_CSR62        0x003e          /* Previous Tx Byte Count */
+#define        LE_CSR63        0x003f          /* Previous Tx Status */
+#define        LE_CSR64        0x0040          /* Next Tx Buffer addr lower */
+#define        LE_CSR65        0x0041          /* Next Tx Buffer addr upper */
+#define        LE_CSR66        0x0042          /* Next Tx Byte Count */
+#define        LE_CSR67        0x0043          /* Next Tx Status */
+#define        LE_CSR72        0x0048          /* Receive Ring Counter */
+#define        LE_CSR74        0x004a          /* Transmit Ring Counter */
+#define        LE_CSR76        0x004c          /* Receive Ring Length */
+#define        LE_CSR78        0x004e          /* Transmit Ring Length */
+#define        LE_CSR80        0x0050          /* DMA Transfer Counter and FIFO
+                                          Threshold Control */
+#define        LE_CSR82        0x0052          /* Tx Desc addr Pointer lower */
+#define        LE_CSR84        0x0054          /* DMA addr register lower */
+#define        LE_CSR85        0x0055          /* DMA addr register upper */
+#define        LE_CSR86        0x0056          /* Buffer Byte Counter */
+#define        LE_CSR88        0x0058          /* Chip ID Register lower */
+#define        LE_CSR89        0x0059          /* Chip ID Register upper */
+#define        LE_CSR92        0x005c          /* Ring Length Conversion */
+#define        LE_CSR100       0x0064          /* Bus Timeout */
+#define        LE_CSR112       0x0070          /* Missed Frame Count */
+#define        LE_CSR114       0x0072          /* Receive Collision Count */
+#define        LE_CSR116       0x0074          /* OnNow Power Mode Register */
+#define        LE_CSR122       0x007a          /* Advanced Feature Control */
+#define        LE_CSR124       0x007c          /* Test Register 1 */
+#define        LE_CSR125       0x007d          /* MAC Enhanced Configuration Control */
+
+/*
+ * Bus Configuration Register addresses
+ */
+#define        LE_BCR0         0x0000          /* Master Mode Read Active */
+#define        LE_BCR1         0x0001          /* Master Mode Write Active */
+#define        LE_BCR2         0x0002          /* Misc. Configuration */
+#define        LE_BCR4         0x0004          /* LED0 Status */
+#define        LE_BCR5         0x0005          /* LED1 Status */
+#define        LE_BCR6         0x0006          /* LED2 Status */
+#define        LE_BCR7         0x0007          /* LED3 Status */
+#define        LE_BCR9         0x0009          /* Full-duplex Control */
+#define        LE_BCR16        0x0010          /* I/O Base Address lower */
+#define        LE_BCR17        0x0011          /* I/O Base Address upper */
+#define        LE_BCR18        0x0012          /* Burst and Bus Control Register */
+#define        LE_BCR19        0x0013          /* EEPROM Control and Status */
+#define        LE_BCR20        0x0014          /* Software Style */
+#define        LE_BCR22        0x0016          /* PCI Latency Register */
+#define        LE_BCR23        0x0017          /* PCI Subsystem Vendor ID */
+#define        LE_BCR24        0x0018          /* PCI Subsystem ID */
+#define        LE_BCR25        0x0019          /* SRAM Size Register */
+#define        LE_BCR26        0x001a          /* SRAM Boundary Register */
+#define        LE_BCR27        0x001b          /* SRAM Interface Control Register */
+#define        LE_BCR28        0x001c          /* Exp. Bus Port Addr lower */
+#define        LE_BCR29        0x001d          /* Exp. Bus Port Addr upper */
+#define        LE_BCR30        0x001e          /* Exp. Bus Data Port */
+#define        LE_BCR31        0x001f          /* Software Timer Register */
+#define        LE_BCR32        0x0020          /* PHY Control and Status Register */
+#define        LE_BCR33        0x0021          /* PHY Address Register */
+#define        LE_BCR34        0x0022          /* PHY Management Data Register */
+#define        LE_BCR35        0x0023          /* PCI Vendor ID Register */
+#define        LE_BCR36        0x0024          /* PCI Power Management Cap. Alias */
+#define        LE_BCR37        0x0025          /* PCI DATA0 Alias */
+#define        LE_BCR38        0x0026          /* PCI DATA1 Alias */
+#define        LE_BCR39        0x0027          /* PCI DATA2 Alias */
+#define        LE_BCR40        0x0028          /* PCI DATA3 Alias */
+#define        LE_BCR41        0x0029          /* PCI DATA4 Alias */
+#define        LE_BCR42        0x002a          /* PCI DATA5 Alias */
+#define        LE_BCR43        0x002b          /* PCI DATA6 Alias */
+#define        LE_BCR44        0x002c          /* PCI DATA7 Alias */
+#define        LE_BCR45        0x002d          /* OnNow Pattern Matching 1 */
+#define        LE_BCR46        0x002e          /* OnNow Pattern Matching 2 */
+#define        LE_BCR47        0x002f          /* OnNow Pattern Matching 3 */
+#define        LE_BCR48        0x0030          /* LED4 Status */
+#define        LE_BCR49        0x0031          /* PHY Select */
+
+/* Control and status register 0 (csr0) */
+#define        LE_C0_ERR       0x8000          /* error summary */
+#define        LE_C0_BABL      0x4000          /* transmitter timeout error */
+#define        LE_C0_CERR      0x2000          /* collision */
+#define        LE_C0_MISS      0x1000          /* missed a packet */
+#define        LE_C0_MERR      0x0800          /* memory error */
+#define        LE_C0_RINT      0x0400          /* receiver interrupt */
+#define        LE_C0_TINT      0x0200          /* transmitter interrupt */
+#define        LE_C0_IDON      0x0100          /* initialization done */
+#define        LE_C0_INTR      0x0080          /* interrupt condition */
+#define        LE_C0_INEA      0x0040          /* interrupt enable */
+#define        LE_C0_RXON      0x0020          /* receiver on */
+#define        LE_C0_TXON      0x0010          /* transmitter on */
+#define        LE_C0_TDMD      0x0008          /* transmit demand */
+#define        LE_C0_STOP      0x0004          /* disable all external activity */
+#define        LE_C0_STRT      0x0002          /* enable external activity */
+#define        LE_C0_INIT      0x0001          /* begin initialization */
+
+#define        LE_C0_BITS \
+    "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\
+\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"
+
+/* Control and status register 3 (csr3) */
+#define        LE_C3_BABLM     0x4000          /* babble mask */
+#define        LE_C3_MISSM     0x1000          /* missed frame mask */
+#define        LE_C3_MERRM     0x0800          /* memory error mask */
+#define        LE_C3_RINTM     0x0400          /* receive interrupt mask */
+#define        LE_C3_TINTM     0x0200          /* transmit interrupt mask */
+#define        LE_C3_IDONM     0x0100          /* initialization done mask */
+#define        LE_C3_DXSUFLO   0x0040          /* disable tx stop on underflow */
+#define        LE_C3_LAPPEN    0x0020          /* look ahead packet processing enbl */
+#define        LE_C3_DXMT2PD   0x0010          /* disable tx two part deferral */
+#define        LE_C3_EMBA      0x0008          /* enable modified backoff algorithm */
+#define        LE_C3_BSWP      0x0004          /* byte swap */
+#define        LE_C3_ACON      0x0002          /* ALE control, eh? */
+#define        LE_C3_BCON      0x0001          /* byte control */
+
+/* Control and status register 4 (csr4) */
+#define        LE_C4_EN124     0x8000          /* enable CSR124 */
+#define        LE_C4_DMAPLUS   0x4000          /* always set (PCnet-PCI) */
+#define        LE_C4_TIMER     0x2000          /* enable bus activity timer */
+#define        LE_C4_TXDPOLL   0x1000          /* disable transmit polling */
+#define        LE_C4_APAD_XMT  0x0800          /* auto pad transmit */
+#define        LE_C4_ASTRP_RCV 0x0400          /* auto strip receive */
+#define        LE_C4_MFCO      0x0200          /* missed frame counter overflow */
+#define        LE_C4_MFCOM     0x0100          /* missed frame coutner overflow mask */
+#define        LE_C4_UINTCMD   0x0080          /* user interrupt command */
+#define        LE_C4_UINT      0x0040          /* user interrupt */
+#define        LE_C4_RCVCCO    0x0020          /* receive collision counter overflow */
+#define        LE_C4_RCVCCOM   0x0010          /* receive collision counter overflow
+                                          mask */
+#define        LE_C4_TXSTRT    0x0008          /* transmit start status */
+#define        LE_C4_TXSTRTM   0x0004          /* transmit start mask */
+
+/* Control and status register 5 (csr5) */
+#define        LE_C5_TOKINTD   0x8000          /* transmit ok interrupt disable */
+#define        LE_C5_LTINTEN   0x4000          /* last transmit interrupt enable */
+#define        LE_C5_SINT      0x0800          /* system interrupt */
+#define        LE_C5_SINTE     0x0400          /* system interrupt enable */
+#define        LE_C5_EXDINT    0x0080          /* excessive deferral interrupt */
+#define        LE_C5_EXDINTE   0x0040          /* excessive deferral interrupt enbl */
+#define        LE_C5_MPPLBA    0x0020          /* magic packet physical logical
+                                          broadcast accept */
+#define        LE_C5_MPINT     0x0010          /* magic packet interrupt */
+#define        LE_C5_MPINTE    0x0008          /* magic packet interrupt enable */
+#define        LE_C5_MPEN      0x0004          /* magic packet enable */
+#define        LE_C5_MPMODE    0x0002          /* magic packet mode */
+#define        LE_C5_SPND      0x0001          /* suspend */
+
+/* Control and status register 6 (csr6) */
+#define        LE_C6_TLEN      0xf000          /* TLEN from init block */
+#define        LE_C6_RLEN      0x0f00          /* RLEN from init block */
+
+/* Control and status register 7 (csr7) */
+#define        LE_C7_FASTSPNDE 0x8000          /* fast suspend enable */
+#define        LE_C7_RDMD      0x2000          /* receive demand */
+#define        LE_C7_RDXPOLL   0x1000          /* receive disable polling */
+#define        LE_C7_STINT     0x0800          /* software timer interrupt */
+#define        LE_C7_STINTE    0x0400          /* software timer interrupt enable */
+#define        LE_C7_MREINT    0x0200          /* PHY management read error intr */
+#define        LE_C7_MREINTE   0x0100          /* PHY management read error intr
+                                          enable */
+#define        LE_C7_MAPINT    0x0080          /* PHY management auto-poll intr */
+#define        LE_C7_MAPINTE   0x0040          /* PHY management auto-poll intr
+                                          enable */
+#define        LE_C7_MCCINT    0x0020          /* PHY management command complete
+                                          interrupt */
+#define        LE_C7_MCCINTE   0x0010          /* PHY management command complete
+                                          interrupt enable */
+#define        LE_C7_MCCIINT   0x0008          /* PHY management command complete
+                                          internal interrupt */
+#define        LE_C7_MCCIINTE  0x0004          /* PHY management command complete
+                                          internal interrupt enable */
+#define        LE_C7_MIIPDTINT 0x0002          /* PHY management detect transition
+                                          interrupt */
+#define        LE_C7_MIIPDTINTE 0x0001         /* PHY management detect transition
+                                          interrupt enable */
+
+/* Control and status register 15 (csr15) */
+#define        LE_C15_PROM     0x8000          /* promiscuous mode */
+#define        LE_C15_DRCVBC   0x4000          /* disable Rx of broadcast */
+#define        LE_C15_DRCVPA   0x2000          /* disable Rx of physical address */
+#define        LE_C15_DLNKTST  0x1000          /* disable link status */
+#define        LE_C15_DAPC     0x0800          /* disable auto-polarity correction */
+#define        LE_C15_MENDECL  0x0400          /* MENDEC Loopback mode */
+#define        LE_C15_LRT      0x0200          /* low receive threshold (TMAU) */
+#define        LE_C15_TSEL     0x0200          /* transmit mode select (AUI) */
+#define        LE_C15_PORTSEL(x) ((x) << 7)    /* port select */
+#define        LE_C15_INTL     0x0040          /* internal loopback */
+#define        LE_C15_DRTY     0x0020          /* disable retry */
+#define        LE_C15_FCOLL    0x0010          /* force collision */
+#define        LE_C15_DXMTFCS  0x0008          /* disable Tx FCS (ADD_FCS overrides) */
+#define        LE_C15_LOOP     0x0004          /* loopback enable */
+#define        LE_C15_DTX      0x0002          /* disable transmit */
+#define        LE_C15_DRX      0x0001          /* disable receiver */
+
+#define        LE_PORTSEL_AUI  0
+#define        LE_PORTSEL_10T  1
+#define        LE_PORTSEL_GPSI 2
+#define        LE_PORTSEL_MII  3
+#define        LE_PORTSEL_MASK 3
+
+/* control and status register 80 (csr80) */
+#define        LE_C80_RCVFW(x) ((x) << 12)     /* Receive FIFO Watermark */
+#define        LE_C80_RCVFW_MAX 3
+#define        LE_C80_XMTSP(x) ((x) << 10)     /* Transmit Start Point */
+#define        LE_C80_XMTSP_MAX 3
+#define        LE_C80_XMTFW(x) ((x) << 8)      /* Transmit FIFO Watermark */
+#define        LE_C80_XMTFW_MAX 3
+#define        LE_C80_DMATC    0x00ff          /* DMA transfer counter */
+
+/* control and status register 116 (csr116) */
+#define        LE_C116_PME_EN_OVR 0x0400       /* PME_EN overwrite */
+#define        LE_C116_LCDET      0x0200       /* link change detected */
+#define        LE_C116_LCMODE     0x0100       /* link change wakeup mode */
+#define        LE_C116_PMAT       0x0080       /* pattern matched */
+#define        LE_C116_EMPPLBA    0x0040       /* magic packet physical logical
+                                          broadcast accept */
+#define        LE_C116_MPMAT      0x0020       /* magic packet match */
+#define        LE_C116_MPPEN      0x0010       /* magic packet pin enable */
+#define        LE_C116_RST_POL    0x0001       /* PHY_RST pin polarity */
+
+/* control and status register 122 (csr122) */
+#define        LE_C122_RCVALGN 0x0001          /* receive packet align */
+
+/* control and status register 124 (csr124) */
+#define        LE_C124_RPA     0x0008          /* runt packet accept */
+
+/* control and status register 125 (csr125) */
+#define        LE_C125_IPG     0xff00          /* inter-packet gap */
+#define        LE_C125_IFS1    0x00ff          /* inter-frame spacing part 1 */
+
+/* bus configuration register 0 (bcr0) */
+#define        LE_B0_MSRDA     0xffff          /* reserved locations */
+
+/* bus configuration register 1 (bcr1) */
+#define        LE_B1_MSWRA     0xffff          /* reserved locations */
+
+/* bus configuration register 2 (bcr2) */
+#define        LE_B2_PHYSSELEN 0x2000          /* enable writes to BCR18[4:3] */
+#define        LE_B2_LEDPE     0x1000          /* LED program enable */
+#define        LE_B2_APROMWE   0x0100          /* Address PROM Write Enable */
+#define        LE_B2_INTLEVEL  0x0080          /* 1 == edge triggered */
+#define        LE_B2_DXCVRCTL  0x0020          /* DXCVR control */
+#define        LE_B2_DXCVRPOL  0x0010          /* DXCVR polarity */
+#define        LE_B2_EADISEL   0x0008          /* EADI select */
+#define        LE_B2_AWAKE     0x0004          /* power saving mode select */
+#define        LE_B2_ASEL      0x0002          /* auto-select PORTSEL */
+#define        LE_B2_XMAUSEL   0x0001          /* reserved location */
+
+/* bus configuration register 4 (bcr4) */
+/* bus configuration register 5 (bcr5) */
+/* bus configuration register 6 (bcr6) */
+/* bus configuration register 7 (bcr7) */
+/* bus configuration register 48 (bcr48) */
+#define        LE_B4_LEDOUT    0x8000          /* LED output active */
+#define        LE_B4_LEDPOL    0x4000          /* LED polarity */
+#define        LE_B4_LEDDIS    0x2000          /* LED disable */
+#define        LE_B4_100E      0x1000          /* 100Mb/s enable */
+#define        LE_B4_MPSE      0x0200          /* magic packet status enable */
+#define        LE_B4_FDLSE     0x0100          /* full-duplex link status enable */
+#define        LE_B4_PSE       0x0080          /* pulse stretcher enable */
+#define        LE_B4_LNKSE     0x0040          /* link status enable */
+#define        LE_B4_RCVME     0x0020          /* receive match status enable */
+#define        LE_B4_XMTE      0x0010          /* transmit status enable */
+#define        LE_B4_POWER     0x0008          /* power enable */
+#define        LE_B4_RCVE      0x0004          /* receive status enable */
+#define        LE_B4_SPEED     0x0002          /* high speed enable */
+#define        LE_B4_COLE      0x0001          /* collision status enable */
+
+/* bus configuration register 9 (bcr9) */
+#define        LE_B9_FDRPAD    0x0004          /* full-duplex runt packet accept
+                                          disable */
+#define        LE_B9_AUIFD     0x0002          /* AUI full-duplex */
+#define        LE_B9_FDEN      0x0001          /* full-duplex enable */
+
+/* bus configuration register 18 (bcr18) */
+#define        LE_B18_ROMTMG   0xf000          /* expansion rom timing */
+#define        LE_B18_NOUFLO   0x0800          /* no underflow on transmit */
+#define        LE_B18_MEMCMD   0x0200          /* memory read multiple enable */
+#define        LE_B18_EXTREQ   0x0100          /* extended request */
+#define        LE_B18_DWIO     0x0080          /* double-word I/O */
+#define        LE_B18_BREADE   0x0040          /* burst read enable */
+#define        LE_B18_BWRITE   0x0020          /* burst write enable */
+#define        LE_B18_PHYSEL1  0x0010          /* PHYSEL 1 */
+#define        LE_B18_PHYSEL0  0x0008          /* PHYSEL 0 */
+                                       /*      00      ex ROM/Flash    */
+                                       /*      01      EADI/MII snoop  */
+                                       /*      10      reserved        */
+                                       /*      11      reserved        */
+#define        LE_B18_LINBC    0x0007          /* reserved locations */
+
+/* bus configuration register 19 (bcr19) */
+#define        LE_B19_PVALID   0x8000          /* EEPROM status valid */
+#define        LE_B19_PREAD    0x4000          /* EEPROM read command */
+#define        LE_B19_EEDET    0x2000          /* EEPROM detect */
+#define        LE_B19_EEN      0x0010          /* EEPROM port enable */
+#define        LE_B19_ECS      0x0004          /* EEPROM chip select */
+#define        LE_B19_ESK      0x0002          /* EEPROM serial clock */
+#define        LE_B19_EDI      0x0001          /* EEPROM data in */
+#define        LE_B19_EDO      0x0001          /* EEPROM data out */
+
+/* bus configuration register 20 (bcr20) */
+#define        LE_B20_APERREN  0x0400          /* Advanced parity error handling */
+#define        LE_B20_CSRPCNET 0x0200          /* PCnet-style CSRs (0 = ILACC) */
+#define        LE_B20_SSIZE32  0x0100          /* Software Size 32-bit */
+#define        LE_B20_SSTYLE   0x0007          /* Software Style */
+#define        LE_B20_SSTYLE_LANCE     0       /* LANCE/PCnet-ISA (16-bit) */
+#define        LE_B20_SSTYLE_ILACC     1       /* ILACC (32-bit) */
+#define        LE_B20_SSTYLE_PCNETPCI2 2       /* PCnet-PCI (32-bit) */
+#define        LE_B20_SSTYLE_PCNETPCI3 3       /* PCnet-PCI II (32-bit) */
+
+/* bus configuration register 25 (bcr25) */
+#define        LE_B25_SRAM_SIZE  0x00ff        /* SRAM size */
+
+/* bus configuration register 26 (bcr26) */
+#define        LE_B26_SRAM_BND   0x00ff        /* SRAM boundary */
+
+/* bus configuration register 27 (bcr27) */
+#define        LE_B27_PTRTST   0x8000          /* reserved for manuf. tests */
+#define        LE_B27_LOLATRX  0x4000          /* low latency receive */
+#define        LE_B27_EBCS     0x0038          /* expansion bus clock source */
+                                       /*      000     CLK pin         */
+                                       /*      001     time base clock */
+                                       /*      010     EBCLK pin       */
+                                       /*      011     reserved        */
+                                       /*      1xx     reserved        */
+#define        LE_B27_CLK_FAC  0x0007          /* clock factor */
+                                       /*      000     1               */
+                                       /*      001     1/2             */
+                                       /*      010     reserved        */
+                                       /*      011     1/4             */
+                                       /*      1xx     reserved        */
+
+/* bus configuration register 28 (bcr28) */
+#define        LE_B28_EADDRL   0xffff          /* expansion port address lower */
+
+/* bus configuration register 29 (bcr29) */
+#define        LE_B29_FLASH    0x8000          /* flash access */
+#define        LE_B29_LAAINC   0x4000          /* lower address auto increment */
+#define        LE_B29_EPADDRU  0x0007          /* expansion port address upper */
+
+/* bus configuration register 30 (bcr30) */
+#define        LE_B30_EBDATA   0xffff          /* expansion bus data port */
+
+/* bus configuration register 31 (bcr31) */
+#define        LE_B31_STVAL    0xffff          /* software timer value */
+
+/* bus configuration register 32 (bcr32) */
+#define        LE_B32_ANTST    0x8000          /* reserved for manuf. tests */
+#define        LE_B32_MIIPD    0x4000          /* MII PHY Detect (manuf. tests) */
+#define        LE_B32_FMDC     0x3000          /* fast management data clock */
+#define        LE_B32_APEP     0x0800          /* auto-poll PHY */
+#define        LE_B32_APDW     0x0700          /* auto-poll dwell time */
+#define        LE_B32_DANAS    0x0080          /* disable autonegotiation */
+#define        LE_B32_XPHYRST  0x0040          /* PHY reset */
+#define        LE_B32_XPHYANE  0x0020          /* PHY autonegotiation enable */
+#define        LE_B32_XPHYFD   0x0010          /* PHY full-duplex */
+#define        LE_B32_XPHYSP   0x0008          /* PHY speed */
+#define        LE_B32_MIIILP   0x0002          /* MII internal loopback */
+
+/* bus configuration register 33 (bcr33) */
+#define        LE_B33_SHADOW   0x8000          /* shadow enable */
+#define        LE_B33_MII_SEL  0x4000          /* MII selected */
+#define        LE_B33_ACOMP    0x2000          /* internal PHY autonegotiation comp */
+#define        LE_B33_LINK     0x1000          /* link status */
+#define        LE_B33_FDX      0x0800          /* full-duplex */
+#define        LE_B33_SPEED    0x0400          /* 1 == high speed */
+#define        LE_B33_PHYAD    0x03e0          /* PHY address */
+#define        PHYAD_SHIFT     5
+#define        LE_B33_REGAD    0x001f          /* register address */
+
+/* bus configuration register 34 (bcr34) */
+#define        LE_B34_MIIMD    0xffff          /* MII data */
+
+/* bus configuration register 49 (bcr49) */
+#define        LE_B49_PCNET    0x8000          /* PCnet mode - Must Be One */
+#define        LE_B49_PHYSEL_D 0x0300          /* PHY_SEL_Default */
+#define        LE_B49_PHYSEL_L 0x0010          /* PHY_SEL_Lock */
+#define        LE_B49_PHYSEL   0x0003          /* PHYSEL */
+                                       /*      00      10baseT PHY     */
+                                       /*      01      HomePNA PHY     */
+                                       /*      10      external PHY    */
+                                       /*      11      reserved        */
+
+/* Initialization block (mode) */
+#define        LE_MODE_PROM    0x8000          /* promiscuous mode */
+/*                     0x7f80             reserved, must be zero */
+/* 0x4000 - 0x0080 are not available on LANCE 7990. */
+#define        LE_MODE_DRCVBC  0x4000          /* disable receive brodcast */
+#define        LE_MODE_DRCVPA  0x2000          /* disable physical address detection */
+#define        LE_MODE_DLNKTST 0x1000          /* disable link status */
+#define        LE_MODE_DAPC    0x0800          /* disable automatic polarity correction */
+#define        LE_MODE_MENDECL 0x0400          /* MENDEC loopback mode */
+#define        LE_MODE_LRTTSEL 0x0200          /* lower receive threshold /
+                                          transmit mode selection */
+#define        LE_MODE_PSEL1   0x0100          /* port selection bit1 */
+#define        LE_MODE_PSEL0   0x0080          /* port selection bit0 */
+#define        LE_MODE_INTL    0x0040          /* internal loopback */
+#define        LE_MODE_DRTY    0x0020          /* disable retry */
+#define        LE_MODE_COLL    0x0010          /* force a collision */
+#define        LE_MODE_DTCR    0x0008          /* disable transmit CRC */
+#define        LE_MODE_LOOP    0x0004          /* loopback mode */
+#define        LE_MODE_DTX     0x0002          /* disable transmitter */
+#define        LE_MODE_DRX     0x0001          /* disable receiver */
+#define        LE_MODE_NORMAL  0               /* none of the above */
+
+/*
+ * Chip ID (CSR88 IDL, CSR89 IDU) values for various AMD PCnet parts
+ */
+#define        CHIPID_MANFID(x)        (((x) >> 1) & 0x3ff)
+#define        CHIPID_PARTID(x)        (((x) >> 12) & 0xffff)
+#define        CHIPID_VER(x)           (((x) >> 28) & 0x7)
+
+#define        PARTID_Am79c960         0x0003
+#define        PARTID_Am79c961         0x2260
+#define        PARTID_Am79c961A        0x2261
+#define        PARTID_Am79c965         0x2430  /* yes, these... */
+#define        PARTID_Am79c970         0x2430  /* ...are the same */
+#define        PARTID_Am79c970A        0x2621
+#define        PARTID_Am79c971         0x2623
+#define        PARTID_Am79c972         0x2624
+#define        PARTID_Am79c973         0x2625
+#define        PARTID_Am79c978         0x2626
+#define        PARTID_Am79c975         0x2627
+#define        PARTID_Am79c976         0x2628
+
+#endif /* !_DEV_LE_LANCEREG_H_ */
diff --git a/sys/dev/netif/lnc/lancevar.h b/sys/dev/netif/lnc/lancevar.h
new file mode 100644 (file)
index 0000000..22ecb27
--- /dev/null
@@ -0,0 +1,167 @@
+/*     $NetBSD: lancevar.h,v 1.10 2005/12/11 12:21:27 christos Exp $   */
+/*     $FreeBSD: src/sys/dev/le/lancevar.h,v 1.2 2006/05/16 21:04:01 marius Exp $      */
+/*     $DragonFly: src/sys/dev/netif/lnc/lancevar.h,v 1.1 2006/07/07 14:16:29 sephe Exp $      */
+
+
+/*-
+ * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
+ * Simulation Facility, NASA Ames Research Center.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the NetBSD
+ *     Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#ifndef _DEV_LE_LANCEVAR_H_
+#define        _DEV_LE_LANCEVAR_H_
+
+extern devclass_t le_devclass;
+
+struct lance_softc {
+       struct arpcom   sc_arp;
+       struct ifnet    *ifp;
+       struct ifmedia  sc_media;
+
+       /*
+        * Memory functions:
+        *
+        *      copy to/from descriptor
+        *      copy to/from buffer
+        *      zero bytes in buffer
+        */
+       void    (*sc_copytodesc)(struct lance_softc *, void *, int, int);
+       void    (*sc_copyfromdesc)(struct lance_softc *, void *, int, int);
+       void    (*sc_copytobuf)(struct lance_softc *, void *, int, int);
+       void    (*sc_copyfrombuf)(struct lance_softc *, void *, int, int);
+       void    (*sc_zerobuf)(struct lance_softc *, int, int);
+
+       /*
+        * Machine-dependent functions:
+        *
+        *      read/write CSR
+        *      hardware reset hook - may be NULL
+        *      hardware init hook - may be NULL
+        *      no carrier hook - may be NULL
+        *      media change hook - may be NULL
+        */
+       uint16_t        (*sc_rdcsr)(struct lance_softc *, uint16_t);
+       void    (*sc_wrcsr)(struct lance_softc *, uint16_t, uint16_t);
+       void    (*sc_hwreset)(struct lance_softc *);
+       void    (*sc_hwinit)(struct lance_softc *);
+       int     (*sc_hwintr)(struct lance_softc *);
+       void    (*sc_nocarrier)(struct lance_softc *);
+       int     (*sc_mediachange)(struct lance_softc *);
+       void    (*sc_mediastatus)(struct lance_softc *, struct ifmediareq *);
+
+       /*
+        * Media-supported by this interface.  If this is NULL,
+        * the only supported media is assumed to be "manual".
+        */
+       const int       *sc_supmedia;
+       int     sc_nsupmedia;
+       int     sc_defaultmedia;
+
+       uint16_t        sc_conf3;       /* CSR3 value */
+
+       void    *sc_mem;                /* base address of RAM - CPU's view */
+       bus_addr_t      sc_addr;        /* base address of RAM - LANCE's view */
+
+       bus_size_t      sc_memsize;     /* size of RAM */
+
+       int     sc_nrbuf;       /* number of receive buffers */
+       int     sc_ntbuf;       /* number of transmit buffers */
+       int     sc_last_rd;
+       int     sc_first_td;
+       int     sc_last_td;
+       int     sc_no_td;
+
+       int     sc_initaddr;
+       int     sc_rmdaddr;
+       int     sc_tmdaddr;
+       int     sc_rbufaddr;
+       int     sc_tbufaddr;
+
+       uint8_t sc_enaddr[ETHER_ADDR_LEN];
+
+       void    (*sc_meminit)(struct lance_softc *);
+       void    (*sc_start_locked)(struct lance_softc *);
+
+       int     sc_flags;
+#define        LE_ALLMULTI     (1 << 0)
+#define        LE_BSWAP        (1 << 1)
+#define        LE_CARRIER      (1 << 2)
+#define        LE_DEBUG        (1 << 3)
+#define        LE_PROMISC      (1 << 4)
+};
+#define sc_if  sc_arp.ac_if
+
+/*
+ * Unfortunately, manual byte swapping is only necessary for the PCnet-PCI
+ * variants but not for the original LANCE or ILACC so we cannot do this
+ * with #ifdefs resolved at compile time.
+ */
+#define        LE_HTOLE16(v)   (((sc)->sc_flags & LE_BSWAP) ? htole16(v) : (v))
+#define        LE_HTOLE32(v)   (((sc)->sc_flags & LE_BSWAP) ? htole32(v) : (v))
+#define        LE_LE16TOH(v)   (((sc)->sc_flags & LE_BSWAP) ? le16toh(v) : (v))
+#define        LE_LE32TOH(v)   (((sc)->sc_flags & LE_BSWAP) ? le32toh(v) : (v))
+
+int lance_config(struct lance_softc *, const char*, int);
+void lance_attach(struct lance_softc *);
+void lance_detach(struct lance_softc *);
+void lance_stop(struct lance_softc *);
+void lance_suspend(struct lance_softc *);
+void lance_resume(struct lance_softc *);
+void lance_init_locked(struct lance_softc *);
+int lance_put(struct lance_softc *, int, struct mbuf *);
+struct mbuf *lance_get(struct lance_softc *, int, int);
+void lance_setladrf(struct lance_softc *, u_int16_t *);
+
+/*
+ * The following functions are only useful on certain CPU/bus
+ * combinations.  They should be written in assembly language for
+ * maximum efficiency, but machine-independent versions are provided
+ * for drivers that have not yet been optimized.
+ */
+void lance_copytobuf_contig(struct lance_softc *, void *, int, int);
+void lance_copyfrombuf_contig(struct lance_softc *, void *, int, int);
+void lance_zerobuf_contig(struct lance_softc *, int, int);
+
+#if 0  /* Example only - see lance.c */
+void lance_copytobuf_gap2(struct lance_softc *, void *, int, int);
+void lance_copyfrombuf_gap2(struct lance_softc *, void *, int, int);
+void lance_zerobuf_gap2(struct lance_softc *, int, int);
+
+void lance_copytobuf_gap16(struct lance_softc *, void *, int, int);
+void lance_copyfrombuf_gap16(struct lance_softc *, void *, int, int);
+void lance_zerobuf_gap16(struct lance_softc *, int, int);
+#endif /* Example only */
+
+#endif /* _DEV_LE_LANCEVAR_H_ */