summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2004-10-05 02:01:19 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2004-10-05 02:01:19 +0000
commit634c7ec3f58881322776370eeb5c8c2c30fdd1fe (patch)
treea5483be32346ff3313f84deb4b1926faa73cbf0c
parent71af365c0cf7ca1e0601b5f7b23bc5cd8cf24181 (diff)
Port of NetBSD's udav driver for Davicom USB DM960 based Ethernet.
Thanks to Mark Uemura for donating several of these adapters. Tested by and ok deraadt@
-rw-r--r--share/man/man4/udav.479
-rw-r--r--share/man/man4/usb.45
-rw-r--r--sys/arch/alpha/conf/GENERIC3
-rw-r--r--sys/arch/alpha/conf/RAMDISKBIG3
-rw-r--r--sys/arch/amd64/conf/GENERIC3
-rw-r--r--sys/arch/amd64/conf/RAMDISK_CD3
-rw-r--r--sys/arch/cats/conf/GENERIC4
-rw-r--r--sys/arch/hppa/conf/GENERIC3
-rw-r--r--sys/arch/hppa/conf/RAMDISK3
-rw-r--r--sys/arch/i386/conf/GENERIC3
-rw-r--r--sys/arch/i386/conf/RAMDISK_CD3
-rw-r--r--sys/arch/macppc/conf/GENERIC4
-rw-r--r--sys/arch/macppc/conf/RAMDISK4
-rw-r--r--sys/arch/sparc64/conf/GENERIC3
-rw-r--r--sys/dev/usb/FILES2
-rw-r--r--sys/dev/usb/files.usb7
-rw-r--r--sys/dev/usb/if_udav.c1731
-rw-r--r--sys/dev/usb/if_udavreg.h214
-rw-r--r--sys/dev/usb/usb_port.h4
19 files changed, 2066 insertions, 15 deletions
diff --git a/share/man/man4/udav.4 b/share/man/man4/udav.4
new file mode 100644
index 00000000000..cbfed15594f
--- /dev/null
+++ b/share/man/man4/udav.4
@@ -0,0 +1,79 @@
+.\" $OpenBSD: udav.4,v 1.1 2004/10/05 02:01:17 jsg Exp $
+.\" $NetBSD: udav.4,v 1.1 2003/08/22 06:42:01 itojun Exp $
+.\"
+.\" Copyright (c) 2003
+.\" Shingo WATANABE <nabe@nabechan.org>. 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.
+.\" 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 author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
+.\" 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.
+.\"
+.Dd August 22, 2003
+.Dt UDAV 4
+.Os
+.Sh NAME
+.Nm udav
+.Nd Davicom DM9601 USB Ethernet driver
+.Sh SYNOPSIS
+.Cd "udav* at uhub?"
+.Cd "ukphy* at mii?"
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for USB
+.Tn Ethernet
+adapters based on the Davicom DM9601 USB-ether bridge chip.
+.Pp
+The
+.Nm
+driver supports the following adapters:
+.Pp
+.Bl -tag -width Dv -offset indent -compact
+.It Tn Corega FEther USB-TXC
+.El
+.Pp
+For more information on configuring this device, see
+.Xr ifconfig 8 .
+.Sh SEE ALSO
+.Xr arp 4 ,
+.Xr ifmedia 4 ,
+.Xr mii 4 ,
+.Xr netintro 4 ,
+.Xr uhub 4 ,
+.Xr usb 4 ,
+.Xr hostname.if 5 ,
+.Xr ifconfig 8
+.Rs
+.%T Davicom DM9601 data sheet
+.%O http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-F01-062202s.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Ox 3.7 .
+.Sh AUTHORS
+The
+.Nm
+driver was written by
+.An Shingo WATANABE Aq nabe@nabechan.org .
diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4
index 7325af592f2..4d036fbb7c8 100644
--- a/share/man/man4/usb.4
+++ b/share/man/man4/usb.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: usb.4,v 1.34 2004/09/30 19:59:26 mickey Exp $
+.\" $OpenBSD: usb.4,v 1.35 2004/10/05 02:01:17 jsg Exp $
.\" $NetBSD: usb.4,v 1.15 1999/07/29 14:20:32 augustss Exp $
.\"
.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -133,6 +133,8 @@ Communication Device Class (CDC) and Ethernet subclass.
CATC USB-EL1201A-based Ethernet interfaces.
.It Xr kue 4
Kawasaki LSI KL5KUSB101B-based Ethernet interfaces.
+.It Xr udav 4
+Davicom DM9601 based Ethernet interfaces.
.It Xr url 4
Realtek RTL8150L-based Ethernet interfaces.
.It Xr wi 4
@@ -437,6 +439,7 @@ Human Interface Devices
.Xr uaudio 4 ,
.Xr ubsa 4 ,
.Xr ucom 4 ,
+.Xr udav 4 ,
.Xr udsbr 4 ,
.Xr uftdi 4 ,
.Xr ugen 4 ,
diff --git a/sys/arch/alpha/conf/GENERIC b/sys/arch/alpha/conf/GENERIC
index 60b6069d8c5..1e1e12561fc 100644
--- a/sys/arch/alpha/conf/GENERIC
+++ b/sys/arch/alpha/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.127 2004/09/18 07:12:13 pvalchev Exp $
+# $OpenBSD: GENERIC,v 1.128 2004/10/05 02:01:17 jsg Exp $
# $NetBSD: GENERIC,v 1.31 1996/12/03 17:25:29 cgd Exp $
machine alpha
@@ -92,6 +92,7 @@ axe* at uhub? # ASIX Electronics AX88172 USB Ethernet
cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
+udav* at uhub? # Davicom DM9601 based Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/arch/alpha/conf/RAMDISKBIG b/sys/arch/alpha/conf/RAMDISKBIG
index d69f2f98cd2..d7e247f5b6f 100644
--- a/sys/arch/alpha/conf/RAMDISKBIG
+++ b/sys/arch/alpha/conf/RAMDISKBIG
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISKBIG,v 1.41 2004/09/16 09:35:36 deraadt Exp $
+# $OpenBSD: RAMDISKBIG,v 1.42 2004/10/05 02:01:17 jsg Exp $
# $NetBSD: GENERIC,v 1.31 1996/12/03 17:25:29 cgd Exp $
#
# Generic Alpha kernel. Enough to get booted, etc., but not much more.
@@ -85,6 +85,7 @@ aue* at uhub? # ADMtek AN986 Pegasus Ethernet
axe* at uhub? # ASIX Electronics AX88172 USB Ethernet
cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
+udav* at uhub? # Davicom DM9601 based Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 40ba27adfe0..2ae09c4a0d3 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.29 2004/09/16 09:14:03 mickey Exp $
+# $OpenBSD: GENERIC,v 1.30 2004/10/05 02:01:17 jsg Exp $
#
# GENERIC -- everything that's currently supported
#
@@ -124,6 +124,7 @@ cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
urio* at uhub? # Diamond Multimedia Rio 500
diff --git a/sys/arch/amd64/conf/RAMDISK_CD b/sys/arch/amd64/conf/RAMDISK_CD
index 4b780ea3537..fdedc5ea526 100644
--- a/sys/arch/amd64/conf/RAMDISK_CD
+++ b/sys/arch/amd64/conf/RAMDISK_CD
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK_CD,v 1.18 2004/09/16 09:35:36 deraadt Exp $
+# $OpenBSD: RAMDISK_CD,v 1.19 2004/10/05 02:01:17 jsg Exp $
machine amd64 # architecture, used by config; REQUIRED
@@ -91,6 +91,7 @@ axe* at uhub? # ASIX Electronics AX88172 USB Ethernet
cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
diff --git a/sys/arch/cats/conf/GENERIC b/sys/arch/cats/conf/GENERIC
index 8818f0a3298..51e24e311a9 100644
--- a/sys/arch/cats/conf/GENERIC
+++ b/sys/arch/cats/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.13 2004/10/01 04:15:14 drahn Exp $
+# $OpenBSD: GENERIC,v 1.14 2004/10/05 02:01:17 jsg Exp $
#
# GENERIC machine description file
#
@@ -147,6 +147,7 @@ xl* at pci? # 3C9xx ethernet
#lmc* at pci? # Lan Media Corp SSI/HSSI/DS3
# MII/PHY support
+amphy* at mii? # AMD 79C873 PHYs
exphy* at mii? # 3Com internal PHYs
icsphy* at mii? # Integrated Circuit Systems ICS189x
inphy* at mii? # Intel 82555 PHYs
@@ -203,6 +204,7 @@ axe* at uhub? # ASIX Electronics AX88172 USB Ethernet
cue* at uhub? # CATC USB-EL1201A based Ethernet
cdce* at uhub? # CDC Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
+udav* at uhub? # Davicom DM9601 based Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/arch/hppa/conf/GENERIC b/sys/arch/hppa/conf/GENERIC
index 20ea16ea3e3..11713f1a688 100644
--- a/sys/arch/hppa/conf/GENERIC
+++ b/sys/arch/hppa/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.59 2004/09/30 19:04:33 mickey Exp $
+# $OpenBSD: GENERIC,v 1.60 2004/10/05 02:01:17 jsg Exp $
# Machine architecture; required by config(8)
machine hppa
@@ -114,6 +114,7 @@ pcmcia* at cardslot?
#cue* at uhub? # CATC USB-EL1201A based Ethernet
#kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
#cdce* at uhub? # CDC Ethernet
+#udav* at uhub? # Davicom DM9601 based Ethernet
#upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
#url* at uhub? # Realtek RTL8150L based adapters
#wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/arch/hppa/conf/RAMDISK b/sys/arch/hppa/conf/RAMDISK
index 25fd3dc3852..96a54331eee 100644
--- a/sys/arch/hppa/conf/RAMDISK
+++ b/sys/arch/hppa/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.39 2004/09/30 19:04:33 mickey Exp $
+# $OpenBSD: RAMDISK,v 1.40 2004/10/05 02:01:17 jsg Exp $
#
# Diskless kernel config
#
@@ -128,6 +128,7 @@ pcmcia* at cardslot?
#cue* at uhub? # CATC USB-EL1201A based Ethernet
#kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
#cdce* at uhub? # CDC Ethernet
+#udav* at uhub? # Davicom DM9601 based Ethernet
#upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
#url* at uhub? # Realtek RTL8150L based adapters
#wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC
index 592a73fb8d5..95f7cbdbb54 100644
--- a/sys/arch/i386/conf/GENERIC
+++ b/sys/arch/i386/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.379 2004/10/03 21:28:34 jcs Exp $
+# $OpenBSD: GENERIC,v 1.380 2004/10/05 02:01:17 jsg Exp $
#
# GENERIC -- everything that's currently supported
#
@@ -157,6 +157,7 @@ cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
urio* at uhub? # Diamond Multimedia Rio 500
diff --git a/sys/arch/i386/conf/RAMDISK_CD b/sys/arch/i386/conf/RAMDISK_CD
index 38c7e97665f..b737f5e2a64 100644
--- a/sys/arch/i386/conf/RAMDISK_CD
+++ b/sys/arch/i386/conf/RAMDISK_CD
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK_CD,v 1.81 2004/09/16 09:35:36 deraadt Exp $
+# $OpenBSD: RAMDISK_CD,v 1.82 2004/10/05 02:01:17 jsg Exp $
machine i386 # architecture, used by config; REQUIRED
@@ -120,6 +120,7 @@ upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
urio* at uhub? # Diamond Multimedia Rio 500
cdce* at uhub? # CDC Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
#uscanner* at uhub? # USB Scanners
diff --git a/sys/arch/macppc/conf/GENERIC b/sys/arch/macppc/conf/GENERIC
index 78147c08d4d..9d2a2b31373 100644
--- a/sys/arch/macppc/conf/GENERIC
+++ b/sys/arch/macppc/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.60 2004/09/16 09:35:36 deraadt Exp $g
+# $OpenBSD: GENERIC,v 1.61 2004/10/05 02:01:18 jsg Exp $g
#
# PPC GENERIC config file
#
@@ -68,6 +68,7 @@ iop* at pci? # I2O processor
ioprbs* at iop? # I2O arrays
iopsp* at iop? # I2O SCSI pass-through
+amphy* at mii? # AMD 79C873 PHYs
dcphy* at mii? # Digital Clone PHYs
exphy* at mii? # 3Com internal PHYs
inphy* at mii? # Intel 82555 PHYs
@@ -209,6 +210,7 @@ cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
urio* at uhub? # Diamond Multimedia Rio 500
diff --git a/sys/arch/macppc/conf/RAMDISK b/sys/arch/macppc/conf/RAMDISK
index 11891b91a4d..5df8eb62154 100644
--- a/sys/arch/macppc/conf/RAMDISK
+++ b/sys/arch/macppc/conf/RAMDISK
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.35 2004/09/16 09:35:36 deraadt Exp $
+# $OpenBSD: RAMDISK,v 1.36 2004/10/05 02:01:18 jsg Exp $
#
# PPC GENERIC config file
#
@@ -69,6 +69,7 @@ an* at pci? # Cisco/Aironet 802.11DS
wi* at pci? # WaveLAN IEEE 802.11DS
# how many of these are needed?
+amphy* at mii? # AMD 79C873 PHYs
dcphy* at mii? # Digital Clone PHYs
exphy* at mii? # 3Com internal PHYs
inphy* at mii? # Intel 82555 PHYs
@@ -148,6 +149,7 @@ cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host
+udav* at uhub? # Davicom DM9601 based Ethernet
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
#uscanner* at uhub? # USB Scanner driver
diff --git a/sys/arch/sparc64/conf/GENERIC b/sys/arch/sparc64/conf/GENERIC
index 9daad590958..6fb6ab6457b 100644
--- a/sys/arch/sparc64/conf/GENERIC
+++ b/sys/arch/sparc64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.105 2004/09/30 19:14:11 robert Exp $
+# $OpenBSD: GENERIC,v 1.106 2004/10/05 02:01:18 jsg Exp $
# $NetBSD: GENERIC32,v 1.18 2001/07/20 00:07:12 eeh Exp $
machine sparc64
@@ -132,6 +132,7 @@ axe* at uhub? # ASIX Electronics AX88172 USB Ethernet
cue* at uhub? # CATC USB-EL1201A based Ethernet
kue* at uhub? # Kawasaki KL5KUSB101B based Ethernet
cdce* at uhub? # CDC Ethernet
+udav* at uhub? # Davicom DM9601 based Ethernet
upl* at uhub? # Prolific PL2301/PL2302 host-to-host `network'
url* at uhub? # Realtek RTL8150L based adapters
wi* at uhub? # WaveLAN IEEE 802.11DS
diff --git a/sys/dev/usb/FILES b/sys/dev/usb/FILES
index 9e15f5945f1..850124edc20 100644
--- a/sys/dev/usb/FILES
+++ b/sys/dev/usb/FILES
@@ -18,6 +18,8 @@ if_cue.c USB CATC Ethernet driver
if_cuereg.h and definitions for it
if_kue.c USB Kawasaki Ethernet driver
if_kuereg.h and definitions for it
+if_udav.c USB Davicom Ethernet driver
+if_udavreg.h and definitions for it
if_upl.c USB Prolofic host-to-host driver
kue_fw.h Kawasaki Ethernet firmware
ohci.c Host controller driver for OHCI
diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb
index 5251509974c..e0ef61ecdcc 100644
--- a/sys/dev/usb/files.usb
+++ b/sys/dev/usb/files.usb
@@ -1,4 +1,4 @@
-# $OpenBSD: files.usb,v 1.36 2004/07/20 20:30:09 dhartmei Exp $
+# $OpenBSD: files.usb,v 1.37 2004/10/05 02:01:18 jsg Exp $
# $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $
#
# Config file and device description for machine-independent USB code.
@@ -145,6 +145,11 @@ device cdce: ether, ifnet, ifmedia
attach cdce at uhub
file dev/usb/if_cdce.c cdce
+# Davicom DM9601
+device udav: ether, ifnet, mii, ifmedia
+attach udav at uhub
+file dev/usb/if_udav.c udav
+
# Prolific PL2302 host-host
device upl: ifnet
attach upl at uhub
diff --git a/sys/dev/usb/if_udav.c b/sys/dev/usb/if_udav.c
new file mode 100644
index 00000000000..b0be090343b
--- /dev/null
+++ b/sys/dev/usb/if_udav.c
@@ -0,0 +1,1731 @@
+/* $OpenBSD: if_udav.c,v 1.1 2004/10/05 02:01:18 jsg Exp $ */
+/* $NetBSD: if_udav.c,v 1.3 2004/04/23 17:25:25 itojun Exp $ */
+/* $nabe: if_udav.c,v 1.3 2003/08/21 16:57:19 nabe Exp $ */
+/*
+ * Copyright (c) 2003
+ * Shingo WATANABE <nabe@nabechan.org>. 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.
+ * 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 author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * DM9601(DAVICOM USB to Ethernet MAC Controller with Integrated 10/100 PHY)
+ * The spec can be found at the following url.
+ * http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-F01-062202s.pdf
+ */
+
+/*
+ * TODO:
+ * Interrupt Endpoint support
+ * External PHYs
+ * powerhook() support?
+ */
+
+#include <sys/cdefs.h>
+#if defined(__NetBSD__)
+__KERNEL_RCSID(0, "$NetBSD: if_udav.c,v 1.3 2004/04/23 17:25:25 itojun Exp $");
+#endif
+
+#if defined(__NetBSD__)
+#include "opt_inet.h"
+#include "opt_ns.h"
+#include "rnd.h"
+#endif
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#if defined(__OpenBSD__)
+#include <sys/proc.h>
+#endif
+#include <sys/socket.h>
+
+#include <sys/device.h>
+#if NRND > 0
+#include <sys/rnd.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+#define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
+
+#if defined(__NetBSD__)
+#include <net/if_ether.h>
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+#endif
+#endif /* defined(__NetBSD__) */
+
+#if defined(__OpenBSD__)
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#endif
+#endif /* defined(__OpenBSD__) */
+
+#ifdef NS
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#endif
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdevs.h>
+
+#include <dev/usb/if_udavreg.h>
+
+
+/* Function declarations */
+USB_DECLARE_DRIVER_CLASS(udav, DV_IFNET);
+
+Static int udav_openpipes(struct udav_softc *);
+Static int udav_rx_list_init(struct udav_softc *);
+Static int udav_tx_list_init(struct udav_softc *);
+Static int udav_newbuf(struct udav_softc *, struct udav_chain *, struct mbuf *);
+Static void udav_start(struct ifnet *);
+Static int udav_send(struct udav_softc *, struct mbuf *, int);
+Static void udav_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+Static void udav_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
+Static void udav_tick(void *);
+Static void udav_tick_task(void *);
+Static int udav_ioctl(struct ifnet *, u_long, caddr_t);
+Static void udav_stop_task(struct udav_softc *);
+Static void udav_stop(struct ifnet *, int);
+Static void udav_watchdog(struct ifnet *);
+Static int udav_ifmedia_change(struct ifnet *);
+Static void udav_ifmedia_status(struct ifnet *, struct ifmediareq *);
+Static void udav_lock_mii(struct udav_softc *);
+Static void udav_unlock_mii(struct udav_softc *);
+Static int udav_miibus_readreg(device_ptr_t, int, int);
+Static void udav_miibus_writereg(device_ptr_t, int, int, int);
+Static void udav_miibus_statchg(device_ptr_t);
+Static int udav_init(struct ifnet *);
+Static void udav_setmulti(struct udav_softc *);
+Static void udav_reset(struct udav_softc *);
+
+Static int udav_csr_read(struct udav_softc *, int, void *, int);
+Static int udav_csr_write(struct udav_softc *, int, void *, int);
+Static int udav_csr_read1(struct udav_softc *, int);
+Static int udav_csr_write1(struct udav_softc *, int, unsigned char);
+
+#if 0
+Static int udav_mem_read(struct udav_softc *, int, void *, int);
+Static int udav_mem_write(struct udav_softc *, int, void *, int);
+Static int udav_mem_write1(struct udav_softc *, int, unsigned char);
+#endif
+
+/* Macros */
+#ifdef UDAV_DEBUG
+#define DPRINTF(x) do { if (udavdebug) logprintf x; } while(0)
+#define DPRINTFN(n,x) do { if (udavdebug >= (n)) logprintf x; } while(0)
+int udavdebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+#define UDAV_SETBIT(sc, reg, x) \
+ udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) | (x))
+
+#define UDAV_CLRBIT(sc, reg, x) \
+ udav_csr_write1(sc, reg, udav_csr_read1(sc, reg) & ~(x))
+
+static const struct udav_type {
+ struct usb_devno udav_dev;
+ u_int16_t udav_flags;
+#define UDAV_EXT_PHY 0x0001
+} udav_devs [] = {
+ /* Corega USB-TXC */
+ {{ USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC }, 0},
+#if 0
+ /* DAVICOM DM9601 Generic? */
+ /* XXX: The following ids was obtained from the data sheet. */
+ {{ 0x0a46, 0x9601 }, 0},
+#endif
+};
+#define udav_lookup(v, p) ((struct udav_type *)usb_lookup(udav_devs, v, p))
+
+
+/* Probe */
+USB_MATCH(udav)
+{
+ USB_MATCH_START(udav, uaa);
+
+ if (uaa->iface != NULL)
+ return (UMATCH_NONE);
+
+ return (udav_lookup(uaa->vendor, uaa->product) != NULL ?
+ UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
+}
+
+/* Attach */
+USB_ATTACH(udav)
+{
+ USB_ATTACH_START(udav, sc, uaa);
+ usbd_device_handle dev = uaa->device;
+ usbd_interface_handle iface;
+ usbd_status err;
+ usb_interface_descriptor_t *id;
+ usb_endpoint_descriptor_t *ed;
+ char devinfo[1024];
+ char *devname = USBDEVNAME(sc->sc_dev);
+ struct ifnet *ifp;
+ struct mii_data *mii;
+ u_char eaddr[ETHER_ADDR_LEN];
+ int i, s;
+
+ usbd_devinfo(dev, 0, devinfo, sizeof(devinfo));
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", devname, devinfo);
+
+ /* Move the device into the configured state. */
+ err = usbd_set_config_no(dev, UDAV_CONFIG_NO, 1);
+ if (err) {
+ printf("%s: setting config no failed\n", devname);
+ goto bad;
+ }
+
+ usb_init_task(&sc->sc_tick_task, udav_tick_task, sc);
+ lockinit(&sc->sc_mii_lock, PZERO, "udavmii", 0, 0);
+ usb_init_task(&sc->sc_stop_task, (void (*)(void *)) udav_stop_task, sc);
+
+ /* get control interface */
+ err = usbd_device2interface_handle(dev, UDAV_IFACE_INDEX, &iface);
+ if (err) {
+ printf("%s: failed to get interface, err=%s\n", devname,
+ usbd_errstr(err));
+ goto bad;
+ }
+
+ sc->sc_udev = dev;
+ sc->sc_ctl_iface = iface;
+ sc->sc_flags = udav_lookup(uaa->vendor, uaa->product)->udav_flags;
+
+ /* get interface descriptor */
+ id = usbd_get_interface_descriptor(sc->sc_ctl_iface);
+
+ /* find endpoints */
+ sc->sc_bulkin_no = sc->sc_bulkout_no = sc->sc_intrin_no = -1;
+ for (i = 0; i < id->bNumEndpoints; i++) {
+ ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i);
+ if (ed == NULL) {
+ printf("%s: couldn't get endpoint %d\n", devname, i);
+ goto bad;
+ }
+ if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
+ UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
+ sc->sc_bulkin_no = ed->bEndpointAddress; /* RX */
+ else if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK &&
+ UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
+ sc->sc_bulkout_no = ed->bEndpointAddress; /* TX */
+ else if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT &&
+ UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
+ sc->sc_intrin_no = ed->bEndpointAddress; /* Status */
+ }
+
+ if (sc->sc_bulkin_no == -1 || sc->sc_bulkout_no == -1 ||
+ sc->sc_intrin_no == -1) {
+ printf("%s: missing endpoint\n", devname);
+ goto bad;
+ }
+
+ s = splnet();
+
+ /* reset the adapter */
+ udav_reset(sc);
+
+ /* Get Ethernet Address */
+ err = udav_csr_read(sc, UDAV_PAR, (void *)eaddr, ETHER_ADDR_LEN);
+ if (err) {
+ printf("%s: read MAC address failed\n", devname);
+ splx(s);
+ goto bad;
+ }
+
+ /* Print Ethernet Address */
+ printf("%s: address %s\n", devname, ether_sprintf(eaddr));
+
+#if defined(__OpenBSD__)
+ bcopy(eaddr, (char *)&sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
+#endif
+
+ /* initialize interface infomation */
+ ifp = GET_IFP(sc);
+ ifp->if_softc = sc;
+ ifp->if_mtu = ETHERMTU;
+ strncpy(ifp->if_xname, devname, IFNAMSIZ);
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = udav_start;
+ ifp->if_ioctl = udav_ioctl;
+ ifp->if_watchdog = udav_watchdog;
+#if defined(__NetBSD__)
+ ifp->if_init = udav_init;
+ ifp->if_stop = udav_stop;
+#endif
+
+ IFQ_SET_READY(&ifp->if_snd);
+
+ /*
+ * Do ifmedia setup.
+ */
+ mii = &sc->sc_mii;
+ mii->mii_ifp = ifp;
+ mii->mii_readreg = udav_miibus_readreg;
+ mii->mii_writereg = udav_miibus_writereg;
+ mii->mii_statchg = udav_miibus_statchg;
+ mii->mii_flags = MIIF_AUTOTSLEEP;
+ ifmedia_init(&mii->mii_media, 0,
+ udav_ifmedia_change, udav_ifmedia_status);
+ mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ if (LIST_FIRST(&mii->mii_phys) == NULL) {
+ ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
+ ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_NONE);
+ } else
+ ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
+
+ /* attach the interface */
+ if_attach(ifp);
+ Ether_ifattach(ifp, eaddr);
+
+#if NRND > 0
+ rnd_attach_source(&sc->rnd_source, devname, RND_TYPE_NET, 0);
+#endif
+
+ usb_callout_init(sc->sc_stat_ch);
+ sc->sc_attached = 1;
+ splx(s);
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, dev, USBDEV(sc->sc_dev));
+
+ USB_ATTACH_SUCCESS_RETURN;
+
+ bad:
+ sc->sc_dying = 1;
+ USB_ATTACH_ERROR_RETURN;
+}
+
+/* detach */
+USB_DETACH(udav)
+{
+ USB_DETACH_START(udav, sc);
+ struct ifnet *ifp = GET_IFP(sc);
+ int s;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ /* Detached before attached finished */
+ if (!sc->sc_attached)
+ return (0);
+
+ usb_uncallout(sc->sc_stat_ch, udav_tick, sc);
+
+ /* Remove any pending tasks */
+ usb_rem_task(sc->sc_udev, &sc->sc_tick_task);
+ usb_rem_task(sc->sc_udev, &sc->sc_stop_task);
+
+ s = splusb();
+
+ if (--sc->sc_refcnt >= 0) {
+ /* Wait for processes to go away */
+ usb_detach_wait(USBDEV(sc->sc_dev));
+ }
+ if (ifp->if_flags & IFF_RUNNING)
+ udav_stop(GET_IFP(sc), 1);
+
+#if NRND > 0
+ rnd_detach_source(&sc->rnd_source);
+#endif
+ mii_detach(&sc->sc_mii, MII_PHY_ANY, MII_OFFSET_ANY);
+ ifmedia_delete_instance(&sc->sc_mii.mii_media, IFM_INST_ANY);
+ ether_ifdetach(ifp);
+ if_detach(ifp);
+
+#ifdef DIAGNOSTIC
+ if (sc->sc_pipe_tx != NULL)
+ printf("%s: detach has active tx endpoint.\n",
+ USBDEVNAME(sc->sc_dev));
+ if (sc->sc_pipe_rx != NULL)
+ printf("%s: detach has active rx endpoint.\n",
+ USBDEVNAME(sc->sc_dev));
+ if (sc->sc_pipe_intr != NULL)
+ printf("%s: detach has active intr endpoint.\n",
+ USBDEVNAME(sc->sc_dev));
+#endif
+ sc->sc_attached = 0;
+
+ splx(s);
+
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+ USBDEV(sc->sc_dev));
+
+ return (0);
+}
+
+#if 0
+/* read memory */
+Static int
+udav_mem_read(struct udav_softc *sc, int offset, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xffff;
+ len &= 0xff;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_MEM_READ;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, len);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, buf);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+
+/* write memory */
+Static int
+udav_mem_write(struct udav_softc *sc, int offset, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xffff;
+ len &= 0xff;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_MEM_WRITE;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, len);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, buf);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+
+/* write memory */
+Static int
+udav_mem_write1(struct udav_softc *sc, int offset, unsigned char ch)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xffff;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_MEM_WRITE1;
+ USETW(req.wValue, ch);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, 0x0000);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, NULL);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+#endif
+
+/* read register(s) */
+Static int
+udav_csr_read(struct udav_softc *sc, int offset, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xff;
+ len &= 0xff;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_REG_READ;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, len);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, buf);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: read failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+
+/* write register(s) */
+Static int
+udav_csr_write(struct udav_softc *sc, int offset, void *buf, int len)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xff;
+ len &= 0xff;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_REG_WRITE;
+ USETW(req.wValue, 0x0000);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, len);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, buf);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+
+Static int
+udav_csr_read1(struct udav_softc *sc, int offset)
+{
+ u_int8_t val = 0;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ return (udav_csr_read(sc, offset, &val, 1) ? 0 : val);
+}
+
+/* write a register */
+Static int
+udav_csr_write1(struct udav_softc *sc, int offset, unsigned char ch)
+{
+ usb_device_request_t req;
+ usbd_status err;
+
+ if (sc == NULL)
+ return (0);
+
+ DPRINTFN(0x200,
+ ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ offset &= 0xff;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = UDAV_REQ_REG_WRITE1;
+ USETW(req.wValue, ch);
+ USETW(req.wIndex, offset);
+ USETW(req.wLength, 0x0000);
+
+ sc->sc_refcnt++;
+ err = usbd_do_request(sc->sc_udev, &req, NULL);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err) {
+ DPRINTF(("%s: %s: write failed. off=%04x, err=%d\n",
+ USBDEVNAME(sc->sc_dev), __func__, offset, err));
+ }
+
+ return (err);
+}
+
+Static int
+udav_init(struct ifnet *ifp)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct mii_data *mii = GET_MII(sc);
+ u_char *eaddr;
+ int s;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ s = splnet();
+
+ /* Cancel pending I/O and free all TX/RX buffers */
+ udav_stop(ifp, 1);
+
+#if defined(__OpenBSD__)
+ eaddr = sc->sc_ac.ac_enaddr;
+#elif defined(__NetBSD__)
+ eaddr = LLADDR(ifp->if_sadl);
+#endif
+ udav_csr_write(sc, UDAV_PAR, eaddr, ETHER_ADDR_LEN);
+
+ /* Initialize network control register */
+ /* Disable loopback */
+ UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_LBK0 | UDAV_NCR_LBK1);
+
+ /* Initialize RX control register */
+ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_DIS_LONG | UDAV_RCR_DIS_CRC);
+
+ /* If we want promiscuous mode, accept all physical frames. */
+ if (ifp->if_flags & IFF_PROMISC)
+ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
+ else
+ UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
+
+ /* Initialize transmit ring */
+ if (udav_tx_list_init(sc) == ENOBUFS) {
+ printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
+ splx(s);
+ return (EIO);
+ }
+
+ /* Initialize receive ring */
+ if (udav_rx_list_init(sc) == ENOBUFS) {
+ printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
+ splx(s);
+ return (EIO);
+ }
+
+ /* Load the multicast filter */
+ udav_setmulti(sc);
+
+ /* Enable RX */
+ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_RXEN);
+
+ /* clear POWER_DOWN state of internal PHY */
+ UDAV_SETBIT(sc, UDAV_GPCR, UDAV_GPCR_GEP_CNTL0);
+ UDAV_CLRBIT(sc, UDAV_GPR, UDAV_GPR_GEPIO0);
+
+ mii_mediachg(mii);
+
+ if (sc->sc_pipe_tx == NULL || sc->sc_pipe_rx == NULL) {
+ if (udav_openpipes(sc)) {
+ splx(s);
+ return (EIO);
+ }
+ }
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ splx(s);
+
+ usb_callout(sc->sc_stat_ch, hz, udav_tick, sc);
+
+ return (0);
+}
+
+Static void
+udav_reset(struct udav_softc *sc)
+{
+ int i;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return;
+
+ /* Select PHY */
+#if 1
+ /*
+ * XXX: force select internal phy.
+ * external phy routines are not tested.
+ */
+ UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
+#else
+ if (sc->sc_flags & UDAV_EXT_PHY) {
+ UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
+ } else {
+ UDAV_CLRBIT(sc, UDAV_NCR, UDAV_NCR_EXT_PHY);
+ }
+#endif
+
+ UDAV_SETBIT(sc, UDAV_NCR, UDAV_NCR_RST);
+
+ for (i = 0; i < UDAV_TX_TIMEOUT; i++) {
+ if (!(udav_csr_read1(sc, UDAV_NCR) & UDAV_NCR_RST))
+ break;
+ delay(10); /* XXX */
+ }
+ delay(10000); /* XXX */
+}
+
+int
+udav_activate(device_ptr_t self, enum devact act)
+{
+ struct udav_softc *sc = (struct udav_softc *)self;
+
+ DPRINTF(("%s: %s: enter, act=%d\n", USBDEVNAME(sc->sc_dev),
+ __func__, act));
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ break;
+
+ case DVACT_DEACTIVATE:
+ if_deactivate(&sc->sc_ec.ec_if);
+ sc->sc_dying = 1;
+ break;
+ }
+ return (0);
+}
+
+#define UDAV_BITS 6
+
+#define UDAV_CALCHASH(addr) \
+ (ether_crc32_le((addr), ETHER_ADDR_LEN) & ((1 << UDAV_BITS) - 1))
+
+Static void
+udav_setmulti(struct udav_softc *sc)
+{
+ struct ifnet *ifp;
+ struct ether_multi *enm;
+ struct ether_multistep step;
+ u_int8_t hashes[8];
+ int h = 0;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return;
+
+ ifp = GET_IFP(sc);
+
+ if (ifp->if_flags & IFF_PROMISC) {
+ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL|UDAV_RCR_PRMSC);
+ return;
+ } else if (ifp->if_flags & IFF_ALLMULTI) {
+ allmulti:
+ ifp->if_flags |= IFF_ALLMULTI;
+ UDAV_SETBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
+ UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_PRMSC);
+ return;
+ }
+
+ /* first, zot all the existing hash bits */
+ memset(hashes, 0x00, sizeof(hashes));
+ hashes[7] |= 0x80; /* broadcast address */
+ udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
+
+ /* now program new ones */
+#if defined(__NetBSD__)
+ ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
+#else
+ ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
+#endif
+ while (enm != NULL) {
+ if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
+ ETHER_ADDR_LEN) != 0)
+ goto allmulti;
+
+ h = UDAV_CALCHASH(enm->enm_addrlo);
+ hashes[h>>3] |= 1 << (h & 0x7);
+ ETHER_NEXT_MULTI(step, enm);
+ }
+
+ /* disable all multicast */
+ ifp->if_flags &= ~IFF_ALLMULTI;
+ UDAV_CLRBIT(sc, UDAV_RCR, UDAV_RCR_ALL);
+
+ /* write hash value to the register */
+ udav_csr_write(sc, UDAV_MAR, hashes, sizeof(hashes));
+}
+
+Static int
+udav_openpipes(struct udav_softc *sc)
+{
+ struct udav_chain *c;
+ usbd_status err;
+ int i;
+ int error = 0;
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ sc->sc_refcnt++;
+
+ /* Open RX pipe */
+ err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
+ USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
+ if (err) {
+ printf("%s: open rx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ error = EIO;
+ goto done;
+ }
+
+ /* Open TX pipe */
+ err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
+ USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
+ if (err) {
+ printf("%s: open tx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ error = EIO;
+ goto done;
+ }
+
+#if 0
+ /* XXX: interrupt endpoint is not yet supported */
+ /* Open Interrupt pipe */
+ err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
+ USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
+ &sc->sc_cdata.udav_ibuf, UDAV_INTR_PKGLEN,
+ udav_intr, UDAV_INTR_INTERVAL);
+ if (err) {
+ printf("%s: open intr pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ error = EIO;
+ goto done;
+ }
+#endif
+
+
+ /* Start up the receive pipe. */
+ for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
+ c = &sc->sc_cdata.udav_rx_chain[i];
+ usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_rx,
+ c, c->udav_buf, UDAV_BUFSZ,
+ USBD_SHORT_XFER_OK | USBD_NO_COPY,
+ USBD_NO_TIMEOUT, udav_rxeof);
+ (void)usbd_transfer(c->udav_xfer);
+ DPRINTF(("%s: %s: start read\n", USBDEVNAME(sc->sc_dev),
+ __func__));
+ }
+
+ done:
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ return (error);
+}
+
+Static int
+udav_newbuf(struct udav_softc *sc, struct udav_chain *c, struct mbuf *m)
+{
+ struct mbuf *m_new = NULL;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (m == NULL) {
+ MGETHDR(m_new, M_DONTWAIT, MT_DATA);
+ if (m_new == NULL) {
+ printf("%s: no memory for rx list "
+ "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
+ return (ENOBUFS);
+ }
+ MCLGET(m_new, M_DONTWAIT);
+ if (!(m_new->m_flags & M_EXT)) {
+ printf("%s: no memory for rx list "
+ "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
+ m_freem(m_new);
+ return (ENOBUFS);
+ }
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ } else {
+ m_new = m;
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ m_new->m_data = m_new->m_ext.ext_buf;
+ }
+
+ m_adj(m_new, ETHER_ALIGN);
+ c->udav_mbuf = m_new;
+
+ return (0);
+}
+
+
+Static int
+udav_rx_list_init(struct udav_softc *sc)
+{
+ struct udav_cdata *cd;
+ struct udav_chain *c;
+ int i;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ cd = &sc->sc_cdata;
+ for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
+ c = &cd->udav_rx_chain[i];
+ c->udav_sc = sc;
+ c->udav_idx = i;
+ if (udav_newbuf(sc, c, NULL) == ENOBUFS)
+ return (ENOBUFS);
+ if (c->udav_xfer == NULL) {
+ c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (c->udav_xfer == NULL)
+ return (ENOBUFS);
+ c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
+ if (c->udav_buf == NULL) {
+ usbd_free_xfer(c->udav_xfer);
+ return (ENOBUFS);
+ }
+ }
+ }
+
+ return (0);
+}
+
+Static int
+udav_tx_list_init(struct udav_softc *sc)
+{
+ struct udav_cdata *cd;
+ struct udav_chain *c;
+ int i;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ cd = &sc->sc_cdata;
+ for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
+ c = &cd->udav_tx_chain[i];
+ c->udav_sc = sc;
+ c->udav_idx = i;
+ c->udav_mbuf = NULL;
+ if (c->udav_xfer == NULL) {
+ c->udav_xfer = usbd_alloc_xfer(sc->sc_udev);
+ if (c->udav_xfer == NULL)
+ return (ENOBUFS);
+ c->udav_buf = usbd_alloc_buffer(c->udav_xfer, UDAV_BUFSZ);
+ if (c->udav_buf == NULL) {
+ usbd_free_xfer(c->udav_xfer);
+ return (ENOBUFS);
+ }
+ }
+ }
+
+ return (0);
+}
+
+Static void
+udav_start(struct ifnet *ifp)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct mbuf *m_head = NULL;
+
+ DPRINTF(("%s: %s: enter, link=%d\n", USBDEVNAME(sc->sc_dev),
+ __func__, sc->sc_link));
+
+ if (sc->sc_dying)
+ return;
+
+ if (!sc->sc_link)
+ return;
+
+ if (ifp->if_flags & IFF_OACTIVE)
+ return;
+
+ IFQ_POLL(&ifp->if_snd, m_head);
+ if (m_head == NULL)
+ return;
+
+ if (udav_send(sc, m_head, 0)) {
+ ifp->if_flags |= IFF_OACTIVE;
+ return;
+ }
+
+ IFQ_DEQUEUE(&ifp->if_snd, m_head);
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m_head);
+#endif
+
+ ifp->if_flags |= IFF_OACTIVE;
+
+ /* Set a timeout in case the chip goes out to lunch. */
+ ifp->if_timer = 5;
+}
+
+Static int
+udav_send(struct udav_softc *sc, struct mbuf *m, int idx)
+{
+ int total_len;
+ struct udav_chain *c;
+ usbd_status err;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
+
+ c = &sc->sc_cdata.udav_tx_chain[idx];
+
+ /* Copy the mbuf data into a contiguous buffer */
+ /* first 2 bytes are packet length */
+ m_copydata(m, 0, m->m_pkthdr.len, c->udav_buf + 2);
+ c->udav_mbuf = m;
+ total_len = m->m_pkthdr.len;
+ if (total_len < UDAV_MIN_FRAME_LEN) {
+ memset(c->udav_buf + 2 + total_len, 0,
+ UDAV_MIN_FRAME_LEN - total_len);
+ total_len = UDAV_MIN_FRAME_LEN;
+ }
+
+ /* Frame length is specified in the first 2bytes of the buffer */
+ c->udav_buf[0] = (u_int8_t)total_len;
+ c->udav_buf[1] = (u_int8_t)(total_len >> 8);
+ total_len += 2;
+
+ usbd_setup_xfer(c->udav_xfer, sc->sc_pipe_tx, c, c->udav_buf, total_len,
+ USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
+ UDAV_TX_TIMEOUT, udav_txeof);
+
+ /* Transmit */
+ sc->sc_refcnt++;
+ err = usbd_transfer(c->udav_xfer);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ if (err != USBD_IN_PROGRESS) {
+ printf("%s: udav_send error=%s\n", USBDEVNAME(sc->sc_dev),
+ usbd_errstr(err));
+ /* Stop the interface */
+ usb_add_task(sc->sc_udev, &sc->sc_stop_task);
+ return (EIO);
+ }
+
+ DPRINTF(("%s: %s: send %d bytes\n", USBDEVNAME(sc->sc_dev),
+ __func__, total_len));
+
+ sc->sc_cdata.udav_tx_cnt++;
+
+ return (0);
+}
+
+Static void
+udav_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+{
+ struct udav_chain *c = priv;
+ struct udav_softc *sc = c->udav_sc;
+ struct ifnet *ifp = GET_IFP(sc);
+ int s;
+
+ if (sc->sc_dying)
+ return;
+
+ s = splnet();
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~IFF_OACTIVE;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
+ splx(s);
+ return;
+ }
+ ifp->if_oerrors++;
+ printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev),
+ usbd_errstr(status));
+ if (status == USBD_STALLED) {
+ sc->sc_refcnt++;
+ usbd_clear_endpoint_stall(sc->sc_pipe_tx);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ }
+ splx(s);
+ return;
+ }
+
+ ifp->if_opackets++;
+
+ m_freem(c->udav_mbuf);
+ c->udav_mbuf = NULL;
+
+ if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
+ udav_start(ifp);
+
+ splx(s);
+}
+
+Static void
+udav_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
+{
+ struct udav_chain *c = priv;
+ struct udav_softc *sc = c->udav_sc;
+ struct ifnet *ifp = GET_IFP(sc);
+ struct mbuf *m;
+ u_int32_t total_len;
+ u_int8_t *pktstat;
+ int s;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__func__));
+
+ if (sc->sc_dying)
+ return;
+
+ if (status != USBD_NORMAL_COMPLETION) {
+ if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
+ return;
+ sc->sc_rx_errs++;
+ if (usbd_ratecheck(&sc->sc_rx_notice)) {
+ printf("%s: %u usb errors on rx: %s\n",
+ USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
+ usbd_errstr(status));
+ sc->sc_rx_errs = 0;
+ }
+ if (status == USBD_STALLED) {
+ sc->sc_refcnt++;
+ usbd_clear_endpoint_stall(sc->sc_pipe_rx);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+ }
+ goto done;
+ }
+
+ usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
+
+ /* copy data to mbuf */
+ m = c->udav_mbuf;
+ memcpy(mtod(m, char *), c->udav_buf, total_len);
+
+ /* first byte in received data */
+ pktstat = mtod(m, u_int8_t *);
+ m_adj(m, sizeof(u_int8_t));
+ DPRINTF(("%s: RX Status: 0x%02x\n", *pktstat));
+
+ total_len = UGETW(mtod(m, u_int8_t *));
+ m_adj(m, sizeof(u_int16_t));
+
+ if (*pktstat & UDAV_RSR_LCS) {
+ ifp->if_collisions++;
+ goto done;
+ }
+
+ if (total_len < sizeof(struct ether_header) ||
+ *pktstat & UDAV_RSR_ERR) {
+ ifp->if_ierrors++;
+ goto done;
+ }
+
+ ifp->if_ipackets++;
+ total_len -= ETHER_CRC_LEN;
+
+ m->m_pkthdr.len = m->m_len = total_len;
+ m->m_pkthdr.rcvif = ifp;
+
+ s = splnet();
+
+ if (udav_newbuf(sc, c, NULL) == ENOBUFS) {
+ ifp->if_ierrors++;
+ goto done1;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ BPF_MTAP(ifp, m);
+#endif
+
+ DPRINTF(("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev),
+ __func__, m->m_len));
+ IF_INPUT(ifp, m);
+
+ done1:
+ splx(s);
+
+ done:
+ /* Setup new transfer */
+ usbd_setup_xfer(xfer, sc->sc_pipe_rx, c, c->udav_buf, UDAV_BUFSZ,
+ USBD_SHORT_XFER_OK | USBD_NO_COPY,
+ USBD_NO_TIMEOUT, udav_rxeof);
+ sc->sc_refcnt++;
+ usbd_transfer(xfer);
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
+ DPRINTF(("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev), __func__));
+}
+
+#if 0
+Static void udav_intr()
+{
+}
+#endif
+
+Static int
+udav_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct mii_data *mii;
+ int s, error = 0;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ s = splnet();
+
+ switch (cmd) {
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ mii = GET_MII(sc);
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+#if defined(__OpenBSD__)
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ udav_init(ifp);
+
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&sc->sc_ac, ifa);
+ break;
+#endif /* INET */
+#ifdef NS
+ case AF_NS:
+ {
+ struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
+
+ if (ns_nullhost(*ina))
+ ina->x_host = *(union ns_host *)
+ LLADDR(ifp->if_sadl);
+ else
+ memcpy(LLADDR(ifp->if_sadl),
+ ina->x_host.c_host,
+ ifp->if_addrlen);
+ break;
+ }
+#endif /* NS */
+ }
+ break;
+
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu > ETHERMTU)
+ error = EINVAL;
+ else
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_flags & IFF_RUNNING &&
+ ifp->if_flags & IFF_PROMISC) {
+ UDAV_SETBIT(sc, UDAV_RCR,
+ UDAV_RCR_ALL|UDAV_RCR_PRMSC);
+ } else if (ifp->if_flags & IFF_RUNNING &&
+ !(ifp->if_flags & IFF_PROMISC)) {
+ UDAV_CLRBIT(sc, UDAV_RCR,
+ UDAV_RCR_PRMSC);
+ } else if (!(ifp->if_flags & IFF_RUNNING))
+ udav_init(ifp);
+ } else {
+ if (ifp->if_flags & IFF_RUNNING)
+ udav_stop(ifp, 1);
+ }
+ error = 0;
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ error = (cmd == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->sc_ac) :
+ ether_delmulti(ifr, &sc->sc_ac);
+ if (error == ENETRESET) {
+ udav_init(ifp);
+ }
+ udav_setmulti(sc);
+ error = 0;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+#else
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ if (error == ENETRESET) {
+ udav_setmulti(sc);
+ error = 0;
+ }
+ break;
+ }
+#endif /* defined(__OpenBSD__) */
+
+
+ splx(s);
+
+ return (error);
+}
+
+Static void
+udav_watchdog(struct ifnet *ifp)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct udav_chain *c;
+ usbd_status stat;
+ int s;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ ifp->if_oerrors++;
+ printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev));
+
+ s = splusb();
+ c = &sc->sc_cdata.udav_tx_chain[0];
+ usbd_get_xfer_status(c->udav_xfer, NULL, NULL, NULL, &stat);
+ udav_txeof(c->udav_xfer, c, stat);
+
+ if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
+ udav_start(ifp);
+ splx(s);
+}
+
+Static void
+udav_stop_task(struct udav_softc *sc)
+{
+ udav_stop(GET_IFP(sc), 1);
+}
+
+/* Stop the adapter and free any mbufs allocated to the RX and TX lists. */
+Static void
+udav_stop(struct ifnet *ifp, int disable)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ usbd_status err;
+ int i;
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ ifp->if_timer = 0;
+
+ udav_reset(sc);
+
+ usb_uncallout(sc->sc_stat_ch, udav_tick, sc);
+
+ /* Stop transfers */
+ /* RX endpoint */
+ if (sc->sc_pipe_rx != NULL) {
+ err = usbd_abort_pipe(sc->sc_pipe_rx);
+ if (err)
+ printf("%s: abort rx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ err = usbd_close_pipe(sc->sc_pipe_rx);
+ if (err)
+ printf("%s: close rx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ sc->sc_pipe_rx = NULL;
+ }
+
+ /* TX endpoint */
+ if (sc->sc_pipe_tx != NULL) {
+ err = usbd_abort_pipe(sc->sc_pipe_tx);
+ if (err)
+ printf("%s: abort tx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ err = usbd_close_pipe(sc->sc_pipe_tx);
+ if (err)
+ printf("%s: close tx pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ sc->sc_pipe_tx = NULL;
+ }
+
+#if 0
+ /* XXX: Interrupt endpoint is not yet supported!! */
+ /* Interrupt endpoint */
+ if (sc->sc_pipe_intr != NULL) {
+ err = usbd_abort_pipe(sc->sc_pipe_intr);
+ if (err)
+ printf("%s: abort intr pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ err = usbd_close_pipe(sc->sc_pipe_intr);
+ if (err)
+ printf("%s: close intr pipe failed: %s\n",
+ USBDEVNAME(sc->sc_dev), usbd_errstr(err));
+ sc->sc_pipe_intr = NULL;
+ }
+#endif
+
+ /* Free RX resources. */
+ for (i = 0; i < UDAV_RX_LIST_CNT; i++) {
+ if (sc->sc_cdata.udav_rx_chain[i].udav_mbuf != NULL) {
+ m_freem(sc->sc_cdata.udav_rx_chain[i].udav_mbuf);
+ sc->sc_cdata.udav_rx_chain[i].udav_mbuf = NULL;
+ }
+ if (sc->sc_cdata.udav_rx_chain[i].udav_xfer != NULL) {
+ usbd_free_xfer(sc->sc_cdata.udav_rx_chain[i].udav_xfer);
+ sc->sc_cdata.udav_rx_chain[i].udav_xfer = NULL;
+ }
+ }
+
+ /* Free TX resources. */
+ for (i = 0; i < UDAV_TX_LIST_CNT; i++) {
+ if (sc->sc_cdata.udav_tx_chain[i].udav_mbuf != NULL) {
+ m_freem(sc->sc_cdata.udav_tx_chain[i].udav_mbuf);
+ sc->sc_cdata.udav_tx_chain[i].udav_mbuf = NULL;
+ }
+ if (sc->sc_cdata.udav_tx_chain[i].udav_xfer != NULL) {
+ usbd_free_xfer(sc->sc_cdata.udav_tx_chain[i].udav_xfer);
+ sc->sc_cdata.udav_tx_chain[i].udav_xfer = NULL;
+ }
+ }
+
+ sc->sc_link = 0;
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+}
+
+/* Set media options */
+Static int
+udav_ifmedia_change(struct ifnet *ifp)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct mii_data *mii = GET_MII(sc);
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return (0);
+
+ sc->sc_link = 0;
+ if (mii->mii_instance) {
+ struct mii_softc *miisc;
+ for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
+ miisc = LIST_NEXT(miisc, mii_list))
+ mii_phy_reset(miisc);
+ }
+
+ return (mii_mediachg(mii));
+}
+
+/* Report current media status. */
+Static void
+udav_ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct udav_softc *sc = ifp->if_softc;
+ struct mii_data *mii = GET_MII(sc);
+
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+
+ if (sc->sc_dying)
+ return;
+
+ if ((ifp->if_flags & IFF_RUNNING) == 0) {
+ ifmr->ifm_active = IFM_ETHER | IFM_NONE;
+ ifmr->ifm_status = 0;
+ return;
+ }
+
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+Static void
+udav_tick(void *xsc)
+{
+ struct udav_softc *sc = xsc;
+
+ if (sc == NULL)
+ return;
+
+ DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
+ __func__));
+
+ if (sc->sc_dying)
+ return;
+
+ /* Perform periodic stuff in process context */
+ usb_add_task(sc->sc_udev, &sc->sc_tick_task);
+}
+
+Static void
+udav_tick_task(void *xsc)
+{
+ struct udav_softc *sc = xsc;
+ struct ifnet *ifp;
+ struct mii_data *mii;
+ int s;
+
+ if (sc == NULL)
+ return;
+
+ DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
+ __func__));
+
+ if (sc->sc_dying)
+ return;
+
+ ifp = GET_IFP(sc);
+ mii = GET_MII(sc);
+
+ if (mii == NULL)
+ return;
+
+ s = splnet();
+
+ mii_tick(mii);
+ if (!sc->sc_link) {
+ mii_pollstat(mii);
+ if (mii->mii_media_status & IFM_ACTIVE &&
+ IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
+ DPRINTF(("%s: %s: got link\n",
+ USBDEVNAME(sc->sc_dev), __func__));
+ sc->sc_link++;
+ if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
+ udav_start(ifp);
+ }
+ }
+
+ usb_callout(sc->sc_stat_ch, hz, udav_tick, sc);
+
+ splx(s);
+}
+
+/* Get exclusive access to the MII registers */
+Static void
+udav_lock_mii(struct udav_softc *sc)
+{
+ DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
+ __func__));
+
+ sc->sc_refcnt++;
+#if defined(__NetBSD__)
+ lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL);
+#else
+ usb_lockmgr(&sc->sc_mii_lock, LK_EXCLUSIVE, NULL, curproc);
+#endif
+}
+
+Static void
+udav_unlock_mii(struct udav_softc *sc)
+{
+ DPRINTFN(0xff, ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),
+ __func__));
+
+#if defined(__NetBSD__)
+ lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL);
+#else
+ usb_lockmgr(&sc->sc_mii_lock, LK_RELEASE, NULL, curproc);
+#endif
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+}
+
+Static int
+udav_miibus_readreg(device_ptr_t dev, int phy, int reg)
+{
+ struct udav_softc *sc;
+ u_int8_t val[2];
+ u_int16_t data16;
+
+ if (dev == NULL)
+ return (0);
+
+ sc = USBGETSOFTC(dev);
+
+ DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x\n",
+ USBDEVNAME(sc->sc_dev), __func__, phy, reg));
+
+ if (sc->sc_dying) {
+#ifdef DIAGNOSTIC
+ printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev),
+ __func__);
+#endif
+ return (0);
+ }
+
+ /* XXX: one PHY only for the internal PHY */
+ if (phy != 0) {
+ DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
+ USBDEVNAME(sc->sc_dev), __func__, phy));
+ return (0);
+ }
+
+ udav_lock_mii(sc);
+
+ /* select internal PHY and set PHY register address */
+ udav_csr_write1(sc, UDAV_EPAR,
+ UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
+
+ /* select PHY operation and start read command */
+ udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRR);
+
+ /* XXX: should be wait? */
+
+ /* end read command */
+ UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRR);
+
+ /* retrieve the result from data registers */
+ udav_csr_read(sc, UDAV_EPDRL, val, 2);
+
+ udav_unlock_mii(sc);
+
+ data16 = val[0] | (val[1] << 8);
+
+ DPRINTFN(0xff, ("%s: %s: phy=%d reg=0x%04x => 0x%04x\n",
+ USBDEVNAME(sc->sc_dev), __func__, phy, reg, data16));
+
+ return (data16);
+}
+
+Static void
+udav_miibus_writereg(device_ptr_t dev, int phy, int reg, int data)
+{
+ struct udav_softc *sc;
+ u_int8_t val[2];
+
+ if (dev == NULL)
+ return;
+
+ sc = USBGETSOFTC(dev);
+
+ DPRINTFN(0xff, ("%s: %s: enter, phy=%d reg=0x%04x data=0x%04x\n",
+ USBDEVNAME(sc->sc_dev), __func__, phy, reg, data));
+
+ if (sc->sc_dying) {
+#ifdef DIAGNOSTIC
+ printf("%s: %s: dying\n", USBDEVNAME(sc->sc_dev),
+ __func__);
+#endif
+ return;
+ }
+
+ /* XXX: one PHY only for the internal PHY */
+ if (phy != 0) {
+ DPRINTFN(0xff, ("%s: %s: phy=%d is not supported\n",
+ USBDEVNAME(sc->sc_dev), __func__, phy));
+ return;
+ }
+
+ udav_lock_mii(sc);
+
+ /* select internal PHY and set PHY register address */
+ udav_csr_write1(sc, UDAV_EPAR,
+ UDAV_EPAR_PHY_ADR0 | (reg & UDAV_EPAR_EROA_MASK));
+
+ /* put the value to the data registers */
+ val[0] = data & 0xff;
+ val[1] = (data >> 8) & 0xff;
+ udav_csr_write(sc, UDAV_EPDRL, val, 2);
+
+ /* select PHY operation and start write command */
+ udav_csr_write1(sc, UDAV_EPCR, UDAV_EPCR_EPOS | UDAV_EPCR_ERPRW);
+
+ /* XXX: should be wait? */
+
+ /* end write command */
+ UDAV_CLRBIT(sc, UDAV_EPCR, UDAV_EPCR_ERPRW);
+
+ udav_unlock_mii(sc);
+
+ return;
+}
+
+Static void
+udav_miibus_statchg(device_ptr_t dev)
+{
+#ifdef UDAV_DEBUG
+ struct udav_softc *sc;
+
+ if (dev == NULL)
+ return;
+
+ sc = USBGETSOFTC(dev);
+ DPRINTF(("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));
+#endif
+ /* Nothing to do */
+}
diff --git a/sys/dev/usb/if_udavreg.h b/sys/dev/usb/if_udavreg.h
new file mode 100644
index 00000000000..6dff5f17762
--- /dev/null
+++ b/sys/dev/usb/if_udavreg.h
@@ -0,0 +1,214 @@
+/* $OpenBSD: if_udavreg.h,v 1.1 2004/10/05 02:01:18 jsg Exp $ */
+/* $NetBSD: if_udavreg.h,v 1.2 2003/09/04 15:17:39 tsutsui Exp $ */
+/* $nabe: if_udavreg.h,v 1.2 2003/08/21 16:26:40 nabe Exp $ */
+/*
+ * Copyright (c) 2003
+ * Shingo WATANABE <nabe@nabechan.org>. 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.
+ * 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 author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define UDAV_IFACE_INDEX 0
+#define UDAV_CONFIG_NO 1
+
+#define UDAV_TX_LIST_CNT 1
+#define UDAV_RX_LIST_CNT 1
+
+#define UDAV_TX_TIMEOUT 1000
+#define UDAV_TIMEOUT 10000
+
+#define ETHER_ALIGN 2
+
+
+/* Packet length */
+#define UDAV_MAX_MTU 1536 /* XXX: max frame size is unknown */
+#define UDAV_MIN_FRAME_LEN 60
+#define UDAV_BUFSZ UDAV_MAX_MTU
+
+/* Request */
+#define UDAV_REQ_REG_READ 0x00 /* Read from register(s) */
+#define UDAV_REQ_REG_WRITE 0x01 /* Write to register(s) */
+#define UDAV_REQ_REG_WRITE1 0x03 /* Write to a register */
+
+#define UDAV_REQ_MEM_READ 0x02 /* Read from memory */
+#define UDAV_REQ_MEM_WRITE 0x05 /* Write to memory */
+#define UDAV_REQ_MEM_WRITE1 0x07 /* Write a byte to memory */
+
+/* Registers */
+#define UDAV_NCR 0x00 /* Network Control Register */
+#define UDAV_NCR_EXT_PHY (1<<7) /* Select External PHY */
+#define UDAV_NCR_WAKEEN (1<<6) /* Wakeup Event Enable */
+#define UDAV_NCR_FCOL (1<<4) /* Force Collision Mode */
+#define UDAV_NCR_FDX (1<<3) /* Full-Duplex Mode (RO on Int. PHY) */
+#define UDAV_NCR_LBK1 (1<<2) /* Lookback Mode */
+#define UDAV_NCR_LBK0 (1<<1) /* Lookback Mode */
+#define UDAV_NCR_RST (1<<0) /* Software reset */
+
+#define UDAV_RCR 0x05 /* RX Control Register */
+#define UDAV_RCR_WTDIS (1<<6) /* Watchdog Timer Disable */
+#define UDAV_RCR_DIS_LONG (1<<5) /* Discard Long Packet(over 1522Byte) */
+#define UDAV_RCR_DIS_CRC (1<<4) /* Discard CRC Error Packet */
+#define UDAV_RCR_ALL (1<<3) /* Pass All Multicast */
+#define UDAV_RCR_RUNT (1<<2) /* Pass Runt Packet */
+#define UDAV_RCR_PRMSC (1<<1) /* Promiscuous Mode */
+#define UDAV_RCR_RXEN (1<<0) /* RX Enable */
+
+#define UDAV_RSR 0x06 /* RX Status Register */
+#define UDAV_RSR_RF (1<<7) /* Runt Frame */
+#define UDAV_RSR_MF (1<<6) /* Multicast Frame */
+#define UDAV_RSR_LCS (1<<5) /* Late Collision Seen */
+#define UDAV_RSR_RWTO (1<<4) /* Receive Watchdog Time-Out */
+#define UDAV_RSR_PLE (1<<3) /* Physical Layer Error */
+#define UDAV_RSR_AE (1<<2) /* Alignment Error */
+#define UDAV_RSR_CE (1<<1) /* CRC Error */
+#define UDAV_RSR_FOE (1<<0) /* FIFO Overflow Error */
+#define UDAV_RSR_ERR (UDAV_RSR_RF | UDAV_RSR_LCS | UDAV_RSR_RWTO |\
+ UDAV_RSR_PLE | UDAV_RSR_AE | UDAV_RSR_CE |\
+ UDAV_RSR_FOE)
+
+#define UDAV_EPCR 0x0b /* EEPROM & PHY Control Register */
+#define UDAV_EPCR_REEP (1<<5) /* Reload EEPROM */
+#define UDAV_EPCR_WEP (1<<4) /* Write EEPROM enable */
+#define UDAV_EPCR_EPOS (1<<3) /* EEPROM or PHY Operation Select */
+#define UDAV_EPCR_ERPRR (1<<2) /* EEPROM/PHY Register Read Command */
+#define UDAV_EPCR_ERPRW (1<<1) /* EEPROM/PHY Register Write Command */
+#define UDAV_EPCR_ERRE (1<<0) /* EEPROM/PHY Access Status */
+
+#define UDAV_EPAR 0x0c /* EEPROM & PHY Control Register */
+#define UDAV_EPAR_PHY_ADR1 (1<<7) /* PHY Address bit 1 */
+#define UDAV_EPAR_PHY_ADR0 (1<<6) /* PHY Address bit 0 */
+#define UDAV_EPAR_EROA (1<<0) /* EEPROM Word/PHY Register Address */
+#define UDAV_EPAR_EROA_MASK (0x1f) /* [5:0] */
+
+#define UDAV_EPDRL 0x0d /* EEPROM & PHY Data Register */
+#define UDAV_EPDRH 0x0e /* EEPROM & PHY Data Register */
+
+#define UDAV_PAR0 0x10 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR1 0x11 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR2 0x12 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR3 0x13 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR4 0x14 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR5 0x15 /* Ethernet Address, load from EEPROM */
+#define UDAV_PAR UDAV_PAR0
+
+#define UDAV_MAR0 0x16 /* Multicast Register */
+#define UDAV_MAR1 0x17 /* Multicast Register */
+#define UDAV_MAR2 0x18 /* Multicast Register */
+#define UDAV_MAR3 0x19 /* Multicast Register */
+#define UDAV_MAR4 0x1a /* Multicast Register */
+#define UDAV_MAR5 0x1b /* Multicast Register */
+#define UDAV_MAR6 0x1c /* Multicast Register */
+#define UDAV_MAR7 0x1d /* Multicast Register */
+#define UDAV_MAR UDAV_MAR0
+
+#define UDAV_GPCR 0x1e /* General purpose control register */
+#define UDAV_GPCR_GEP_CNTL6 (1<<6) /* General purpose control 6 */
+#define UDAV_GPCR_GEP_CNTL5 (1<<5) /* General purpose control 5 */
+#define UDAV_GPCR_GEP_CNTL4 (1<<4) /* General purpose control 4 */
+#define UDAV_GPCR_GEP_CNTL3 (1<<3) /* General purpose control 3 */
+#define UDAV_GPCR_GEP_CNTL2 (1<<2) /* General purpose control 2 */
+#define UDAV_GPCR_GEP_CNTL1 (1<<1) /* General purpose control 1 */
+#define UDAV_GPCR_GEP_CNTL0 (1<<0) /* General purpose control 0 */
+
+#define UDAV_GPR 0x1f /* General purpose register */
+#define UDAV_GPR_GEPIO6 (1<<6) /* General purpose 6 */
+#define UDAV_GPR_GEPIO5 (1<<5) /* General purpose 5 */
+#define UDAV_GPR_GEPIO4 (1<<4) /* General purpose 4 */
+#define UDAV_GPR_GEPIO3 (1<<3) /* General purpose 3 */
+#define UDAV_GPR_GEPIO2 (1<<2) /* General purpose 2 */
+#define UDAV_GPR_GEPIO1 (1<<1) /* General purpose 1 */
+#define UDAV_GPR_GEPIO0 (1<<0) /* General purpose 0 */
+
+#if defined(__NetBSD__)
+#define GET_IFP(sc) (&(sc)->sc_ec.ec_if)
+#else
+#define GET_IFP(sc) (&(sc)->sc_ac.ac_if)
+#endif
+#define GET_MII(sc) (&(sc)->sc_mii)
+
+struct udav_chain {
+ struct udav_softc *udav_sc;
+ usbd_xfer_handle udav_xfer;
+ char *udav_buf;
+ struct mbuf *udav_mbuf;
+ int udav_idx;
+};
+
+struct udav_cdata {
+ struct udav_chain udav_tx_chain[UDAV_TX_LIST_CNT];
+ struct udav_chain udav_rx_chain[UDAV_TX_LIST_CNT];
+#if 0
+ /* XXX: Intrrupt Endpoint is not yet supported! */
+ struct udav_intrpkg udav_ibuf;
+#endif
+ int udav_tx_prod;
+ int udav_tx_cons;
+ int udav_tx_cnt;
+ int udav_rx_prod;
+};
+
+struct udav_softc {
+ USBBASEDEVICE sc_dev; /* base device */
+ usbd_device_handle sc_udev;
+
+ /* USB */
+ usbd_interface_handle sc_ctl_iface;
+ /* int sc_ctl_iface_no; */
+ int sc_bulkin_no; /* bulk in endpoint */
+ int sc_bulkout_no; /* bulk out endpoint */
+ int sc_intrin_no; /* intr in endpoint */
+ usbd_pipe_handle sc_pipe_rx;
+ usbd_pipe_handle sc_pipe_tx;
+ usbd_pipe_handle sc_pipe_intr;
+ usb_callout_t sc_stat_ch;
+ u_int sc_rx_errs;
+ /* u_int sc_intr_errs; */
+ struct timeval sc_rx_notice;
+
+ /* Ethernet */
+#if defined(__NetBSD__)
+ struct ethercom sc_ec; /* ethernet common */
+#else
+ struct arpcom sc_ac; /* ethernet common */
+#endif
+ struct mii_data sc_mii;
+ struct lock sc_mii_lock;
+ int sc_link;
+#define sc_media udav_mii.mii_media
+#if NRND > 0
+ rndsource_element_t rnd_source;
+#endif
+ struct udav_cdata sc_cdata;
+
+ int sc_attached;
+ int sc_dying;
+ int sc_refcnt;
+
+ struct usb_task sc_tick_task;
+ struct usb_task sc_stop_task;
+
+ u_int16_t sc_flags;
+};
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 50d58327ce6..3342c7999d0 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_port.h,v 1.50 2004/08/30 03:06:48 drahn Exp $ */
+/* $OpenBSD: usb_port.h,v 1.51 2004/10/05 02:01:18 jsg Exp $ */
/* $NetBSD: usb_port.h,v 1.62 2003/02/15 18:33:30 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.21 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -82,6 +82,7 @@ MALLOC_DECLARE(M_USBHC);
#define AXE_DEBUG 1
#define CUE_DEBUG 1
#define KUE_DEBUG 1
+#define UDAV_DEBUG 1
#define URL_DEBUG 1
#define UMASS_DEBUG 1
#define UVISOR_DEBUG 1
@@ -222,6 +223,7 @@ int __CONCAT(dname,_detach)(struct device *self, int flags)
#define AUE_DEBUG 1
#define CUE_DEBUG 1
#define KUE_DEBUG 1
+#define UDAV_DEBUG 1
#define UMASS_DEBUG 1
#define UVISOR_DEBUG 1
#define UPL_DEBUG 1