aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2000-01-20 07:38:33 +0000
committerBill Paul <wpaul@FreeBSD.org>2000-01-20 07:38:33 +0000
commita6d9a40e8163f779fb153df81631a6ab9f441bb4 (patch)
tree257dd3a68bb1d36943d4bed83eff93d8fcaad2c7 /sys
parenta5c3c93893fc8aca96d072a8e84d3602c6ed194a (diff)
downloadsrc-a6d9a40e8163f779fb153df81631a6ab9f441bb4.tar.gz
src-a6d9a40e8163f779fb153df81631a6ab9f441bb4.zip
More USB ethernet tweaks:
- Sync ohci, uhci and usbdi modules with NetBSD in order to obtain the following improvements: o New USBD_NO_TSLEEP flag can be used in place of UQ_NO_TSLEEP quirk. This allows drivers to specify busy waiting only for certain transfers (namely control transfers for reading/writing registers and stuff). o New USBD_FORCE_SHORT_XFER flag can be used to deal with devices like the ADMtek Pegasus that sense the end of bulk OUT transfers in a special way (if a transfer is exactly a multiple of 64 bytes in size, you need to send an extra empty packet to terminate the transfer). o usbd_open_pipe_intr() now accepts an interval argument which can be used to change the rate at which the interrupt callback routine is invoked. Specifying USBD_DEFAULT_INTERVAL uses the value specified in the device's config data, but drivers can override it if needed. - Change if_aue to use USBD_FORCE_SHORT_XFER for packet transmissions. - Change if_aue, if_kue and if_cue to use USBD_NO_TSLEEP for all control transfers. We no longer force the non-tsleep hack for bulk transfers since these are done asynchronously anyway. - Removed quirk entry fiddling from if_aue and if_kue since we don't need it anymore now that we have the USBD_NO_TSLEEP flag. - Tweak ulpt, uhid, ums and ukbd drivers to use the new arg to usbd_open_pipe_intr(). - Add a flag to the softc struct in the ethernet drivers to indicate when a device has been detached, and use this flag to perform tests to prevent the drivers from trying to do control transfers if this is the case. This is necessary because calling if_detach() with INET6 enabled will eventually result in a call to the driver's ioctl() routine to delete the multicast groups on the interface, which will result in attempts to perform control transfers. (It's possible this also happens even without INET6 support enabled.) This is pointless since we know that if the detach method has been called, the hardware has been unplugged. - Changed watchdog timeout routines to just call the driver init routines to initialize the device states without trying to close and re-open the pipes. This is partly because we don't want to frob things at interrupt context, but also because this doesn't seem to work right and I don't want to panic the system just because a USB device may have stopped responding. - Fix aue_rxeof() to be a little smarter about detecting when a double transfer is needed. Unfortunately, the design of the chip makes it hard to get this exactly right. Hopefully, this will go away once either Nick or Lennart finds the bug in the uhci driver that makes this ugly hack necessary. - Also sync usbdevs with NetBSD.
Notes
Notes: svn path=/head/; revision=56318
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/if_aue.c53
-rw-r--r--sys/dev/usb/if_auereg.h2
-rw-r--r--sys/dev/usb/if_cue.c61
-rw-r--r--sys/dev/usb/if_cuereg.h1
-rw-r--r--sys/dev/usb/if_kue.c33
-rw-r--r--sys/dev/usb/if_kuereg.h1
-rw-r--r--sys/dev/usb/ohci.c443
-rw-r--r--sys/dev/usb/ohcireg.h29
-rw-r--r--sys/dev/usb/ohcivar.h16
-rw-r--r--sys/dev/usb/ugen.c3
-rw-r--r--sys/dev/usb/uhci.c186
-rw-r--r--sys/dev/usb/uhcireg.h4
-rw-r--r--sys/dev/usb/uhcivar.h29
-rw-r--r--sys/dev/usb/uhid.c2
-rw-r--r--sys/dev/usb/uhub.c2
-rw-r--r--sys/dev/usb/ukbd.c3
-rw-r--r--sys/dev/usb/ums.c3
-rw-r--r--sys/dev/usb/usb_quirks.c36
-rw-r--r--sys/dev/usb/usb_subr.c76
-rw-r--r--sys/dev/usb/usbdevs404
-rw-r--r--sys/dev/usb/usbdi.c97
-rw-r--r--sys/dev/usb/usbdi.h32
-rw-r--r--sys/dev/usb/usbdivar.h48
23 files changed, 1040 insertions, 524 deletions
diff --git a/sys/dev/usb/if_aue.c b/sys/dev/usb/if_aue.c
index 42f28f4eeb43..7971fc397dc4 100644
--- a/sys/dev/usb/if_aue.c
+++ b/sys/dev/usb/if_aue.c
@@ -203,6 +203,9 @@ static int csr_read_1(sc, reg)
u_int8_t val = 0;
int s;
+ if (sc->aue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_READ_VENDOR_DEVICE;
@@ -211,7 +214,8 @@ static int csr_read_1(sc, reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 1);
- err = usbd_do_request(sc->aue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->aue_udev, &req,
+ &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -230,6 +234,9 @@ static int csr_read_2(sc, reg)
u_int16_t val = 0;
int s;
+ if (sc->aue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_READ_VENDOR_DEVICE;
@@ -238,7 +245,8 @@ static int csr_read_2(sc, reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 2);
- err = usbd_do_request(sc->aue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->aue_udev, &req,
+ &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -256,6 +264,9 @@ static int csr_write_1(sc, reg, val)
usbd_status err;
int s;
+ if (sc->aue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -264,7 +275,8 @@ static int csr_write_1(sc, reg, val)
USETW(req.wIndex, reg);
USETW(req.wLength, 1);
- err = usbd_do_request(sc->aue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->aue_udev, &req,
+ &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -282,6 +294,9 @@ static int csr_write_2(sc, reg, val)
usbd_status err;
int s;
+ if (sc->aue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -290,7 +305,8 @@ static int csr_write_2(sc, reg, val)
USETW(req.wIndex, reg);
USETW(req.wLength, 2);
- err = usbd_do_request(sc->aue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->aue_udev, &req,
+ &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -713,6 +729,7 @@ USB_ATTACH(aue)
callout_handle_init(&sc->aue_stat_ch);
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
usb_register_netisr();
+ sc->aue_gone = 0;
splx(s);
USB_ATTACH_SUCCESS_RETURN;
@@ -730,6 +747,7 @@ static int aue_detach(dev)
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
+ sc->aue_gone = 1;
untimeout(aue_tick, sc, sc->aue_stat_ch);
if_detach(ifp);
@@ -872,7 +890,7 @@ static void aue_intr(xfer, priv, status)
if (p->aue_txstat0)
ifp->if_oerrors++;
- if (p->aue_txstat0 & (AUE_TXSTAT0_LATECOLL | AUE_TXSTAT0_EXCESSCOLL))
+ if (p->aue_txstat0 & (AUE_TXSTAT0_LATECOLL & AUE_TXSTAT0_EXCESSCOLL))
ifp->if_collisions++;
splx(s);
@@ -971,7 +989,7 @@ static void aue_rxeof(xfer, priv, status)
* split transfer. We really need a more reliable way
* to detect this.
*/
- if (r.aue_pktlen != total_len && total_len == AUE_CUTOFF) {
+ if (r.aue_pktlen != AUE_CUTOFF && total_len == AUE_CUTOFF) {
c->aue_accum = AUE_CUTOFF;
usbd_setup_xfer(xfer, sc->aue_ep[AUE_ENDPT_RX],
c, mtod(c->aue_mbuf, char *) + AUE_CUTOFF,
@@ -1120,15 +1138,7 @@ static int aue_encap(sc, m, idx)
m_copydata(m, 0, m->m_pkthdr.len, c->aue_buf + 2);
c->aue_mbuf = m;
- /*
- * XXX I don't understand why, but transfers that
- * are exactly a multiple of 64 bytes in size don't
- * work. I'm not sure why. If we detect such a
- * transfer, we pad it out by one extra byte.
- */
total_len = m->m_pkthdr.len + 2;
- if (!(total_len % 64))
- total_len++;
/*
* The ADMtek documentation says that the packet length is
@@ -1140,7 +1150,8 @@ static int aue_encap(sc, m, idx)
c->aue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
usbd_setup_xfer(c->aue_xfer, sc->aue_ep[AUE_ENDPT_TX],
- c, c->aue_buf, total_len, 0, 10000, aue_txeof);
+ c, c->aue_buf, total_len, USBD_FORCE_SHORT_XFER,
+ 10000, aue_txeof);
/* Transmit */
err = usbd_transfer(c->aue_xfer);
@@ -1274,7 +1285,8 @@ static void aue_init(xsc)
err = usbd_open_pipe_intr(sc->aue_iface, sc->aue_ed[AUE_ENDPT_INTR],
USBD_SHORT_XFER_OK, &sc->aue_ep[AUE_ENDPT_INTR], sc,
- sc->aue_cdata.aue_ibuf, AUE_INTR_PKTLEN, aue_intr);
+ sc->aue_cdata.aue_ibuf, AUE_INTR_PKTLEN, aue_intr,
+ AUE_INTR_INTERVAL);
if (err) {
printf("aue%d: open intr pipe failed: %s\n",
sc->aue_unit, usbd_errstr(err));
@@ -1412,16 +1424,7 @@ static void aue_watchdog(ifp)
ifp->if_oerrors++;
printf("aue%d: watchdog timeout\n", sc->aue_unit);
- /*
- * The polling business is a kludge to avoid allowing the
- * USB code to call tsleep() in usbd_delay_ms(), which will
- * kill us since the watchdog routine is invoked from
- * interrupt context.
- */
- sc->aue_udev->bus->use_polling++;
- aue_stop(sc);
aue_init(sc);
- sc->aue_udev->bus->use_polling--;
if (ifp->if_snd.ifq_head != NULL)
aue_start(ifp);
diff --git a/sys/dev/usb/if_auereg.h b/sys/dev/usb/if_auereg.h
index 23a7c930a80c..20caa52e7466 100644
--- a/sys/dev/usb/if_auereg.h
+++ b/sys/dev/usb/if_auereg.h
@@ -243,6 +243,7 @@ struct aue_softc {
usbd_pipe_handle aue_ep[AUE_ENDPT_MAX];
int aue_unit;
u_int8_t aue_link;
+ u_int8_t aue_gone;
int aue_if_flags;
struct aue_cdata aue_cdata;
struct callout_handle aue_stat_ch;
@@ -253,3 +254,4 @@ struct aue_softc {
#define AUE_BUFSZ 1536
#define AUE_CUTOFF 1088
#define AUE_MIN_FRAMELEN 60
+#define AUE_INTR_INTERVAL 100 /* ms */
diff --git a/sys/dev/usb/if_cue.c b/sys/dev/usb/if_cue.c
index 16899a201d0b..7cbf68ffbd6c 100644
--- a/sys/dev/usb/if_cue.c
+++ b/sys/dev/usb/if_cue.c
@@ -73,7 +73,6 @@
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdevs.h>
-#include <dev/usb/usb_quirks.h>
#include <dev/usb/usb_ethersubr.h>
#include <dev/usb/if_cuereg.h>
@@ -165,6 +164,9 @@ static int csr_read_1(sc, reg)
u_int8_t val = 0;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_READ_VENDOR_DEVICE;
@@ -173,7 +175,8 @@ static int csr_read_1(sc, reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 1);
- err = usbd_do_request(sc->cue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -192,6 +195,9 @@ static int csr_read_2(sc, reg)
u_int16_t val = 0;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_READ_VENDOR_DEVICE;
@@ -200,7 +206,8 @@ static int csr_read_2(sc, reg)
USETW(req.wIndex, reg);
USETW(req.wLength, 2);
- err = usbd_do_request(sc->cue_udev, &req, &val);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -218,6 +225,9 @@ static int csr_write_1(sc, reg, val)
usbd_status err;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -226,7 +236,8 @@ static int csr_write_1(sc, reg, val)
USETW(req.wIndex, reg);
USETW(req.wLength, 0);
- err = usbd_do_request(sc->cue_udev, &req, NULL);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -245,6 +256,9 @@ static int csr_write_2(sc, reg, val)
usbd_status err;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -253,7 +267,8 @@ static int csr_write_2(sc, reg, val)
USETW(req.wIndex, reg);
USETW(req.wLength, 0);
- err = usbd_do_request(sc->cue_udev, &req, NULL);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, &val, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -275,6 +290,9 @@ static int cue_mem(sc, cmd, addr, buf, len)
usbd_status err;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
if (cmd == CUE_CMD_READSRAM)
@@ -286,7 +304,8 @@ static int cue_mem(sc, cmd, addr, buf, len)
USETW(req.wIndex, addr);
USETW(req.wLength, len);
- err = usbd_do_request(sc->cue_udev, &req, buf);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, &buf, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -304,6 +323,9 @@ static int cue_getmac(sc, buf)
usbd_status err;
int s;
+ if (sc->cue_gone)
+ return(0);
+
s = splusb();
req.bmRequestType = UT_READ_VENDOR_DEVICE;
@@ -312,7 +334,8 @@ static int cue_getmac(sc, buf)
USETW(req.wIndex, 0);
USETW(req.wLength, ETHER_ADDR_LEN);
- err = usbd_do_request(sc->cue_udev, &req, buf);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, buf, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -395,6 +418,9 @@ static void cue_reset(sc)
usbd_status err;
int s;
+ if (sc->cue_gone)
+ return;
+
s = splusb();
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
@@ -402,7 +428,8 @@ static void cue_reset(sc)
USETW(req.wValue, 0);
USETW(req.wIndex, 0);
USETW(req.wLength, 0);
- err = usbd_do_request(sc->cue_udev, &req, NULL);
+ err = usbd_do_request_flags(sc->cue_udev,
+ &req, NULL, USBD_NO_TSLEEP, NULL);
splx(s);
@@ -421,19 +448,14 @@ USB_MATCH(cue)
{
USB_MATCH_START(cue, uaa);
struct cue_type *t;
- usb_device_descriptor_t *dd;
if (!uaa->iface)
return(UMATCH_NONE);
- dd = &uaa->device->ddesc;
-
t = cue_devs;
while(t->cue_vid) {
if (uaa->vendor == t->cue_vid &&
uaa->product == t->cue_did) {
- USETW(dd->bcdDevice, 0x220);
- uaa->device->quirks = usbd_find_quirk(dd);
return(UMATCH_VENDOR_PRODUCT);
}
t++;
@@ -539,6 +561,7 @@ USB_ATTACH(cue)
callout_handle_init(&sc->cue_stat_ch);
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
usb_register_netisr();
+ sc->cue_gone = 0;
splx(s);
USB_ATTACH_SUCCESS_RETURN;
@@ -556,6 +579,7 @@ static int cue_detach(dev)
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
+ sc->cue_gone = 1;
untimeout(cue_tick, sc, sc->cue_stat_ch);
if_detach(ifp);
@@ -1023,7 +1047,7 @@ static void cue_init(xsc)
c = &sc->cue_cdata.cue_rx_chain[i];
usbd_setup_xfer(c->cue_xfer, sc->cue_ep[CUE_ENDPT_RX],
c, mtod(c->cue_mbuf, char *), CUE_CUTOFF,
- USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof);
+ USBD_SHORT_XFER_OK, USBD_NO_TIMEOUT, cue_rxeof);
usbd_transfer(c->cue_xfer);
}
@@ -1099,16 +1123,7 @@ static void cue_watchdog(ifp)
ifp->if_oerrors++;
printf("cue%d: watchdog timeout\n", sc->cue_unit);
- /*
- * The polling business is a kludge to avoid allowing the
- * USB code to call tsleep() in usbd_delay_ms(), which will
- * kill us since the watchdog routine is invoked from
- * interrupt context.
- */
- sc->cue_udev->bus->use_polling++;
- cue_stop(sc);
cue_init(sc);
- sc->cue_udev->bus->use_polling--;
if (ifp->if_snd.ifq_head != NULL)
cue_start(ifp);
diff --git a/sys/dev/usb/if_cuereg.h b/sys/dev/usb/if_cuereg.h
index 392184303772..19e6a43eb117 100644
--- a/sys/dev/usb/if_cuereg.h
+++ b/sys/dev/usb/if_cuereg.h
@@ -176,6 +176,7 @@ struct cue_softc {
int cue_unit;
u_int8_t cue_mctab[CUE_MCAST_TABLE_LEN];
int cue_if_flags;
+ u_int8_t cue_gone;
u_int16_t cue_rxfilt;
struct cue_cdata cue_cdata;
struct callout_handle cue_stat_ch;
diff --git a/sys/dev/usb/if_kue.c b/sys/dev/usb/if_kue.c
index c2b5a53ebfc2..21b6b3878ed5 100644
--- a/sys/dev/usb/if_kue.c
+++ b/sys/dev/usb/if_kue.c
@@ -88,7 +88,6 @@
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdevs.h>
-#include <dev/usb/usb_quirks.h>
#include <dev/usb/usb_ethersubr.h>
#include <dev/usb/if_kuereg.h>
@@ -104,14 +103,14 @@ static const char rcsid[] =
*/
static struct kue_type kue_devs[] = {
{ USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 },
- { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET },
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT },
{ USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T },
{ USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 },
{ USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET },
{ USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 },
{ USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 },
{ USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 },
- { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_USB_T },
+ { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T },
{ USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C },
{ USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB },
{ 0, 0 }
@@ -187,7 +186,7 @@ static usbd_status kue_do_request(dev, req, data)
xfer = usbd_alloc_xfer(dev);
usbd_setup_default_xfer(xfer, dev, 0, 500000, req,
- data, UGETW(req->wLength), USBD_SHORT_XFER_OK, 0);
+ data, UGETW(req->wLength), USBD_SHORT_XFER_OK|USBD_NO_TSLEEP, 0);
err = usbd_sync_transfer(xfer);
usbd_free_xfer(xfer);
return(err);
@@ -203,6 +202,9 @@ static usbd_status kue_setword(sc, breq, word)
usbd_status err;
int s;
+ if (sc->kue_gone)
+ return(USBD_NORMAL_COMPLETION);
+
dev = sc->kue_udev;
s = splusb();
@@ -236,6 +238,9 @@ static usbd_status kue_ctl(sc, rw, breq, val, data, len)
dev = sc->kue_udev;
+ if (sc->kue_gone)
+ return(USBD_NORMAL_COMPLETION);
+
s = splusb();
if (rw == KUE_CTL_WRITE)
@@ -266,14 +271,6 @@ static int kue_load_fw(sc)
hwrev = UGETW(dd->bcdDevice);
/*
- * Force the revision code and rescan the quirks
- * database: the adapter will return a different
- * revision code if the firmware is already running.
- */
- USETW(dd->bcdDevice, 0x002);
- sc->kue_udev->quirks = usbd_find_quirk(dd);
-
- /*
* First, check if we even need to load the firmware.
* If the device was still attached when the system was
* rebooted, it may already have firmware loaded in it.
@@ -505,6 +502,7 @@ USB_ATTACH(kue)
ether_ifattach(ifp);
bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));
usb_register_netisr();
+ sc->kue_gone = 0;
splx(s);
USB_ATTACH_SUCCESS_RETURN;
@@ -522,6 +520,8 @@ static int kue_detach(dev)
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
+ sc->kue_gone = 1;
+
if (ifp != NULL)
if_detach(ifp);
@@ -1002,16 +1002,7 @@ static void kue_watchdog(ifp)
ifp->if_oerrors++;
printf("kue%d: watchdog timeout\n", sc->kue_unit);
- /*
- * The polling business is a kludge to avoid allowing the
- * USB code to call tsleep() in usbd_delay_ms(), which will
- * kill us since the watchdog routine is invoked from
- * interrupt context.
- */
- sc->kue_udev->bus->use_polling++;
- kue_stop(sc);
kue_init(sc);
- sc->kue_udev->bus->use_polling--;
if (ifp->if_snd.ifq_head != NULL)
kue_start(ifp);
diff --git a/sys/dev/usb/if_kuereg.h b/sys/dev/usb/if_kuereg.h
index 6b3e56307918..97b629a74bc6 100644
--- a/sys/dev/usb/if_kuereg.h
+++ b/sys/dev/usb/if_kuereg.h
@@ -167,6 +167,7 @@ struct kue_softc {
usbd_pipe_handle kue_ep[KUE_ENDPT_MAX];
int kue_unit;
int kue_if_flags;
+ u_int8_t kue_gone;
u_int16_t kue_rxfilt;
u_int8_t *kue_mcfilters;
struct kue_cdata kue_cdata;
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 3bbc809061ec..c5a2d8180d07 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ohci.c,v 1.55 1999/11/18 23:32:26 augustss Exp $ */
+/* $NetBSD: ohci.c,v 1.64 2000/01/19 00:23:58 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -115,15 +115,21 @@ static void ohci_free_sed __P((ohci_softc_t *, ohci_soft_ed_t *));
static ohci_soft_td_t *ohci_alloc_std __P((ohci_softc_t *));
static void ohci_free_std __P((ohci_softc_t *, ohci_soft_td_t *));
+static ohci_soft_itd_t *ohci_alloc_sitd __P((ohci_softc_t *));
+static void ohci_free_sitd __P((ohci_softc_t *,ohci_soft_itd_t *));
+
#if 0
static void ohci_free_std_chain __P((ohci_softc_t *,
ohci_soft_td_t *, ohci_soft_td_t *));
#endif
static usbd_status ohci_alloc_std_chain __P((struct ohci_pipe *,
- ohci_softc_t *, int, int, int, usb_dma_t *,
+ ohci_softc_t *, int, int, u_int16_t, usb_dma_t *,
ohci_soft_td_t *, ohci_soft_td_t **));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+static void ohci_shutdown __P((void *v));
static void ohci_power __P((int, void *));
+#endif
static usbd_status ohci_open __P((usbd_pipe_handle));
static void ohci_poll __P((struct usbd_bus *));
static void ohci_waitintr __P((ohci_softc_t *,
@@ -142,10 +148,16 @@ static void ohci_hash_rem_td __P((ohci_softc_t *,
static ohci_soft_td_t *ohci_hash_find_td __P((ohci_softc_t *,
ohci_physaddr_t));
+static usbd_status ohci_setup_isoc __P((usbd_pipe_handle pipe));
+static void ohci_device_isoc_enter __P((usbd_xfer_handle));
+
static usbd_status ohci_allocm __P((struct usbd_bus *, usb_dma_t *,
u_int32_t));
static void ohci_freem __P((struct usbd_bus *, usb_dma_t *));
+static usbd_xfer_handle ohci_allocx __P((struct usbd_bus *));
+static void ohci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
static usbd_status ohci_root_ctrl_transfer __P((usbd_xfer_handle));
static usbd_status ohci_root_ctrl_start __P((usbd_xfer_handle));
static void ohci_root_ctrl_abort __P((usbd_xfer_handle));
@@ -175,13 +187,11 @@ static void ohci_device_intr_abort __P((usbd_xfer_handle));
static void ohci_device_intr_close __P((usbd_pipe_handle));
static void ohci_device_intr_done __P((usbd_xfer_handle));
-#if 0
static usbd_status ohci_device_isoc_transfer __P((usbd_xfer_handle));
static usbd_status ohci_device_isoc_start __P((usbd_xfer_handle));
static void ohci_device_isoc_abort __P((usbd_xfer_handle));
static void ohci_device_isoc_close __P((usbd_pipe_handle));
static void ohci_device_isoc_done __P((usbd_xfer_handle));
-#endif
static usbd_status ohci_device_setintr __P((ohci_softc_t *sc,
struct ohci_pipe *pipe, int ival));
@@ -221,7 +231,10 @@ static u_int8_t revbits[OHCI_NO_INTRS] =
struct ohci_pipe {
struct usbd_pipe pipe;
ohci_soft_ed_t *sed;
- ohci_soft_td_t *tail;
+ union {
+ ohci_soft_td_t *td;
+ ohci_soft_itd_t *itd;
+ } tail;
/* Info needed for different pipe kinds. */
union {
/* Control pipe */
@@ -242,7 +255,7 @@ struct ohci_pipe {
} bulk;
/* Iso pipe */
struct iso {
- int xxxxx;
+ int next, inuse;
} iso;
} u;
};
@@ -254,6 +267,8 @@ static struct usbd_bus_methods ohci_bus_methods = {
ohci_poll,
ohci_allocm,
ohci_freem,
+ ohci_allocx,
+ ohci_freex,
};
static struct usbd_pipe_methods ohci_root_ctrl_methods = {
@@ -301,7 +316,6 @@ static struct usbd_pipe_methods ohci_device_bulk_methods = {
ohci_device_bulk_done,
};
-#if 0
static struct usbd_pipe_methods ohci_device_isoc_methods = {
ohci_device_isoc_transfer,
ohci_device_isoc_start,
@@ -310,7 +324,6 @@ static struct usbd_pipe_methods ohci_device_isoc_methods = {
ohci_noop,
ohci_device_isoc_done,
};
-#endif
#if defined(__NetBSD__) || defined(__OpenBSD__)
int
@@ -348,6 +361,9 @@ ohci_detach(sc, flags)
return (rv);
powerhook_disestablish(sc->sc_powerhook);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+#endif
/* free data structures XXX */
return (rv);
@@ -433,28 +449,32 @@ ohci_free_std(sc, std)
}
usbd_status
-ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
- struct ohci_pipe *upipe;
+ohci_alloc_std_chain(opipe, sc, len, rd, flags, dma, sp, ep)
+ struct ohci_pipe *opipe;
ohci_softc_t *sc;
- int len, rd, shortok;
+ int len, rd;
+ u_int16_t flags;
usb_dma_t *dma;
ohci_soft_td_t *sp, **ep;
{
ohci_soft_td_t *next, *cur;
ohci_physaddr_t dataphys, dataphysend;
- u_int32_t intr;
+ u_int32_t intr, tdflags;
int curlen;
DPRINTFN(len < 4096,("ohci_alloc_std_chain: start len=%d\n", len));
cur = sp;
dataphys = DMAADDR(dma);
dataphysend = OHCI_PAGE(dataphys + len - 1);
+ tdflags =
+ (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
+ OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY |
+ (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0);
+
for (;;) {
next = ohci_alloc_std(sc);
- if (next == 0) {
- /* XXX free chain */
- return (USBD_NOMEM);
- }
+ if (next == 0)
+ goto nomem;
/* The OHCI hardware can handle at most one page crossing. */
if (OHCI_PAGE(dataphys) == dataphysend ||
@@ -473,10 +493,7 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
len -= curlen;
intr = len == 0 ? OHCI_TD_SET_DI(1) : OHCI_TD_NOINTR;
- cur->td.td_flags = LE(
- (rd ? OHCI_TD_IN : OHCI_TD_OUT) | OHCI_TD_NOCC |
- intr | OHCI_TD_TOGGLE_CARRY |
- (shortok ? OHCI_TD_R : 0));
+ cur->td.td_flags = LE(tdflags | intr);
cur->td.td_cbp = LE(dataphys);
cur->nexttd = next;
cur->td.td_nexttd = LE(next->physaddr);
@@ -491,10 +508,31 @@ ohci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
dataphys += curlen;
cur = next;
}
+ if ((flags & USBD_FORCE_SHORT_XFER) &&
+ len % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
+ /* Force a 0 length transfer at the end. */
+ next = ohci_alloc_std(sc);
+ if (next == 0)
+ goto nomem;
+
+ cur->td.td_flags = LE(tdflags | OHCI_TD_SET_DI(1));
+ cur->td.td_cbp = 0; /* indicate 0 length packet */
+ cur->nexttd = next;
+ cur->td.td_nexttd = LE(next->physaddr);
+ cur->td.td_be = LE(dataphys - 1);
+ cur->len = 0;
+ cur->flags = 0;
+ cur = next;
+ DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+ }
cur->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
*ep = next;
return (USBD_NORMAL_COMPLETION);
+
+ nomem:
+ /* XXX free chain */
+ return (USBD_NOMEM);
}
#if 0
@@ -513,15 +551,53 @@ ohci_free_std_chain(sc, std, stdend)
}
#endif
+ohci_soft_itd_t *
+ohci_alloc_sitd(sc)
+ ohci_softc_t *sc;
+{
+ ohci_soft_itd_t *sitd;
+ usbd_status err;
+ int i, offs;
+ usb_dma_t dma;
+
+ if (sc->sc_freeitds == NULL) {
+ DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
+ err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK,
+ OHCI_TD_ALIGN, &dma);
+ if (err)
+ return (0);
+ for(i = 0; i < OHCI_STD_CHUNK; i++) {
+ offs = i * OHCI_STD_SIZE;
+ sitd = (ohci_soft_itd_t *)((char*)KERNADDR(&dma)+offs);
+ sitd->physaddr = DMAADDR(&dma) + offs;
+ sitd->nextitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd;
+ }
+ }
+ sitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd->nextitd;
+ memset(&sitd->itd, 0, sizeof(ohci_itd_t));
+ sitd->nextitd = 0;
+ return (sitd);
+}
+
+void
+ohci_free_sitd(sc, sitd)
+ ohci_softc_t *sc;
+ ohci_soft_itd_t *sitd;
+{
+ sitd->nextitd = sc->sc_freeitds;
+ sc->sc_freeitds = sitd;
+}
+
usbd_status
ohci_init(sc)
ohci_softc_t *sc;
{
ohci_soft_ed_t *sed, *psed;
usbd_status err;
- int rev;
int i;
- u_int32_t s, ctl, ival, hcr, fm, per;
+ u_int32_t s, ctl, ival, hcr, fm, per, rev;
DPRINTF(("ohci_init: start\n"));
#if defined(__OpenBSD__)
@@ -544,6 +620,8 @@ ohci_init(sc)
for (i = 0; i < OHCI_HASH_SIZE; i++)
LIST_INIT(&sc->sc_hash_tds[i]);
+ SIMPLEQ_INIT(&sc->sc_free_xfers);
+
/* Allocate the HCCA area. */
err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE,
OHCI_HCCA_ALIGN, &sc->sc_hccadma);
@@ -554,6 +632,7 @@ ohci_init(sc)
sc->sc_eintrs = OHCI_NORMAL_INTRS;
+ /* Allocate dummy ED that starts the control list. */
sc->sc_ctrl_head = ohci_alloc_sed(sc);
if (sc->sc_ctrl_head == NULL) {
err = USBD_NOMEM;
@@ -561,6 +640,7 @@ ohci_init(sc)
}
sc->sc_ctrl_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+ /* Allocate dummy ED that starts the bulk list. */
sc->sc_bulk_head = ohci_alloc_sed(sc);
if (sc->sc_bulk_head == NULL) {
err = USBD_NOMEM;
@@ -568,6 +648,14 @@ ohci_init(sc)
}
sc->sc_bulk_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+ /* Allocate dummy ED that starts the isochronous list. */
+ sc->sc_isoc_head = ohci_alloc_sed(sc);
+ if (sc->sc_isoc_head == NULL) {
+ err = USBD_NOMEM;
+ goto bad3;
+ }
+ sc->sc_isoc_head->ed.ed_flags |= LE(OHCI_ED_SKIP);
+
/* Allocate all the dummy EDs that make up the interrupt tree. */
for (i = 0; i < OHCI_NO_EDS; i++) {
sed = ohci_alloc_sed(sc);
@@ -575,16 +663,17 @@ ohci_init(sc)
while (--i >= 0)
ohci_free_sed(sc, sc->sc_eds[i]);
err = USBD_NOMEM;
- goto bad3;
+ goto bad4;
}
/* All ED fields are set to 0. */
sc->sc_eds[i] = sed;
sed->ed.ed_flags |= LE(OHCI_ED_SKIP);
- if (i != 0) {
+ if (i != 0)
psed = sc->sc_eds[(i-1) / 2];
- sed->next = psed;
- sed->ed.ed_nexted = LE(psed->physaddr);
- }
+ else
+ psed= sc->sc_isoc_head;
+ sed->next = psed;
+ sed->ed.ed_nexted = LE(psed->physaddr);
}
/*
* Fill HCCA interrupt table. The bit reversal is to get
@@ -647,14 +736,14 @@ ohci_init(sc)
if (hcr) {
printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
err = USBD_IOERROR;
- goto bad3;
+ goto bad5;
}
#ifdef OHCI_DEBUG
if (ohcidebug > 15)
ohci_dumpregs(sc);
#endif
- /* The controller is now in suspend state, we have 2ms to finish. */
+ /* The controller is now in SUSPEND state, we have 2ms to finish. */
/* Set up HC registers. */
OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma));
@@ -696,9 +785,16 @@ ohci_init(sc)
sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
sc->sc_powerhook = powerhook_establish(ohci_power, sc);
-
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
+#endif
return (USBD_NORMAL_COMPLETION);
+ bad5:
+ for (i = 0; i < OHCI_NO_EDS; i++)
+ ohci_free_sed(sc, sc->sc_eds[i]);
+ bad4:
+ ohci_free_sed(sc, sc->sc_isoc_head);
bad3:
ohci_free_sed(sc, sc->sc_ctrl_head);
bad2:
@@ -733,7 +829,54 @@ ohci_freem(bus, dma)
usb_freemem(&sc->sc_bus, dma);
}
-#if defined(__NetBSD__)
+usbd_xfer_handle
+ohci_allocx(bus)
+ struct usbd_bus *bus;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+ usbd_xfer_handle xfer;
+
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer != NULL)
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ else
+ xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ if (xfer != NULL)
+ memset(xfer, 0, sizeof *xfer);
+ return (xfer);
+}
+
+void
+ohci_freex(bus, xfer)
+ struct usbd_bus *bus;
+ usbd_xfer_handle xfer;
+{
+ struct ohci_softc *sc = (struct ohci_softc *)bus;
+
+ SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+/*
+ * Shut down the controller when the system is going down.
+ */
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+void
+ohci_shutdown(v)
+ void *v;
+{
+ ohci_softc_t *sc = v;
+
+ DPRINTF(("ohci_shutdown: stopping the HC\n"));
+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
+}
+
+/*
+ * Handle suspend/resume.
+ *
+ * We need to switch to polling mode here, because this routine is
+ * called from an intterupt context. This is all right since we
+ * are almost suspended anyway.
+ */
void
ohci_power(why, v)
int why;
@@ -747,7 +890,7 @@ ohci_power(why, v)
ohci_dumpregs(sc);
#endif
}
-#endif /* defined(__NetBSD__) */
+#endif
#ifdef OHCI_DEBUG
void
@@ -801,8 +944,9 @@ ohci_intr(p)
/* If we get an interrupt while polling, then just ignore it. */
if (sc->sc_bus.use_polling) {
- DPRINTF(("%s: Ignored interrupt while polling",
- USBDEVNAME(sc->sc_bus.bdev)));
+#ifdef DIAGNOSTIC
+ printf("ohci_intr: ignored interrupt while polling\n");
+#endif
return (0);
}
@@ -948,12 +1092,12 @@ ohci_process_done(sc, done)
#endif
for (std = sdone; std; std = stdnext) {
- stdnext = std->dnext;
xfer = std->xfer;
- usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
+ stdnext = std->dnext;
DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
std, xfer, xfer->hcpriv));
cc = OHCI_TD_GET_CC(LE(std->td.td_flags));
+ usb_untimeout(ohci_timeout, xfer, xfer->timo_handle);
if (xfer->status == USBD_CANCELLED ||
xfer->status == USBD_TIMEOUT) {
DPRINTF(("ohci_process_done: cancel/timeout %p\n",
@@ -1036,7 +1180,7 @@ ohci_device_intr_done(xfer)
xfer->hcpriv = NULL;
if (xfer->pipe->repeat) {
- data = opipe->tail;
+ data = opipe->tail.td;
tail = ohci_alloc_std(sc); /* XXX should reuse TD */
if (tail == NULL) {
xfer->status = USBD_NOMEM;
@@ -1061,7 +1205,7 @@ ohci_device_intr_done(xfer)
ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
}
}
@@ -1191,7 +1335,7 @@ ohci_device_request(xfer)
UGETW(req->wIndex), len, addr,
opipe->pipe.endpoint->edesc->bEndpointAddress));
- setup = opipe->tail;
+ setup = opipe->tail.td;
stat = ohci_alloc_std(sc);
if (stat == NULL) {
err = USBD_NOMEM;
@@ -1244,7 +1388,7 @@ ohci_device_request(xfer)
memcpy(KERNADDR(&opipe->u.ctl.reqdma), req, sizeof *req);
setup->td.td_flags = LE(OHCI_TD_SETUP | OHCI_TD_NOCC |
- OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
+ OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR);
setup->td.td_cbp = LE(DMAADDR(&opipe->u.ctl.reqdma));
setup->nexttd = next;
setup->td.td_nexttd = LE(next->physaddr);
@@ -1279,7 +1423,7 @@ ohci_device_request(xfer)
ohci_hash_add_td(sc, data);
ohci_hash_add_td(sc, stat);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
usb_timeout(ohci_timeout, xfer,
@@ -1289,6 +1433,7 @@ ohci_device_request(xfer)
#ifdef OHCI_DEBUG
if (ohcidebug > 5) {
+ usb_delay_ms(&sc->sc_bus, 5);
DPRINTF(("ohci_device_request: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dump_ed(sed);
@@ -1462,10 +1607,15 @@ ohci_open(pipe)
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
u_int8_t addr = dev->address;
+ u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
ohci_soft_ed_t *sed;
- ohci_soft_td_t *std;
+ ohci_soft_td_t *std = NULL;
+ ohci_soft_itd_t *sitd;
+ ohci_physaddr_t tdphys;
+ u_int32_t fmt;
usbd_status err;
int s;
+ int ival;
DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, addr, ed->bEndpointAddress, sc->sc_addr));
@@ -1484,22 +1634,35 @@ ohci_open(pipe)
sed = ohci_alloc_sed(sc);
if (sed == NULL)
goto bad0;
- std = ohci_alloc_std(sc);
- if (std == NULL)
- goto bad1;
opipe->sed = sed;
- opipe->tail = std;
+ if (xfertype == UE_ISOCHRONOUS) {
+ sitd = ohci_alloc_sitd(sc);
+ if (sitd == NULL) {
+ ohci_free_sitd(sc, sitd);
+ goto bad1;
+ }
+ opipe->tail.itd = sitd;
+ tdphys = LE(sitd->physaddr);
+ fmt = OHCI_ED_FORMAT_ISO;
+ } else {
+ std = ohci_alloc_std(sc);
+ if (std == NULL) {
+ ohci_free_std(sc, std);
+ goto bad1;
+ }
+ opipe->tail.td = std;
+ tdphys = LE(std->physaddr);
+ fmt = OHCI_ED_FORMAT_GEN;
+ }
sed->ed.ed_flags = LE(
OHCI_ED_SET_FA(addr) |
OHCI_ED_SET_EN(ed->bEndpointAddress) |
OHCI_ED_DIR_TD |
- (dev->lowspeed ? OHCI_ED_SPEED : 0) |
- ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ?
- OHCI_ED_FORMAT_ISO : OHCI_ED_FORMAT_GEN) |
+ (dev->lowspeed ? OHCI_ED_SPEED : 0) | fmt |
OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)));
- sed->ed.ed_headp = sed->ed.ed_tailp = LE(std->physaddr);
+ sed->ed.ed_headp = sed->ed.ed_tailp = tdphys;
- switch (ed->bmAttributes & UE_XFERTYPE) {
+ switch (xfertype) {
case UE_CONTROL:
pipe->methods = &ohci_device_ctrl_methods;
err = usb_allocmem(&sc->sc_bus,
@@ -1513,10 +1676,13 @@ ohci_open(pipe)
break;
case UE_INTERRUPT:
pipe->methods = &ohci_device_intr_methods;
- return (ohci_device_setintr(sc, opipe, ed->bInterval));
+ ival = pipe->interval;
+ if (ival == USBD_DEFAULT_INTERVAL)
+ ival = ed->bInterval;
+ return (ohci_device_setintr(sc, opipe, ival));
case UE_ISOCHRONOUS:
- printf("ohci_open: open iso unimplemented\n");
- return (USBD_INVAL);
+ pipe->methods = &ohci_device_isoc_methods;
+ return (ohci_setup_isoc(pipe));
case UE_BULK:
pipe->methods = &ohci_device_bulk_methods;
s = splusb();
@@ -1574,7 +1740,6 @@ ohci_close_pipe(pipe, head)
#endif
ohci_rem_ed(sed, head);
splx(s);
- ohci_free_std(sc, opipe->tail);
ohci_free_sed(sc, opipe->sed);
}
@@ -1606,6 +1771,7 @@ ohci_abort_xfer(xfer, status)
DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
sed->ed.ed_flags |= LE(OHCI_ED_SKIP); /* force hardware skip */
+#if 1
if (xfer->device->bus->intr_context) {
/* We have no process context, so we can't use tsleep(). */
timeout(ohci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
@@ -1617,6 +1783,10 @@ ohci_abort_xfer(xfer, status)
usb_delay_ms(opipe->pipe.device->bus, 1);
ohci_abort_xfer_end(xfer);
}
+#else
+ delay(1000);
+ ohci_abort_xfer_end(xfer);
+#endif
}
void
@@ -2181,10 +2351,12 @@ static void
ohci_device_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
ohci_close_pipe(pipe, sc->sc_ctrl_head);
+ ohci_free_std(sc, opipe->tail.td);
}
/************************/
@@ -2258,9 +2430,8 @@ ohci_device_bulk_start(xfer)
OHCI_ED_SET_FA(addr));
/* Allocate a chain of new TDs (including a new tail). */
- data = opipe->tail;
- err = ohci_alloc_std_chain(opipe, sc, len, isread,
- xfer->flags & USBD_SHORT_XFER_OK,
+ data = opipe->tail.td;
+ err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer->flags,
&xfer->dmabuf, data, &tail);
if (err)
return (err);
@@ -2287,7 +2458,7 @@ ohci_device_bulk_start(xfer)
ohci_hash_add_td(sc, tdp);
}
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
@@ -2326,10 +2497,12 @@ static void
ohci_device_bulk_close(pipe)
usbd_pipe_handle pipe;
{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
ohci_close_pipe(pipe, sc->sc_bulk_head);
+ ohci_free_std(sc, opipe->tail.td);
}
/************************/
@@ -2372,7 +2545,7 @@ ohci_device_intr_start(xfer)
len = xfer->length;
- data = opipe->tail;
+ data = opipe->tail.td;
tail = ohci_alloc_std(sc);
if (tail == NULL)
return (USBD_NOMEM);
@@ -2404,7 +2577,7 @@ ohci_device_intr_start(xfer)
s = splusb();
ohci_hash_add_td(sc, data);
sed->ed.ed_tailp = LE(tail->physaddr);
- opipe->tail = tail;
+ opipe->tail.td = tail;
sed->ed.ed_flags &= LE(~OHCI_ED_SKIP);
#if 0
@@ -2472,7 +2645,7 @@ ohci_device_intr_close(pipe)
for (j = 0; j < nslots; j++)
--sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
- ohci_free_std(sc, opipe->tail);
+ ohci_free_std(sc, opipe->tail.td);
ohci_free_sed(sc, opipe->sed);
}
@@ -2540,3 +2713,149 @@ ohci_device_setintr(sc, opipe, ival)
DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe));
return (USBD_NORMAL_COMPLETION);
}
+
+/***********************/
+
+usbd_status
+ohci_device_isoc_transfer(xfer)
+ usbd_xfer_handle xfer;
+{
+ usbd_status err;
+
+ DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
+
+ /* Put it on our queue, */
+ err = usb_insert_transfer(xfer);
+
+ /* bail out on error, */
+ if (err && err != USBD_IN_PROGRESS)
+ return (err);
+
+ /* XXX should check inuse here */
+
+ /* insert into schedule, */
+ ohci_device_isoc_enter(xfer);
+
+ /* and put on interrupt list if the pipe wasn't running */
+ if (!err)
+ ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+
+ return (err);
+}
+
+void
+ohci_device_isoc_enter(xfer)
+ usbd_xfer_handle xfer;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+ usbd_device_handle dev = opipe->pipe.device;
+ ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+ ohci_soft_ed_t *sed = opipe->sed;
+ struct iso *iso = &opipe->u.iso;
+ ohci_soft_itd_t *sitd, *nsitd;
+ ohci_physaddr_t buf, offs;
+ int i, ncur, nframes;
+ int ncross = 0;
+ int s;
+
+ s = splusb();
+ sitd = opipe->tail.itd;
+ buf = DMAADDR(&xfer->dmabuf);
+ sitd->itd.itd_bp0 = LE(buf & OHCI_ITD_PAGE_MASK);
+ nframes = xfer->nframes;
+ offs = buf & OHCI_ITD_OFFSET_MASK;
+ for (i = ncur = 0; i < nframes; i++, ncur++) {
+ if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */
+ ncross > 1) { /* too many page crossings */
+
+ nsitd = ohci_alloc_sitd(sc);
+ if (nsitd == NULL) {
+ /* XXX what now? */
+ return;
+ }
+ sitd->nextitd = nsitd;
+ sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+ sitd->itd.itd_flags = LE(
+ OHCI_ITD_NOCC |
+ OHCI_ITD_SET_SF(iso->next) |
+ OHCI_ITD_NOINTR |
+ OHCI_ITD_SET_FC(OHCI_ITD_NOFFSET));
+ sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+ nsitd->itd.itd_bp0 = LE((buf + offs) & OHCI_ITD_PAGE_MASK);
+ sitd = nsitd;
+ iso->next = iso->next + ncur;
+ ncur = 0;
+ ncross = 0;
+ }
+ /* XXX byte order */
+ sitd->itd.itd_offset[i] =
+ offs | (ncross == 1 ? OHCI_ITD_PAGE_SELECT : 0);
+ offs += xfer->frlengths[i];
+ /* XXX update ncross */
+ }
+ nsitd = ohci_alloc_sitd(sc);
+ if (nsitd == NULL) {
+ /* XXX what now? */
+ return;
+ }
+ sitd->nextitd = nsitd;
+ sitd->itd.itd_nextitd = LE(nsitd->physaddr);
+ sitd->itd.itd_flags = LE(
+ OHCI_ITD_NOCC |
+ OHCI_ITD_SET_SF(iso->next) |
+ OHCI_ITD_SET_DI(0) |
+ OHCI_ITD_SET_FC(ncur));
+ sitd->itd.itd_be = LE(LE(sitd->itd.itd_bp0) + offs - 1);
+ iso->next = iso->next + ncur;
+
+ opipe->tail.itd = nsitd;
+ sed->ed.ed_tailp = LE(nsitd->physaddr);
+ /* XXX update ED */
+ splx(s);
+}
+
+usbd_status
+ohci_device_isoc_start(xfer)
+ usbd_xfer_handle xfer;
+{
+ printf("ohci_device_isoc_start: not implemented\n");
+ return (USBD_INVAL);
+}
+
+void
+ohci_device_isoc_abort(xfer)
+ usbd_xfer_handle xfer;
+{
+}
+
+void
+ohci_device_isoc_done(xfer)
+ usbd_xfer_handle xfer;
+{
+ printf("ohci_device_isoc_done: not implemented\n");
+}
+
+usbd_status
+ohci_setup_isoc(pipe)
+ usbd_pipe_handle pipe;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+ struct iso *iso = &opipe->u.iso;
+
+ iso->next = -1;
+ iso->inuse = 0;
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+void
+ohci_device_isoc_close(pipe)
+ usbd_pipe_handle pipe;
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
+
+ DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
+ ohci_close_pipe(pipe, sc->sc_isoc_head);
+ ohci_free_sitd(sc, opipe->tail.itd);
+}
diff --git a/sys/dev/usb/ohcireg.h b/sys/dev/usb/ohcireg.h
index ba75709cafee..0939368f6eda 100644
--- a/sys/dev/usb/ohcireg.h
+++ b/sys/dev/usb/ohcireg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcireg.h,v 1.8 1999/08/22 23:41:00 augustss Exp $ */
+/* $NetBSD: ohcireg.h,v 1.11 2000/01/16 10:35:24 augustss Exp $ */
/* $FreeBSD$ */
@@ -195,6 +195,33 @@ typedef struct {
/* #define OHCI_TD_SIZE 16 */
#define OHCI_TD_ALIGN 16
+#define OHCI_ITD_NOFFSET 8
+typedef struct {
+ u_int32_t itd_flags;
+#define OHCI_ITD_GET_SF(x) ((x) & 0x0000ffff)
+#define OHCI_ITD_SET_SF(x) ((x) & 0xffff)
+#define OHCI_ITD_GET_DI(x) (((x) >> 21) & 7) /* Delay Interrupt */
+#define OHCI_ITD_SET_DI(x) ((x) << 21)
+#define OHCI_ITD_NOINTR 0x00e00000
+#define OHCI_ITD_GET_FC(x) ((((x) >> 24) & 7)+1) /* Frame Count */
+#define OHCI_ITD_SET_FC(x) (((x)-1) << 24)
+#define OHCI_ITD_GET_CC(x) ((x) >> 28) /* Condition Code */
+#define OHCI_ITD_NOCC 0xf0000000
+ ohci_physaddr_t itd_bp0; /* Buffer Page 0 */
+#define OHCI_ITD_OFFSET_MASK 0x00000fff
+#define OHCI_ITD_PAGE_MASK (~OHCI_ITD_OFFSET_MASK)
+ ohci_physaddr_t itd_nextitd; /* Next ITD */
+ ohci_physaddr_t itd_be; /* Buffer End */
+ u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */
+#define itd_pswn itd_offset /* Packet Status Word*/
+#define OHCI_ITD_PAGE_SELECT 0x00001000
+#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */
+#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */
+} ohci_itd_t;
+/* #define OHCI_ITD_SIZE 32 */
+#define OHCI_ITD_ALIGN 32
+
+
#define OHCI_CC_NO_ERROR 0
#define OHCI_CC_CRC 1
#define OHCI_CC_BIT_STUFFING 2
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index cd61ee6fd397..555e09be52b2 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcivar.h,v 1.13 1999/10/13 08:10:55 augustss Exp $ */
+/* $NetBSD: ohcivar.h,v 1.18 2000/01/18 20:11:00 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -61,6 +61,14 @@ typedef struct ohci_soft_td {
#define OHCI_STD_SIZE ((sizeof (struct ohci_soft_td) + OHCI_TD_ALIGN - 1) / OHCI_TD_ALIGN * OHCI_TD_ALIGN)
#define OHCI_STD_CHUNK 128
+typedef struct ohci_soft_itd {
+ ohci_itd_t itd;
+ struct ohci_soft_itd *nextitd; /* mirrors nexttd in ITD */
+ ohci_physaddr_t physaddr;
+} ohci_soft_itd_t;
+#define OHCI_SITD_SIZE ((sizeof (struct ohci_soft_itd) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN)
+#define OHCI_SITD_CHUNK 64
+
#define OHCI_NO_EDS (2*OHCI_NO_INTRS-1)
#define OHCI_HASH_SIZE 128
@@ -76,6 +84,7 @@ typedef struct ohci_softc {
u_int sc_bws[OHCI_NO_INTRS];
u_int32_t sc_eintrs;
+ ohci_soft_ed_t *sc_isoc_head;
ohci_soft_ed_t *sc_ctrl_head;
ohci_soft_ed_t *sc_bulk_head;
@@ -87,6 +96,9 @@ typedef struct ohci_softc {
ohci_soft_ed_t *sc_freeeds;
ohci_soft_td_t *sc_freetds;
+ ohci_soft_itd_t *sc_freeitds;
+
+ SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
usbd_xfer_handle sc_intrxfer;
@@ -94,6 +106,8 @@ typedef struct ohci_softc {
int sc_id_vendor;
void *sc_powerhook;
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+
device_ptr_t sc_child;
} ohci_softc_t;
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 2342a027ca3d..3c5520cc6cd7 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -333,7 +333,8 @@ ugenopen(dev, flag, mode, p)
err = usbd_open_pipe_intr(sce->iface,
edesc->bEndpointAddress,
USBD_SHORT_XFER_OK, &sce->pipeh, sce,
- sce->ibuf, isize, ugenintr);
+ sce->ibuf, isize, ugenintr,
+ USBD_DEFAULT_INTERVAL);
if (err) {
free(sce->ibuf, M_USBDEV);
clfree(&sce->q);
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 9601da2d080a..3e907d8cd5ad 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uhci.c,v 1.67 1999/11/18 23:32:28 augustss Exp $ */
+/* $NetBSD: uhci.c,v 1.80 2000/01/19 01:16:38 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -42,10 +42,10 @@
* USB Universal Host Controller driver.
* Handles e.g. PIIX3 and PIIX4.
*
- * Data sheets: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
- * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
* UHCI spec: http://www.intel.com/design/usb/uhci11d.pdf
* USB spec: http://www.usb.org/developers/data/usb11.pdf
+ * PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
+ * ftp://download.intel.com/design/intarch/datashts/29056201.pdf
*/
#include <sys/param.h>
@@ -151,6 +151,7 @@ LIST_HEAD(, uhci_intr_info) uhci_ii_free;
static void uhci_busreset __P((uhci_softc_t *));
#if defined(__NetBSD__) || defined(__OpenBSD__)
+static void uhci_shutdown __P((void *v));
static void uhci_power __P((int, void *));
#endif
static usbd_status uhci_run __P((uhci_softc_t *, int run));
@@ -169,7 +170,7 @@ static void uhci_exit_ctl_q __P((uhci_softc_t *, uhci_soft_qh_t *));
static void uhci_free_std_chain __P((uhci_softc_t *,
uhci_soft_td_t *, uhci_soft_td_t *));
static usbd_status uhci_alloc_std_chain __P((struct uhci_pipe *,
- uhci_softc_t *, int, int, int, usb_dma_t *,
+ uhci_softc_t *, int, int, u_int16_t, usb_dma_t *,
uhci_soft_td_t **, uhci_soft_td_t **));
static void uhci_timo __P((void *));
static void uhci_waitintr __P((uhci_softc_t *,
@@ -196,6 +197,9 @@ static usbd_status uhci_allocm __P((struct usbd_bus *, usb_dma_t *,
u_int32_t));
static void uhci_freem __P((struct usbd_bus *, usb_dma_t *));
+static usbd_xfer_handle uhci_allocx __P((struct usbd_bus *));
+static void uhci_freex __P((struct usbd_bus *, usbd_xfer_handle));
+
static usbd_status uhci_device_ctrl_transfer __P((usbd_xfer_handle));
static usbd_status uhci_device_ctrl_start __P((usbd_xfer_handle));
static void uhci_device_ctrl_abort __P((usbd_xfer_handle));
@@ -274,6 +278,8 @@ struct usbd_bus_methods uhci_bus_methods = {
uhci_poll,
uhci_allocm,
uhci_freem,
+ uhci_allocx,
+ uhci_freex,
};
struct usbd_pipe_methods uhci_root_ctrl_methods = {
@@ -418,17 +424,23 @@ uhci_init(sc)
LIST_INIT(&sc->sc_intrhead);
+ SIMPLEQ_INIT(&sc->sc_free_xfers);
+
/* Set up the bus struct. */
sc->sc_bus.methods = &uhci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct uhci_pipe);
sc->sc_suspend = PWR_RESUME;
sc->sc_powerhook = powerhook_establish(uhci_power, sc);
-
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sc->sc_shutdownhook = shutdownhook_establish(uhci_shutdown, sc);
+#endif
DPRINTFN(1,("uhci_init: enabling\n"));
UWRITE2(sc, UHCI_INTR, UHCI_INTR_TOCRCIE | UHCI_INTR_RIE |
UHCI_INTR_IOCE | UHCI_INTR_SPIE); /* enable interrupts */
+ UHCICMD(sc, UHCI_CMD_MAXP); /* Assume 64 byte packets at frame end */
+
return (uhci_run(sc, 1)); /* and here we go... */
}
@@ -459,6 +471,7 @@ uhci_detach(sc, flags)
struct uhci_softc *sc;
int flags;
{
+ usbd_xfer_handle xfer;
int rv = 0;
if (sc->sc_child != NULL)
@@ -468,7 +481,18 @@ uhci_detach(sc, flags)
return (rv);
powerhook_disestablish(sc->sc_powerhook);
- /* free data structures XXX */
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+
+ /* Free all xfers associated with this HC. */
+ for (;;) {
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer == NULL)
+ break;
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ free(xfer, M_USB);
+ }
+
+ /* XXX free other data structures XXX */
return (rv);
}
@@ -492,7 +516,47 @@ uhci_freem(bus, dma)
usb_freemem(&((struct uhci_softc *)bus)->sc_bus, dma);
}
-#if defined(__NetBSD__)
+usbd_xfer_handle
+uhci_allocx(bus)
+ struct usbd_bus *bus;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)bus;
+ usbd_xfer_handle xfer;
+
+ xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
+ if (xfer != NULL)
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, xfer, next);
+ else
+ xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ if (xfer != NULL)
+ memset(xfer, 0, sizeof *xfer);
+ return (xfer);
+}
+
+void
+uhci_freex(bus, xfer)
+ struct usbd_bus *bus;
+ usbd_xfer_handle xfer;
+{
+ struct uhci_softc *sc = (struct uhci_softc *)bus;
+
+ SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
+}
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+/*
+ * Shut down the controller when the system is going down.
+ */
+void
+uhci_shutdown(v)
+ void *v;
+{
+ uhci_softc_t *sc = v;
+
+ DPRINTF(("uhci_shutdown: stopping the HC\n"));
+ uhci_run(sc, 0); /* stop the controller */
+}
+
/*
* Handle suspend/resume.
*
@@ -520,7 +584,7 @@ uhci_power(why, v)
if (uhcidebug > 2)
uhci_dumpregs(sc);
#endif
- if (sc->sc_has_timo)
+ if (sc->sc_has_timo != NULL)
usb_untimeout(uhci_timo, sc->sc_has_timo,
sc->sc_has_timo->timo_handle);
sc->sc_bus.use_polling++;
@@ -552,7 +616,7 @@ uhci_power(why, v)
uhci_run(sc, 1); /* and start traffic again */
usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
sc->sc_bus.use_polling--;
- if (sc->sc_has_timo)
+ if (sc->sc_has_timo != NULL)
usb_timeout(uhci_timo, sc->sc_has_timo,
sc->sc_ival, sc->sc_has_timo->timo_handle);
#ifdef UHCI_DEBUG
@@ -729,14 +793,13 @@ uhci_root_intr_done(xfer)
{
}
-
void
uhci_lock_frames(sc)
uhci_softc_t *sc;
{
int s = splusb();
- while (sc->sc_vflock) {
+ while (sc->sc_vflock & UHCI_HAS_LOCK) {
sc->sc_vflock |= UHCI_WANT_LOCK;
tsleep(&sc->sc_vflock, PRIBIO, "uhcqhl", 0);
}
@@ -1107,7 +1170,7 @@ uhci_idone(ii)
actlen, status));
xfer->actlen = actlen;
if (status != 0) {
- DPRINTFN((status&UHCI_TD_STALLED)*10,
+ DPRINTFN((status == UHCI_TD_STALLED)*10,
("uhci_idone: error, addr=%d, endpt=0x%02x, "
"status 0x%b\n",
xfer->pipe->device->address,
@@ -1222,17 +1285,17 @@ uhci_run(sc, run)
int run;
{
int s, n, running;
+ u_int16_t cmd;
run = run != 0;
s = splusb();
DPRINTF(("uhci_run: setting run=%d\n", run));
- /*
- * When activating the controller, set the MAXP bit.
- * Certain high speed devices such as network adapters
- * require this in order to avoid babble errors that
- * can cause an endpoint stall.
- */
- UHCICMD(sc, run ? UHCI_CMD_RS|UHCI_CMD_MAXP : 0);
+ cmd = UREAD2(sc, UHCI_CMD);
+ if (run)
+ cmd |= UHCI_CMD_RS;
+ else
+ cmd &= ~UHCI_CMD_RS;
+ UHCICMD(sc, cmd);
for(n = 0; n < 10; n++) {
running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
/* return when we've entered the state we want */
@@ -1375,10 +1438,11 @@ uhci_free_std_chain(sc, std, stdend)
}
usbd_status
-uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
+uhci_alloc_std_chain(upipe, sc, len, rd, flags, dma, sp, ep)
struct uhci_pipe *upipe;
uhci_softc_t *sc;
- int len, rd, shortok;
+ int len, rd;
+ u_int16_t flags;
usb_dma_t *dma;
uhci_soft_td_t **sp, **ep;
{
@@ -1390,20 +1454,22 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
DPRINTFN(8, ("uhci_alloc_std_chain: addr=%d endpt=%d len=%d ls=%d "
- "shortok=%d\n", addr, UE_GET_ADDR(endpt), len,
- upipe->pipe.device->lowspeed, shortok));
- if (len == 0) {
- *sp = *ep = 0;
- DPRINTFN(-1,("uhci_alloc_std_chain: len=0\n"));
- return (USBD_NORMAL_COMPLETION);
- }
+ "flags=0x%x\n", addr, UE_GET_ADDR(endpt), len,
+ upipe->pipe.device->lowspeed, flags));
maxp = UGETW(upipe->pipe.endpoint->edesc->wMaxPacketSize);
if (maxp == 0) {
printf("uhci_alloc_std_chain: maxp=0\n");
return (USBD_INVAL);
}
ntd = (len + maxp - 1) / maxp;
+ if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
+ ntd++;
DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
+ if (ntd == 0) {
+ *sp = *ep = 0;
+ DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
+ return (USBD_NORMAL_COMPLETION);
+ }
tog = upipe->nexttoggle;
if (ntd % 2 == 0)
tog ^= 1;
@@ -1414,7 +1480,7 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
if (upipe->pipe.device->lowspeed)
status |= UHCI_TD_LS;
- if (shortok)
+ if (flags & USBD_SHORT_XFER_OK)
status |= UHCI_TD_SPD;
for (i = ntd; i >= 0; i--) {
p = uhci_alloc_std(sc);
@@ -1433,7 +1499,8 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
if (i == ntd) {
/* last TD */
l = len % maxp;
- if (l == 0) l = maxp;
+ if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER))
+ l = maxp;
*ep = p;
} else
l = maxp;
@@ -1510,9 +1577,8 @@ uhci_device_bulk_start(xfer)
upipe->u.bulk.isread = isread;
upipe->u.bulk.length = len;
- err = uhci_alloc_std_chain(upipe, sc, len, isread,
- xfer->flags & USBD_SHORT_XFER_OK,
- &xfer->dmabuf, &data, &dataend);
+ err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
if (err)
return (err);
dataend->td.td_status |= LE(UHCI_TD_IOC);
@@ -1532,6 +1598,9 @@ uhci_device_bulk_start(xfer)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_bulk_transfer: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -1594,7 +1663,8 @@ uhci_abort_xfer(xfer, status)
xfer->hcpriv = ii;
- /* make sure hardware has completed, */
+#if 1
+ /* Make sure hardware has completed. */
if (xfer->device->bus->intr_context) {
/* We have no process context, so we can't use tsleep(). */
timeout(uhci_abort_xfer_end, xfer, hz / USB_FRAMES_PER_SECOND);
@@ -1607,6 +1677,10 @@ uhci_abort_xfer(xfer, status)
/* and call final part of interrupt handler. */
uhci_abort_xfer_end(xfer);
}
+#else
+ delay(1000);
+ uhci_abort_xfer_end(xfer);
+#endif
}
void
@@ -1711,9 +1785,8 @@ uhci_device_intr_start(xfer)
panic("uhci_device_intr_transfer: a request\n");
#endif
- err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1,
- xfer->flags & USBD_SHORT_XFER_OK,
- &xfer->dmabuf, &data, &dataend);
+ err = uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
if (err)
return (err);
dataend->td.td_status |= LE(UHCI_TD_IOC);
@@ -1735,6 +1808,9 @@ uhci_device_intr_start(xfer)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_intr_transfer: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -1864,14 +1940,13 @@ uhci_device_request(xfer)
/* Set up data transaction */
if (len != 0) {
upipe->nexttoggle = 1;
- err = uhci_alloc_std_chain(upipe, sc, len, isread,
- xfer->flags & USBD_SHORT_XFER_OK,
- &xfer->dmabuf, &data, &dataend);
+ err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
+ &xfer->dmabuf, &data, &dataend);
if (err)
return (err);
next = data;
dataend->link.std = stat;
- dataend->td.td_link = LE(stat->physaddr|UHCI_PTR_VF);
+ dataend->td.td_link = LE(stat->physaddr | UHCI_PTR_VF);
} else {
next = stat;
}
@@ -1880,7 +1955,7 @@ uhci_device_request(xfer)
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
setup->link.std = next;
- setup->td.td_link = LE(next->physaddr|UHCI_PTR_VF);
+ setup->td.td_link = LE(next->physaddr | UHCI_PTR_VF);
setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
@@ -1909,6 +1984,9 @@ uhci_device_request(xfer)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_request: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
@@ -2080,6 +2158,9 @@ uhci_device_isoc_start(xfer)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_isoc_start: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
@@ -2265,8 +2346,7 @@ uhci_device_intr_done(xfer)
uhci_soft_td_t *data, *dataend;
/* This alloc cannot fail since we freed the chain above. */
- uhci_alloc_std_chain(upipe, sc, xfer->length, 1,
- xfer->flags & USBD_SHORT_XFER_OK,
+ uhci_alloc_std_chain(upipe, sc, xfer->length, 1, xfer->flags,
&xfer->dmabuf, &data, &dataend);
dataend->td.td_status |= LE(UHCI_TD_IOC);
@@ -2284,6 +2364,9 @@ uhci_device_intr_done(xfer)
callout_handle_init(&ii->timeout_handle);
#endif
#ifdef DIAGNOSTIC
+ if (!ii->isdone) {
+ printf("uhci_device_intr_done: not done, ii=%p\n", ii);
+ }
ii->isdone = 0;
#endif
for (i = 0; i < npoll; i++) {
@@ -2460,6 +2543,7 @@ uhci_open(pipe)
struct uhci_pipe *upipe = (struct uhci_pipe *)pipe;
usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
usbd_status err;
+ int ival;
DPRINTFN(1, ("uhci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, pipe->device->address,
@@ -2508,7 +2592,10 @@ uhci_open(pipe)
break;
case UE_INTERRUPT:
pipe->methods = &uhci_device_intr_methods;
- return (uhci_device_setintr(sc, upipe, ed->bInterval));
+ ival = pipe->interval;
+ if (ival == USBD_DEFAULT_INTERVAL)
+ ival = ed->bInterval;
+ return (uhci_device_setintr(sc, upipe, ival));
case UE_ISOCHRONOUS:
pipe->methods = &uhci_device_isoc_methods;
return (uhci_setup_isoc(pipe));
@@ -2961,7 +3048,7 @@ void
uhci_root_ctrl_abort(xfer)
usbd_xfer_handle xfer;
{
- /* Nothing to do, all transfers are syncronous. */
+ /* Nothing to do, all transfers are synchronous. */
}
/* Close the root pipe. */
@@ -2969,9 +3056,6 @@ void
uhci_root_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
- uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
-
- sc->sc_has_timo = 0;
DPRINTF(("uhci_root_ctrl_close\n"));
}
@@ -2983,7 +3067,7 @@ uhci_root_intr_abort(xfer)
uhci_softc_t *sc = (uhci_softc_t *)xfer->pipe->device->bus;
usb_untimeout(uhci_timo, xfer, xfer->timo_handle);
- sc->sc_has_timo = 0;
+ sc->sc_has_timo = NULL;
if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("uhci_root_intr_abort: remove\n"));
@@ -3035,6 +3119,6 @@ uhci_root_intr_close(pipe)
uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
usb_untimeout(uhci_timo, pipe->intrxfer, pipe->intrxfer->timo_handle);
- sc->sc_has_timo = 0;
+ sc->sc_has_timo = NULL;
DPRINTF(("uhci_root_intr_close\n"));
}
diff --git a/sys/dev/usb/uhcireg.h b/sys/dev/usb/uhcireg.h
index 59f1afe00222..2e5dffb6ad72 100644
--- a/sys/dev/usb/uhcireg.h
+++ b/sys/dev/usb/uhcireg.h
@@ -1,5 +1,5 @@
-/* $NetBSD: uhcireg.h,v 1.8 1999/11/18 23:32:28 augustss Exp $ */
-/* $FreeBSD$ */
+/* $NetBSD: uhcireg.h,v 1.9 1999/11/20 00:57:09 augustss Exp $ */
+/* $FreeBSD$ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index 682a4958452d..82e4c1ea2346 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: uhcivar.h,v 1.16 1999/10/13 08:10:56 augustss Exp $ */
+/* $NetBSD: uhcivar.h,v 1.21 2000/01/18 20:11:01 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -92,7 +92,7 @@ struct uhci_soft_td {
};
/*
* Make the size such that it is a multiple of UHCI_TD_ALIGN. This way
- * we can pack a number of soft TD together and have the real TS well
+ * we can pack a number of soft TD together and have the real TD well
* aligned.
* NOTE: Minimum size is 32 bytes.
*/
@@ -116,7 +116,7 @@ struct uhci_soft_qh {
#define UHCI_SQH_CHUNK 128 /*(PAGE_SIZE / UHCI_QH_SIZE)*/
/*
- * Information about an entry in the virtial frame list.
+ * Information about an entry in the virtual frame list.
*/
struct uhci_vframe {
uhci_soft_td_t *htd; /* pointer to dummy TD */
@@ -140,31 +140,34 @@ typedef struct uhci_softc {
uhci_soft_qh_t *sc_bulk_start; /* dummy QH for bulk */
uhci_soft_qh_t *sc_bulk_end; /* last bulk transfer */
- uhci_soft_td_t *sc_freetds;
- uhci_soft_qh_t *sc_freeqhs;
+ uhci_soft_td_t *sc_freetds; /* TD free list */
+ uhci_soft_qh_t *sc_freeqhs; /* QH free list */
+
+ SIMPLEQ_HEAD(, usbd_xfer) sc_free_xfers; /* free xfers */
u_int8_t sc_addr; /* device address */
u_int8_t sc_conf; /* device configuration */
char sc_isreset;
-
char sc_suspend;
- usbd_xfer_handle sc_has_timo;
LIST_HEAD(, uhci_intr_info) sc_intrhead;
/* Info for the root hub interrupt channel. */
- int sc_ival;
+ int sc_ival; /* time between root hug intrs */
+ usbd_xfer_handle sc_has_timo; /* root hub interrupt transfer */
- char sc_vflock;
+ char sc_vflock; /* for lock virtual frame list */
#define UHCI_HAS_LOCK 1
#define UHCI_WANT_LOCK 2
- char sc_vendor[16];
- int sc_id_vendor;
+ char sc_vendor[16]; /* vendor string for root hub */
+ int sc_id_vendor; /* vendor ID for root hub */
+
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
- void *sc_powerhook;
- device_ptr_t sc_child;
+ device_ptr_t sc_child; /* /dev/usb device */
} uhci_softc_t;
usbd_status uhci_init __P((uhci_softc_t *));
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 51a4e95f679d..a785b2d6b179 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -382,7 +382,7 @@ uhidopen(dev, flag, mode, p)
/* Set up interrupt pipe. */
err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc, sc->sc_ibuf,
- sc->sc_isize, uhid_intr);
+ sc->sc_isize, uhid_intr, USBD_DEFAULT_INTERVAL);
if (err) {
DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
"error=%d\n",err));
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index f8d9c2acd4cb..a0087de3daed 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -237,7 +237,7 @@ USB_ATTACH(uhub)
err = usbd_open_pipe_intr(iface, ed->bEndpointAddress,
USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status,
- sizeof(sc->sc_status), uhub_intr);
+ sizeof(sc->sc_status), uhub_intr, USBD_DEFAULT_INTERVAL);
if (err) {
printf("%s: cannot open interrupt pipe\n",
USBDEVNAME(sc->sc_dev));
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 1bda564d4074..18523b181bdc 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -592,7 +592,8 @@ ukbd_enable_intr(keyboard_t *kbd, int on, usbd_intr_t *func)
USBD_SHORT_XFER_OK,
&state->ks_intrpipe, kbd,
&state->ks_ndata,
- sizeof(state->ks_ndata), func);
+ sizeof(state->ks_ndata), func,
+ USBD_DEFAULT_INTERVAL);
if (err)
return (EIO);
} else {
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index f48f6a12cc78..3eed7aa2fe12 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -553,7 +553,8 @@ ums_enable(v)
/* Set up interrupt pipe. */
err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
USBD_SHORT_XFER_OK, &sc->sc_intrpipe, sc,
- sc->sc_ibuf, sc->sc_isize, ums_intr);
+ sc->sc_ibuf, sc->sc_isize, ums_intr,
+ USBD_DEFAULT_INTERVAL);
if (err) {
DPRINTF(("ums_enable: usbd_open_pipe_intr failed, error=%d\n",
err));
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index c42e4e8c0f01..f99d3c3064e3 100644
--- a/sys/dev/usb/usb_quirks.c
+++ b/sys/dev/usb/usb_quirks.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_quirks.c,v 1.18 1999/11/16 12:08:38 augustss Exp $ */
+/* $NetBSD: usb_quirks.c,v 1.21 2000/01/17 01:43:31 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -60,43 +60,11 @@ static struct usbd_quirk_entry {
{ USB_VENDOR_INSIDEOUT,USB_PRODUCT_INSIDEOUT_EDGEPORT4,
0x094, { UQ_SWAP_UNICODE}},
{ USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }},
- { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_USB_T, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
- { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C, 0x002, { UQ_NO_STRINGS|
- UQ_NO_TSLEEP }},
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT, 0x002, { UQ_NO_STRINGS }},
{ USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1, 0x101, { UQ_NO_STRINGS }},
{ USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48, 0x110, { UQ_MS_REVZ }},
{ USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }},
{ USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, { UQ_SPUR_BUT_UP }},
- { USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUS, 0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB100,
- 0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX, 0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX, 0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX_PNA,0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_SMC, USB_PRODUCT_SMC_2202USB, 0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100TX,0x101, { UQ_NO_TSLEEP }},
- { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE, 0x220, { UQ_NO_TSLEEP }},
- { USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2, 0x220, { UQ_NO_TSLEEP }},
{ 0, 0, 0, { 0 } }
};
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 46c2e8b0ac99..5ac7b95691a4 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_subr.c,v 1.56 1999/11/18 23:32:32 augustss Exp $ */
+/* $NetBSD: usb_subr.c,v 1.63 2000/01/19 00:23:58 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -344,7 +344,7 @@ usbd_reset_port(dev, port, ps)
err = usbd_get_port_status(dev, port, ps);
if (err) {
DPRINTF(("usbd_reset_port: get status failed %d\n",
- err));
+ err));
return (err);
}
} while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
@@ -356,7 +356,7 @@ usbd_reset_port(dev, port, ps)
#ifdef USB_DEBUG
if (err)
DPRINTF(("usbd_reset_port: clear port feature failed %d\n",
- err));
+ err));
#endif
/* Wait for the device to recover from reset. */
@@ -395,7 +395,7 @@ usbd_find_idesc(cd, ifaceidx, altidx)
return (d);
}
}
- return (0);
+ return (NULL);
}
usb_endpoint_descriptor_t *
@@ -413,9 +413,9 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
d = usbd_find_idesc(cd, ifaceidx, altidx);
if (d == NULL)
- return (0);
+ return (NULL);
if (endptidx >= d->bNumEndpoints) /* quick exit */
- return (0);
+ return (NULL);
curidx = -1;
for (p = (char *)d + d->bLength; p < end; ) {
@@ -424,14 +424,14 @@ usbd_find_edesc(cd, ifaceidx, altidx, endptidx)
break;
p += e->bLength;
if (p <= end && e->bDescriptorType == UDESC_INTERFACE)
- return (0);
+ return (NULL);
if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) {
curidx++;
if (curidx == endptidx)
return (e);
}
}
- return (0);
+ return (NULL);
}
usbd_status
@@ -453,15 +453,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
ifc->index = ifaceidx;
ifc->altindex = altidx;
nendpt = ifc->idesc->bNumEndpoints;
- DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt));
+ DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
if (nendpt != 0) {
ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
M_USB, M_NOWAIT);
- if (ifc->endpoints == 0)
+ if (ifc->endpoints == NULL)
return (USBD_NOMEM);
} else
- ifc->endpoints = 0;
- ifc->priv = 0;
+ ifc->endpoints = NULL;
+ ifc->priv = NULL;
p = (char *)ifc->idesc + ifc->idesc->bLength;
end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
#define ed ((usb_endpoint_descriptor_t *)p)
@@ -475,11 +475,15 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
if (p + ed->bLength <= end && ed->bLength != 0 &&
ed->bDescriptorType == UDESC_ENDPOINT)
goto found;
- if (ed->bDescriptorType == UDESC_INTERFACE ||
- ed->bLength == 0)
+ if (ed->bLength == 0 ||
+ ed->bDescriptorType == UDESC_INTERFACE)
break;
}
/* passed end, or bad desc */
+ DPRINTF(("usbd_fill_iface_data: bad descriptor(s): %s\n",
+ ed->bLength == 0 ? "0 length" :
+ ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
+ "out of data"));
goto bad;
found:
ifc->endpoints[endpt].edesc = ed;
@@ -491,7 +495,8 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
return (USBD_NORMAL_COMPLETION);
bad:
- free(ifc->endpoints, M_USB);
+ if (ifc->endpoints != NULL)
+ free(ifc->endpoints, M_USB);
return (USBD_INVAL);
}
@@ -640,7 +645,7 @@ usbd_set_config_index(dev, index, msg)
nifc = cdp->bNumInterface;
dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
M_USB, M_NOWAIT);
- if (dev->ifaces == 0) {
+ if (dev->ifaces == NULL) {
err = USBD_NOMEM;
goto bad;
}
@@ -666,10 +671,11 @@ usbd_set_config_index(dev, index, msg)
/* XXX add function for alternate settings */
usbd_status
-usbd_setup_pipe(dev, iface, ep, pipe)
+usbd_setup_pipe(dev, iface, ep, ival, pipe)
usbd_device_handle dev;
usbd_interface_handle iface;
struct usbd_endpoint *ep;
+ int ival;
usbd_pipe_handle *pipe;
{
usbd_pipe_handle p;
@@ -688,6 +694,7 @@ usbd_setup_pipe(dev, iface, ep, pipe)
p->intrxfer = 0;
p->running = 0;
p->repeat = 0;
+ p->interval = ival;
SIMPLEQ_INIT(&p->queue);
err = dev->bus->methods->open_pipe(p);
if (err) {
@@ -769,6 +776,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
uaa.release = UGETW(dd->bcdDevice);
/* First try with device specific drivers. */
+ DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
if (dv) {
dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
@@ -781,6 +789,8 @@ usbd_probe_and_attach(parent, dev, port, addr)
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
+ DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
+ dd->bNumConfigurations));
/* Next try with interface drivers. */
for (confi = 0; confi < dd->bNumConfigurations; confi++) {
DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
@@ -829,7 +839,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
ifaces[i] = 0; /* consumed */
#if defined(__FreeBSD__)
- /* create another device for the next iface */
+ /* create another child for the next iface */
bdev = device_add_child(parent, NULL, -1);
device_set_ivars(bdev, &uaa);
if (!bdev) {
@@ -947,7 +957,8 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
dev->cookie.cookie = ++usb_cookie_no;
/* Establish the the default pipe. */
- err = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
+ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+ &dev->default_pipe);
if (err) {
usbd_remove_device(dev, up);
return (err);
@@ -992,8 +1003,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
- /* Get the full device descriptor. */
- err = usbd_get_device_desc(dev, dd);
+ err = usbd_reload_device_desc(dev);
if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
"failed\n", addr));
@@ -1001,13 +1011,11 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
return (err);
}
- /* Figure out what's wrong with this device. */
- dev->quirks = usbd_find_quirk(dd);
-
/* Set the address */
err = usbd_set_address(dev, addr);
+ DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
if (err) {
- DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
+ DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
err = USBD_SET_ADDR_FAILED;
usbd_remove_device(dev, up);
return (err);
@@ -1035,6 +1043,23 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
return (USBD_NORMAL_COMPLETION);
}
+usbd_status
+usbd_reload_device_desc(dev)
+ usbd_device_handle dev;
+{
+ usbd_status err;
+
+ /* Get the full device descriptor. */
+ err = usbd_get_device_desc(dev, &dev->ddesc);
+ if (err)
+ return (err);
+
+ /* Figure out what's wrong with this device. */
+ dev->quirks = usbd_find_quirk(&dev->ddesc);
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
void
usbd_remove_device(dev, up)
usbd_device_handle dev;
@@ -1277,6 +1302,7 @@ usb_disconnect_port(up, parent)
}
}
+ /*usbd_add_event(USB_EVENT_DETACH, dev);*/
dev->bus->devices[dev->address] = NULL;
up->device = NULL;
usb_free_device(dev);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index b7a6a4c61445..d7df50be3356 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -52,7 +52,7 @@ vendor SUN 0x0430 Sun Microsystems
vendor LEXMARK 0x043d Lexmark International Inc.
vendor NANAO 0x0440 NANAO Corp.
vendor THRUST 0x044f Thrustmaster
-vendor TI 0x0451 Texas Instruments
+vendor TI 0x0451 Texas Instruments
vendor KYE 0x0458 KYE Systems Corp.
vendor MICROSOFT 0x045e Microsoft
vendor PRIMAX 0x0461 Primax Electronics
@@ -100,22 +100,26 @@ vendor QTRONIX 0x05c7 Qtronix Corp
vendor ELSA 0x05cc ELSA Gmbh
vendor EIZONANAO 0x05e7 EIZO Nanao
vendor KLSI 0x05e9 Kawasaki LSI
-vendor PIENGINEERING 0x05f3 P.I. Engineering
+vendor PIENGINEERING 0x05f3 P.I. Engineering
vendor CHIC 0x05fe Chic Technology
+vendor SOLIDYEAR 0x060b Solid Year
vendor MACALLY 0x0618 Macally
-vendor LINKSYS 0x066B LinkSys
+vendor LINKSYS 0x066b Linksys Inc.
vendor MULTITECH 0x06e0 MultiTech
vendor ADS 0x06e1 ADS Technologies
+vendor SIRIUS 0x06ea Sirius Technologies
vendor SMC 0x0707 Standard Microsystems Corp
vendor MIDIMAN 0x0763 Midiman
vendor SANDISK 0x0781 SanDisk Corp
vendor ADMTEK 0x07a6 ADMtek Inc.
vendor COREGA 0x07aa Corega
vendor SIIG 0x07cc SIIG
+vendor ZOOM 0x0803 Zoom Telephonics Inc.
vendor HANDSPRING 0x082d Handspring Inc.
-vendor ACTIVEWIRE 0x0854 ActiveWire Inc.
+vendor DIAMOND 0x0841 Diamond
vendor NETGEAR 0x0846 BayNETGEAR Inc.
-vendor BILLIONTON 0x08DD Billionton Systems
+vendor ACTIVEWIRE 0x0854 ActiveWire Inc.
+vendor BILLIONTON 0x08dd Billionton Systems Inc.
vendor MOTOROLA 0x1063 Motorola
vendor PLX 0x10b5 PLX
vendor INSIDEOUT 0x1608 Inside Out Networks
@@ -127,187 +131,176 @@ vendor INTEL 0x8086 Intel
* List of known products. Grouped by vendor.
*/
-/* AOX Inc. products */
-product AOX USB101 0x0008 USB ethernet controller engine
+/* 3Com products */
+product 3COM HOMECONN 0x009d HomeConnect USB Camera
+product 3COM 3C19250 0x03E8 3C19250 Ethernet adapter
+product 3COM USR56K 0x3021 U.S.Robotics 56000 Voice Faxmodem Pro
-/* HP products */
-product HP 4100C 0x0101 Scanjet 4100C
-product HP 6300C 0x0601 Scanjet 6300C
+product 3COMUSR USR56K 0x3021 U.S.Robotics 56000 Voice Faxmodem Pro
-/* NEC products */
-product NEC HUB 0x55aa hub
-product NEC HUB_B 0x55ab hub
+/* Acer products */
+product ACER ACERSCAN_C310U 0x12a6 Acerscan C310U
-/* Kodak products */
-product KODAK DC260 0x0110 Digital Science DC260
-product KODAK DC240 0x0120 Digital Science DC240
-product KODAK DC280 0x0130 Digital Science DC280
+/* ActiveWire Inc. products */
+product ACTIVEWIRE IOBOARD 0x0100 I/O Board
+product ACTIVEWIRE IOBOARD_FW1 0x0101 I/O Board, rev. 1 firmware
-/* Melco products */
-product MELCO LUATX 0x0001 LU-ATX Ethernet adapter
+/* ADMtek products */
+product ADMTEK PEGASUS 0x0986 AN986 USB Ethernet adapter
-/* CATC products */
-product CATC ANDROMEDA 0x1237 Andromeda hub
-product CATC NETMATE 0x000a Netmate ethernet adapter
-product CATC NETMATE2 0x000c Netmate2 ethernet adapter
-product CATC CHIEF 0x000d USB Chief Bus & Protocol Analyzer
+/* ADS products */
+product ADS UBS10BT 0x0008 UBS-10BT Ethernet adapter
-/* Gravis products */
-product GRAVIS GAMEPADPRO 0x4001 GamePad Pro
+/* Agiler products */
+product ELECOM MOUSE29UO 0x0002 mouse 29UO
-/* Sun Microsystems products */
-product SUN KEYBOARD 0x0005 Type 6 USB
-/* XXX The above is a North American PC style keyboard possibly */
+/* AKS products */
+product AKS USBHASP 0x0001 USB-HASP 0.06
-/* Lexmark products */
-product LEXMARK S2450 0x0009 Optra S 2450
+/* Altec Lansing products */
+product ALTEC ASC495 0xff05 ASC495 Speakers
-/* Thrustmaster products */
-product THRUST FUSION_PAD 0xa0a3 Fusion Digital Gamepad
+/* American Power Conversion products */
+product APC UPSPRO500 0x0002 Back-UPS Pro 500
-/* Texas Intel products */
-product TI UTUSB41 0x1446 UT-USB41 hub
+/* Anchor products */
+product ANCHOR EZUSB 0x2131 EZUSB
-/* (KYE) Genius products */
-product KYE NICHE 0x0001 Niche mouse
-product KYE FLIGHT2000 0x1004 Flight 2000 joystick
+/* AOX Inc. products */
+product AOX USB101 0x0008 USB ethernet controller engine
-/* Microsoft products */
-product MICROSOFT INTELLIMOUSE 0x0009 IntelliMouse
-product MICROSOFT NATURALKBD 0x000b Natural Keyboard Elite
-product MICROSOFT DDS80 0x0014 Digital Sound System 80
+/* ATen products */
+product ATEN UC1284 0x2001 Parallel printer adapter
+product ATEN UC10T 0x2002 10Mbps ethernet adapter
-/* Primax products */
-product PRIMAX COMFORT 0x4d01 Comfort
-product PRIMAX MOUSEINABOX 0x4d02 Mouse-in-a-Box
+/* Belkin products */
+/*product BELKIN F5U111 0x???? F5U111 Ethernet adapter*/
-/* Cherry products */
-product CHERRY MY3000KBD 0x0001 My3000 keyboard
-product CHERRY MY3000HUB 0x0003 My3000 hub
+/* Billionton products */
+product BILLIONTON USB100 0x0986 USB100N 10/100 FastEthernet Adapter
+
+/* Brother Industries products */
+product BROTHER HL1050 0x0002 HL-1050 laser printer
/* Behavior Technology Computer products */
product BTC BTC7932 0x6782 Keyboard with mouse port
-/* Philips products */
-product PHILIPS DSS350 0x0101 DSS 350 Digital Speaker System
-product PHILIPS DSS 0x0104 DSS XXX Digital Speaker System
-product PHILIPS HUB 0x0201 hub
-product PHILIPS DSS150 0x0471 DSS XXX Digital Speaker System
-
-/* Connectix products */
-product CONNECTIX QUICKCAM 0x0001 QuickCam
-
-/* Lucent products */
-product LUCENT EVALKIT 0x1001 USS-720 evaluation kit
-
-/* STMicroelectronics products */
-product STMICRO COMMUNICATOR 0x7554 USB Communicator
-
-/* Acer products */
-product ACER ACERSCAN_C310U 0x12a6 Acerscan C310U
-
/* Canon Inc. products */
product CANON S10 0x3041 PowerShot S10
-/* Cypress Semiconductor products */
-product CYPRESS MOUSE 0x0001 mouse
-product CYPRESS THERMO 0x0002 thermometer
-
-/* Epson products */
-product EPSON PRINTER2 0x0002 ISD USB Smart Cable for Mac
-product EPSON PRINTER3 0x0003 ISD USB Smart Cable
-
-/* 3Com products */
-product 3COMUSR USR56K 0x3021 U.S.Robotics 56000 Voice Faxmodem Pro
-
-/* Konica Corp. Products */
-product KONICA CAMERA 0x0720 Digital Color Camera
+/* CATC products */
+product CATC NETMATE 0x000a Netmate ethernet adapter
+product CATC NETMATE2 0x000c Netmate2 ethernet adapter
+product CATC CHIEF 0x000d USB Chief Bus & Protocol Analyzer
+product CATC ANDROMEDA 0x1237 Andromeda hub
-/* Altec Lansing products */
-product ALTEC ASC495 0xff05 ASC495 Speakers
+/* Cherry products */
+product CHERRY MY3000KBD 0x0001 My3000 keyboard
+product CHERRY MY3000HUB 0x0003 My3000 hub
-/* Shuttle Technology products */
-product SHUTTLE EUSB 0x0001 E-USB Bridge
+/* Chic Technology products */
+product CHIC MOUSE1 0x0001 mouse
/* Chicony products */
product CHICONY KB8933 0x0001 KB-8933 keyboard
-/* Brother Industries products */
-product BROTHER HL1050 0x0002 HL-1050 laser printer
-
-/* Dallas Semiconductor products */
-product DALLAS J6502 0x4201 J-6502 speakers
-
-/* 3Com products */
-product 3COM 3C19250 0x03E8 3C19250 Ethernet adapter
+/* Connectix products */
+product CONNECTIX QUICKCAM 0x0001 QuickCam
-/* Kawatsu products */
-product KAWATSU MH4000P 0x0003 MiniHub 4000P
+/* Corega products */
+product COREGA ETHER_USB_T 0x0001 Ether USB-T
-/* American Power Conversion products */
-product APC UPSPRO500 0x0002 Back-UPS Pro 500
+/* Cypress Semiconductor products */
+product CYPRESS MOUSE 0x0001 mouse
+product CYPRESS THERMO 0x0002 thermometer
-/* NetChip Technology Products */
-product NETCHIP TURBOCONNECT 0x1080 Turbo-Connect
+/* D-Link products */
+/*product DLINK DSBS25 0x0100 DSB-S25 serial adapter*/
+product DLINK DSB650C 0x4000 10Mbps ethernet adapter
+product DLINK DSB650TX 0x4002 10/100 ethernet adapter
+product DLINK DSB650TX_PNA 0x4003 1/10/100 ethernet adapter
-/* AKS products */
-product AKS USBHASP 0x0001 USB-HASP 0.06
+/* Dallas Semiconductor products */
+product DALLAS J6502 0x4201 J-6502 speakers
-/* Universal Access products */
-product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter
+/* Diamond products */
+product DIAMOND RIO500USB 0x0001 Rio 500 USB
-/* Anchor products */
-product ANCHOR EZUSB 0x2131 EZUSB
+/* EIZO products */
+product EIZO HUB 0x0000 hub
+product EIZO MONITOR 0x0001 monitor
-/* Vision products */
-product VISION VC6452V002 0x0002 VC6452V002 Camera
+/* Elsa products */
+product ELSA MODEM1 0x2265 ELSA Modem Board
-/* ATen products */
-product ATEN UC1284 0x2001 Parallel printer adapter
-product ATEN UC10T 0x2002 10Mbps ethernet adapter
+/* Entrega products */
+product ENTREGA 1S 0x0001 1S serial connector
+product ENTREGA 2S 0x0002 2S serial connector
+product ENTREGA 1S25 0x0003 1S25 serial connector
+product ENTREGA 4S 0x0004 4S serial connector
+product ENTREGA E45 0x0005 E45 Ethernet adapter
+product ENTREGA CENTRONICS 0x0006 Centronics connector
+product ENTREGA 1S9 0x0093 1S9 serial connector
+product ENTREGA EZUSB 0x8000 EZ-USB
+/*product ENTREGA SERIAL 0x8001 DB25 Serial connector*/
+/*product ENTREGA SERIAL_DB9 0x8093 DB9 Serial connector*/
-/* Mustek products */
-product MUSTEK MDC800 0xa800 MDC-800 digital camera
+/* e-TEK Labs products */
+product ETEK 1COM 0x8007 Serial port
-/* Telex Communications products */
-product TELEX MIC1 0x0001 Enhanced USB Microphone
+/* Epson products */
+product EPSON PRINTER2 0x0002 ISD USB Smart Cable for Mac
+product EPSON PRINTER3 0x0003 ISD USB Smart Cable
-/* Peracom products */
-product PERACOM SERIAL1 0x0001 Serial Converter
-product PERACOM ENET 0x0002 Ethernet adapter
-product PERACOM ENET2 0x0005 Ethernet adapter
+/* Gravis products */
+product GRAVIS GAMEPADPRO 0x4001 GamePad Pro
-/* Wacom products */
-product WACOM CT0405U 0x0000 CT-0405-U Tablet
+/* Handspring Inc. */
+product HANDSPRING VISOR 0x0100 Handspring Visor
-/* e-TEK Labs products */
-product ETEK 1COM 0x8007 Serial port
+/* HP products */
+product HP 4100C 0x0101 Scanjet 4100C
+product HP S20 0x0102 Photosmart S20
+product HP 5200 0x0401 Scanjet 5200
+product HP 6300C 0x0601 Scanjet 6300C
+product HP 970CSE 0x1004 Deskjet 970Cse
+product HP P1100 0x3102 Photosmart P1100
-/* EIZO products */
-product EIZO HUB 0x0000 hub
-product EIZO MONITOR 0x0001 monitor
+/* Inside Out Networks products */
+product INSIDEOUT EDGEPORT4 0x0001 EdgePort/4 serial ports
-/* Agiler products */
-product ELECOM MOUSE29UO 0x0002 mouse 29UO
+/* In-System products */
+product INSYSTEM F5U002 0x0002 Parallel printer adapter
+product INSYSTEM ISD110 0x0200 IDE adapter
-/* Rockfire products */
-product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB
+/* Intel products */
+product INTEL TESTBOARD 0x9890 82930 test board
/* Iomega products */
product IOMEGA ZIP100 0x0001 Zip 100
-/* OmniVision Technologies Inc. products */
-product OMNIVISION OV511 0x0511 OV511 Camera
+/* Kawatsu products */
+product KAWATSU MH4000P 0x0003 MiniHub 4000P
-/* In-System products */
-product INSYSTEM F5U002 0x0002 Parallel printer adapter
-product INSYSTEM ISD110 0x0200 IDE adapter
+/* Kodak products */
+product KODAK DC260 0x0110 Digital Science DC260
+product KODAK DC265 0x0111 Digital Science DC265
+product KODAK DC290 0x0111 Digital Science DC290
+product KODAK DC240 0x0120 Digital Science DC240
+product KODAK DC280 0x0130 Digital Science DC280
-/* Qtronix products */
-product QTRONIX 980N 0x2011 Scorpion-980N keyboard
+/* Konica Corp. Products */
+product KONICA CAMERA 0x0720 Digital Color Camera
-/* Elsa products */
-product ELSA MODEM1 0x2265 ELSA Modem Board
+/* KYE products */
+product KYE NICHE 0x0001 Niche mouse
+product KYE FLIGHT2000 0x1004 Flight 2000 joystick
+
+/* Lexmark products */
+product LEXMARK S2450 0x0009 Optra S 2450
+
+/* Linksys products */
+product LINKSYS USB100TX 0x2203 USB100TX Ethernet
/* Logitech products */
product LOGITECH M2452 0x0203 M2452 keyboard
@@ -317,81 +310,116 @@ product LOGITECH QUICKCAMPRO 0x0810 QuickCam Pro
product LOGITECH N48 0xc001 N48 mouse
product LOGITECH MBA47 0xc002 M-BA47 mouse
-/* P.I. Engineering products */
-product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter
-
-/* Chic Technology products */
-product CHIC MOUSE1 0x0001 mouse
+/* Lucent products */
+product LUCENT EVALKIT 0x1001 USS-720 evaluation kit
/* Macally products */
product MACALLY MOUSE1 0x0101 mouse
-/* LinkSys products */
-product LINKSYS USB100TX 0x2203 10/100 ethernet adapter
+/* Melco Inc products */
+product MELCO LUATX 0x0001 LU-ATX Ethernet
+
+/* Microsoft products */
+product MICROSOFT INTELLIMOUSE 0x0009 IntelliMouse
+product MICROSOFT NATURALKBD 0x000b Natural Keyboard Elite
+product MICROSOFT DDS80 0x0014 Digital Sound System 80
+product MICROSOFT SIDEWINDER 0x001a Sidewinder Precision Racing Wheel
+
+/* Midiman products */
+product MIDIMAN MIDISPORT2X2 0x1001 Midisport 2x2
+
+/* Motorola products */
+product MOTOROLA MC141555 0x1555 MC141555 hub controller
/* MultiTech products */
product MULTITECH ATLAS 0xf101 MT5634ZBA-USB modem
-/* ADS products */
-product ADS ENET 0x0008 Ethernet adapter
+/* Mustek products */
+product MUSTEK MDC800 0xa800 MDC-800 digital camera
-/* SMC products */
-product SMC 2102USB 0x0100 10Mbps ethernet adapter
-product SMC 2202USB 0x0200 10/100 ethernet adapter
+/* NEC products */
+product NEC HUB 0x55aa hub
+product NEC HUB_B 0x55ab hub
-/* Entrega products */
-product ENTREGA 1S 0x0001 1S serial connector
-product ENTREGA 2S 0x0002 2S serial connector
-product ENTREGA 1S25 0x0003 1S25 serial connector
-product ENTREGA 4S 0x0004 4S serial connector
-product ENTREGA E45 0x0005 E45 Ethernet adapter
-product ENTREGA CENTRONICS 0x0006 Centronics connector
-product ENTREGA 1S9 0x0093 1S9 serial connector
-product ENTREGA EZUSB 0x8000 EZ-USB
-product ENTREGA SERIAL 0x8001 DB25 Serial connector
-product ENTREGA SERIAL_DB9 0x8093 DB9 Serial connector
+/* NetChip Technology Products */
+product NETCHIP TURBOCONNECT 0x1080 Turbo-Connect
-/* Midiman products */
-product MIDIMAN MIDISPORT2X2 0x1001 Midisport 2x2
+/* Netgear products */
+product NETGEAR EA101 0x1001 Ethernet adapter
-/* SanDisk products */
-product SANDISK IMAGEMATE 0x0001 USB ImageMate
+/* OmniVision Technologies Inc. products */
+product OMNIVISION OV511 0x0511 OV511 Camera
-/* ADMtek products */
-product ADMTEK PEGASUS 0x0986 AN986 USB Ethernet adapter
+/* Peracom products */
+product PERACOM SERIAL1 0x0001 Serial Converter
+product PERACOM ENET 0x0002 Ethernet adapter
+product PERACOM ENET2 0x0005 Ethernet adapter
-/* Corega products */
-product COREGA USB_T 0x0001 USB ethernet adapter
+/* Philips products */
+product PHILIPS DSS350 0x0101 DSS 350 Digital Speaker System
+product PHILIPS DSS 0x0104 DSS XXX Digital Speaker System
+product PHILIPS HUB 0x0201 hub
+product PHILIPS DSS150 0x0471 DSS XXX Digital Speaker System
+
+/* P.I. Engineering products */
+product PIENGINEERING PS2USB 0x020b PS2 to Mac USB Adapter
+
+/* PLX products */
+product PLX TESTBOARD 0x9060 test board
+
+/* Primax products */
+product PRIMAX COMFORT 0x4d01 Comfort
+product PRIMAX MOUSEINABOX 0x4d02 Mouse-in-a-Box
+
+/* Rockfire products */
+product ROCKFIRE GAMEPAD 0x2033 gamepad 203USB
+
+/* Qtronix products */
+product QTRONIX 980N 0x2011 Scorpion-980N keyboard
+
+/* SanDisk products */
+product SANDISK IMAGEMATE 0x0001 USB ImageMate
+
+/* Shuttle Technology products */
+product SHUTTLE EUSB 0x0001 E-USB Bridge
/* SIIG products */
product SIIG DIGIFILMREADER 0x0004 DigiFilm-Combo Reader
-/* Handspring Inc. */
-product HANDSPRING VISOR 0x0100 Handspring Visor
+/* Sirius Technologies products */
+product SIRIUS ROADSTER 0x0001 NetComm Roadster II 56 USB
-/* ActiveWire Inc. products */
-product ACTIVEWIRE IOBOARD 0x0100 I/O Board
-product ACTIVEWIRE IOBOARD_FW1 0x0101 I/O Board, rev. 1 firmware
+/* SMC products */
+product SMC 2102USB 0x0100 10Mbps ethernet adapter
+product SMC 2202USB 0x0200 10/100 ethernet adapter
-/* Netgear products */
-product NETGEAR EA101 0x1001 Ethernet adapter
+/* SOLID YEAR products */
+product SOLIDYEAR KEYBOARD 0x2101 Solid Year USB keyboard
-/* Billionton products */
-product BILLIONTON USB100 0x0986 USB100 Ethernet adapter
+/* STMicroelectronics products */
+product STMICRO COMMUNICATOR 0x7554 USB Communicator
-/* Motorola products */
-product MOTOROLA MC141555 0x1555 MC141555 hub controller
+/* Sun Microsystems products */
+product SUN KEYBOARD 0x0005 Type 6 USB
+/* XXX The above is a North American PC style keyboard possibly */
-/* PLX products */
-product PLX TESTBOARD 0x9060 test board
+/* Telex Communications products */
+product TELEX MIC1 0x0001 Enhanced USB Microphone
-/* Inside Out Networks products */
-product INSIDEOUT EDGEPORT4 0x0001 EdgePort/4 serial ports
+/* Texas Intel products */
+product TI UTUSB41 0x1446 UT-USB41 hub
-/* D-Link products */
-product DLINK DSB650C 0x4000 10Mbps ethernet adapter
-product DLINK DSB650TX 0x4002 10/100 ethernet adapter
-product DLINK DSB650TX_PNA 0x4003 1/10/100 ethernet adapter
+/* Thrustmaster products */
+product THRUST FUSION_PAD 0xa0a3 Fusion Digital Gamepad
-/* Intel products */
-product INTEL TESTBOARD 0x9890 82930 test board
+/* Universal Access products */
+product UNIACCESS PANACHE 0x0101 Panache Surf USB ISDN Adapter
+
+/* Vision products */
+product VISION VC6452V002 0x0002 VC6452V002 Camera
+
+/* Wacom products */
+product WACOM CT0405U 0x0000 CT-0405-U Tablet
+
+/* Zoom Telephonics Inc. products */
+product ZOOM 2986L 0x9700 2986L Fax modem
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index a5442060878a..75741fbd3b83 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi.c,v 1.51 1999/11/18 23:32:33 augustss Exp $ */
+/* $NetBSD: usbdi.c,v 1.60 2000/01/19 00:23:58 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -56,17 +56,17 @@
#include <sys/proc.h>
#include <machine/bus.h>
-#include <machine/clock.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_mem.h>
-#include <dev/usb/usb_quirks.h>
#if defined(__FreeBSD__)
#include "usb_if.h"
+#include <machine/clock.h>
+#define delay(d) DELAY(d)
#endif
#ifdef USB_DEBUG
@@ -80,11 +80,10 @@ extern int usbdebug;
static usbd_status usbd_ar_pipe __P((usbd_pipe_handle pipe));
static void usbd_do_request_async_cb
- __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
+ __P((usbd_xfer_handle, usbd_private_handle, usbd_status));
static void usbd_start_next __P((usbd_pipe_handle pipe));
-
-static SIMPLEQ_HEAD(, usbd_xfer) usbd_free_xfers =
- SIMPLEQ_HEAD_INITIALIZER(usbd_free_xfers);
+static usbd_status usbd_open_pipe_ival
+ __P((usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int));
static int usbd_nbuses = 0;
@@ -97,18 +96,7 @@ usbd_init()
void
usbd_finish()
{
- usbd_xfer_handle xfer;
-
- if (--usbd_nbuses == 0) {
- /* Last controller is gone, free all xfers. */
- for (;;) {
- xfer = SIMPLEQ_FIRST(&usbd_free_xfers);
- if (xfer == NULL)
- break;
- SIMPLEQ_REMOVE_HEAD(&usbd_free_xfers, xfer, next);
- free(xfer, M_USB);
- }
- }
+ --usbd_nbuses;
}
static __inline int usbd_xfer_isread __P((usbd_xfer_handle xfer));
@@ -148,11 +136,26 @@ usbd_open_pipe(iface, address, flags, pipe)
u_int8_t flags;
usbd_pipe_handle *pipe;
{
+ return (usbd_open_pipe_ival(iface, address, flags, pipe,
+ USBD_DEFAULT_INTERVAL));
+}
+
+usbd_status
+usbd_open_pipe_ival(iface, address, flags, pipe, ival)
+ usbd_interface_handle iface;
+ u_int8_t address;
+ u_int8_t flags;
+ usbd_pipe_handle *pipe;
+ int ival;
+{
usbd_pipe_handle p;
struct usbd_endpoint *ep;
usbd_status err;
int i;
+ DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
+ iface, address, flags));
+
for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
ep = &iface->endpoints[i];
if (ep->edesc == NULL)
@@ -162,10 +165,9 @@ usbd_open_pipe(iface, address, flags, pipe)
}
return (USBD_BAD_ADDRESS);
found:
- if ((flags & USBD_EXCLUSIVE_USE) &&
- ep->refcnt != 0)
+ if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
return (USBD_IN_USE);
- err = usbd_setup_pipe(iface->device, iface, ep, &p);
+ err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
if (err)
return (err);
LIST_INSERT_HEAD(&iface->pipes, p, next);
@@ -174,21 +176,26 @@ usbd_open_pipe(iface, address, flags, pipe)
}
usbd_status
-usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
+usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, len, cb, ival)
usbd_interface_handle iface;
u_int8_t address;
u_int8_t flags;
usbd_pipe_handle *pipe;
usbd_private_handle priv;
void *buffer;
- u_int32_t length;
+ u_int32_t len;
usbd_callback cb;
+ int ival;
{
usbd_status err;
usbd_xfer_handle xfer;
usbd_pipe_handle ipipe;
- err = usbd_open_pipe(iface, address, USBD_EXCLUSIVE_USE, &ipipe);
+ DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
+ address, flags, len));
+
+ err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
+ &ipipe, ival);
if (err)
return (err);
xfer = usbd_alloc_xfer(iface->device);
@@ -196,8 +203,8 @@ usbd_open_pipe_intr(iface, address, flags, pipe, priv, buffer, length, cb)
err = USBD_NOMEM;
goto bad1;
}
- usbd_setup_xfer(xfer, ipipe, priv, buffer, length, flags,
- USBD_NO_TIMEOUT, cb);
+ usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
+ USBD_NO_TIMEOUT, cb);
ipipe->intrxfer = xfer;
ipipe->repeat = 1;
err = usbd_transfer(xfer);
@@ -299,13 +306,13 @@ usbd_transfer(xfer)
if (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done\n");
- if (pipe->device->quirks->uq_flags & UQ_NO_TSLEEP) {
- int i, to;
- usbd_bus_handle bus;
- to = xfer->timeout * 1000;
- bus = pipe->device->bus;
+ /* XXX Temporary hack XXX */
+ if (xfer->flags & USBD_NO_TSLEEP) {
+ int i;
+ usbd_bus_handle bus = pipe->device->bus;
+ int to = xfer->timeout * 1000;
for (i = 0; i < to; i += 10) {
- DELAY(10);
+ delay(10);
bus->methods->do_poll(bus);
if (xfer->done)
break;
@@ -313,6 +320,7 @@ usbd_transfer(xfer)
if (!xfer->done)
pipe->methods->abort(xfer);
} else
+ /* XXX End hack XXX */
tsleep(xfer, PRIBIO, "usbsyn", 0);
}
splx(s);
@@ -372,14 +380,9 @@ usbd_alloc_xfer(dev)
{
usbd_xfer_handle xfer;
- xfer = SIMPLEQ_FIRST(&usbd_free_xfers);
- if (xfer != NULL)
- SIMPLEQ_REMOVE_HEAD(&usbd_free_xfers, xfer, next);
- else
- xfer = malloc(sizeof(*xfer), M_USB, M_NOWAIT);
+ xfer = dev->bus->methods->allocx(dev->bus);
if (xfer == NULL)
- return (0);
- memset(xfer, 0, sizeof *xfer);
+ return (NULL);
xfer->device = dev;
DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
return (xfer);
@@ -392,7 +395,7 @@ usbd_free_xfer(xfer)
DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
usbd_free_buffer(xfer);
- SIMPLEQ_INSERT_HEAD(&usbd_free_xfers, xfer, next);
+ xfer->device->bus->methods->freex(xfer->device->bus, xfer);
return (USBD_NORMAL_COMPLETION);
}
@@ -497,6 +500,12 @@ usb_config_descriptor_t *
usbd_get_config_descriptor(dev)
usbd_device_handle dev;
{
+#ifdef DIAGNOSTIC
+ if (dev == NULL) {
+ printf("usbd_get_config_descriptor: dev == NULL\n");
+ return (NULL);
+ }
+#endif
return (dev->cdesc);
}
@@ -504,6 +513,12 @@ usb_interface_descriptor_t *
usbd_get_interface_descriptor(iface)
usbd_interface_handle iface;
{
+#ifdef DIAGNOSTIC
+ if (iface == NULL) {
+ printf("usbd_get_interface_descriptor: dev == NULL\n");
+ return (NULL);
+ }
+#endif
return (iface->idesc);
}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index e9795433effd..dd1671c95155 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi.h,v 1.33 1999/11/17 23:00:50 augustss Exp $ */
+/* $NetBSD: usbdi.h,v 1.39 2000/01/19 00:23:59 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -70,18 +70,23 @@ typedef enum { /* keep in sync with usbd_status_msgs */
USBD_ERROR_MAX, /* must be last */
} usbd_status;
-typedef int usbd_lock_token;
-
typedef void (*usbd_callback) __P((usbd_xfer_handle, usbd_private_handle,
usbd_status));
/* Open flags */
#define USBD_EXCLUSIVE_USE 0x01
+/* Use default (specified by ep. desc.) interval on interrupt pipe */
+#define USBD_DEFAULT_INTERVAL (-1)
+
/* Request flags */
#define USBD_NO_COPY 0x01 /* do not copy data to DMA buffer */
#define USBD_SYNCHRONOUS 0x02 /* wait for completion */
/* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */
+#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */
+
+/* XXX Temporary hack XXX */
+#define USBD_NO_TSLEEP 0x80 /* XXX use busy wait */
#define USBD_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -137,7 +142,7 @@ usbd_status usbd_open_pipe_intr
__P((usbd_interface_handle iface, u_int8_t address,
u_int8_t flags, usbd_pipe_handle *pipe,
usbd_private_handle priv, void *buffer,
- u_int32_t length, usbd_callback));
+ u_int32_t length, usbd_callback, int));
usbd_status usbd_do_request
__P((usbd_device_handle pipe, usb_device_request_t *req, void *data));
usbd_status usbd_do_request_async
@@ -172,6 +177,13 @@ const char *usbd_errstr __P((usbd_status err));
void usbd_add_event __P((int, usbd_device_handle));
+void usbd_devinfo __P((usbd_device_handle, int, char *));
+struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
+usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
+ __P((usbd_interface_handle iface, u_int8_t address));
+
+usbd_status usbd_reload_device_desc __P((usbd_device_handle));
+
/* NetBSD attachment information */
/* Attach data */
@@ -231,17 +243,17 @@ struct usb_attach_arg {
#endif
-void usbd_devinfo __P((usbd_device_handle, int, char *));
-struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
-usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor
- __P((usbd_interface_handle iface, u_int8_t address));
-
#if defined(__FreeBSD__)
int usbd_driver_load __P((module_t mod, int what, void *arg));
#endif
+/*
+ * XXX
+ * splusb MUST be the lowest level interrupt so that within USB callbacks
+ * the level can be raised the appropriate level.
+ * XXX Should probably use a softsplusb.
+ */
/* XXX */
#define splusb splbio
#define IPL_USB IPL_BIO
/* XXX */
-
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index e1a6acaea6ec..6c8468d45d9e 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdivar.h,v 1.41 1999/11/18 23:32:37 augustss Exp $ */
+/* $NetBSD: usbdivar.h,v 1.46 2000/01/19 01:16:40 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -55,6 +55,9 @@ struct usbd_bus_methods {
usbd_status (*allocm)__P((struct usbd_bus *, usb_dma_t *,
u_int32_t bufsize));
void (*freem)__P((struct usbd_bus *, usb_dma_t *));
+ struct usbd_xfer * (*allocx)__P((struct usbd_bus *));
+ void (*freex)__P((struct usbd_bus *,
+ struct usbd_xfer *));
};
struct usbd_pipe_methods {
@@ -114,26 +117,26 @@ struct usbd_bus {
};
struct usbd_device {
- struct usbd_bus *bus;
- struct usbd_pipe *default_pipe;
- u_int8_t address;
- u_int8_t depth;
- u_int8_t lowspeed;
- u_int16_t power;
- u_int8_t self_powered;
- int config;
- int langid; /* language to use for strings */
+ struct usbd_bus *bus; /* our controller */
+ struct usbd_pipe *default_pipe; /* pipe 0 */
+ u_int8_t address; /* device addess */
+ u_int8_t config; /* current configuration # */
+ u_int8_t depth; /* distance from root hub */
+ u_int8_t lowspeed; /* lowspeed flag */
+ u_int8_t self_powered; /* flag for self powered */
+ u_int16_t power; /* mA the device uses */
+ int16_t langid; /* language for strings */
#define USBD_NOLANG (-1)
- usb_event_cookie_t cookie; /* unique connection id */
- struct usbd_port *powersrc;
- struct usbd_endpoint def_ep; /* for pipe 0 */
+ usb_event_cookie_t cookie; /* unique connection id */
+ struct usbd_port *powersrc; /* upstream hub port, or 0 */
+ struct usbd_endpoint def_ep; /* for pipe 0 */
usb_endpoint_descriptor_t def_ep_desc; /* for pipe 0 */
- struct usbd_interface *ifaces;
- usb_device_descriptor_t ddesc;
- usb_config_descriptor_t *cdesc; /* full config descr */
- struct usbd_quirks *quirks;
- struct usbd_hub *hub; /* only if this is a hub */
- device_ptr_t *subdevs; /* sub-devices, 0 terminated */
+ struct usbd_interface *ifaces; /* array of all interfaces */
+ usb_device_descriptor_t ddesc; /* device descriptor */
+ usb_config_descriptor_t *cdesc; /* full config descr */
+ struct usbd_quirks *quirks; /* device quirks, always set */
+ struct usbd_hub *hub; /* only if this is a hub */
+ device_ptr_t *subdevs; /* sub-devices, 0 terminated */
};
struct usbd_interface {
@@ -155,8 +158,9 @@ struct usbd_pipe {
SIMPLEQ_HEAD(, usbd_xfer) queue;
LIST_ENTRY(usbd_pipe) next;
- usbd_xfer_handle intrxfer; /* used for repeating requests */
+ usbd_xfer_handle intrxfer; /* used for repeating requests */
char repeat;
+ int interval;
/* Filled by HC driver. */
struct usbd_pipe_methods *methods;
@@ -193,7 +197,7 @@ struct usbd_xfer {
SIMPLEQ_ENTRY(usbd_xfer) next;
void *hcpriv; /* private use by the HC driver */
- int hcprivint; /* ditto */
+ int hcprivint;
#if defined(__FreeBSD__)
struct callout_handle timo_handle;
@@ -211,7 +215,7 @@ usbd_status usbd_reset_port __P((usbd_device_handle dev,
int port, usb_port_status_t *ps));
usbd_status usbd_setup_pipe __P((usbd_device_handle dev,
usbd_interface_handle iface,
- struct usbd_endpoint *,
+ struct usbd_endpoint *, int,
usbd_pipe_handle *pipe));
usbd_status usbd_new_device __P((device_ptr_t parent,
usbd_bus_handle bus, int depth,