summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authoraugustss <augustss@NetBSD.org>1998-12-26 12:53:00 +0000
committeraugustss <augustss@NetBSD.org>1998-12-26 12:53:00 +0000
commite0c228ae9ccccf6f66a1aa9af09b93b1aecd7218 (patch)
tree88502f87b0b8f6cf6a605dea707b6a8657c6275b /sys/dev
parentfbff13e33e5a1d7fbf790ac60cfd70868190330e (diff)
Merge changes to make the USB stack work with FreeBSD. The original
diffs from Nick Hibma <n_hibma@freebsd.org>, but with substantial changes from me. XXX Not tested on FreeBSD yet.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/hid.c8
-rw-r--r--sys/dev/usb/ohci.c150
-rw-r--r--sys/dev/usb/ohcivar.h10
-rw-r--r--sys/dev/usb/ucom.c64
-rw-r--r--sys/dev/usb/ugen.c56
-rw-r--r--sys/dev/usb/uhci.c121
-rw-r--r--sys/dev/usb/uhcivar.h12
-rw-r--r--sys/dev/usb/uhid.c113
-rw-r--r--sys/dev/usb/uhub.c277
-rw-r--r--sys/dev/usb/ukbd.c127
-rw-r--r--sys/dev/usb/ulpt.c95
-rw-r--r--sys/dev/usb/umodem.c68
-rw-r--r--sys/dev/usb/ums.c527
-rw-r--r--sys/dev/usb/usb.c216
-rw-r--r--sys/dev/usb/usb.h50
-rw-r--r--sys/dev/usb/usb_mem.h34
-rw-r--r--sys/dev/usb/usb_port.h180
-rw-r--r--sys/dev/usb/usb_quirks.c6
-rw-r--r--sys/dev/usb/usb_subr.c288
-rw-r--r--sys/dev/usb/usbdi.c85
-rw-r--r--sys/dev/usb/usbdi.h44
-rw-r--r--sys/dev/usb/usbdi_util.c24
-rw-r--r--sys/dev/usb/usbdi_util.h7
-rw-r--r--sys/dev/usb/usbdivar.h30
-rw-r--r--sys/dev/usb/usbhid.h37
25 files changed, 1958 insertions, 671 deletions
diff --git a/sys/dev/usb/hid.c b/sys/dev/usb/hid.c
index 1b9614c57a9..41948f17391 100644
--- a/sys/dev/usb/hid.c
+++ b/sys/dev/usb/hid.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hid.c,v 1.4 1998/12/08 14:31:58 augustss Exp $ */
+/* $NetBSD: hid.c,v 1.5 1998/12/26 12:53:00 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -50,7 +50,7 @@
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
-int usbdebug;
+extern int usbdebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -426,7 +426,7 @@ hid_get_data(buf, loc)
u_int32_t data;
int i, s;
- DPRINTFN(1, ("hid_get_data: loc %d/%d\n", hpos, hsize));
+ DPRINTFN(10, ("hid_get_data: loc %d/%d\n", hpos, hsize));
if (hsize == 0)
return (0);
@@ -440,7 +440,7 @@ hid_get_data(buf, loc)
hsize = 32 - hsize;
/* Sign extend */
data = ((int32_t)data << hsize) >> hsize;
- DPRINTFN(2,("hid_get_data: loc %d/%d = %lu\n",
+ DPRINTFN(10,("hid_get_data: loc %d/%d = %lu\n",
loc->pos, loc->size, (long)data));
return (data);
}
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 5b8edd025fd..39b1cf62160 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ohci.c,v 1.14 1998/12/10 23:16:47 augustss Exp $ */
+/* $NetBSD: ohci.c,v 1.15 1998/12/26 12:53:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -48,7 +48,12 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/select.h>
@@ -64,7 +69,13 @@
#include <dev/usb/ohcireg.h>
#include <dev/usb/ohcivar.h>
-int ohcidebug = 0;
+#if defined(__FreeBSD__)
+#include <machine/clock.h>
+#include "dev/usb/queue.addendum.h"
+
+#define delay(d) DELAY(d)
+
+#endif
struct ohci_pipe;
@@ -79,6 +90,7 @@ void ohci_poll __P((struct usbd_bus *));
void ohci_waitintr __P((ohci_softc_t *, usbd_request_handle));
void ohci_rhsc __P((ohci_softc_t *, usbd_request_handle));
void ohci_process_done __P((ohci_softc_t *, ohci_physaddr_t));
+void ohci_ii_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_ctrl_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_intr_done __P((ohci_softc_t *, usbd_request_handle));
void ohci_bulk_done __P((ohci_softc_t *, usbd_request_handle));
@@ -125,9 +137,15 @@ void ohci_dump_td __P((ohci_soft_td_t *));
void ohci_dump_ed __P((ohci_soft_ed_t *));
#endif
+#if defined(__NetBSD__)
#define OWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
#define OREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r))
#define OREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r))
+#elif defined(__FreeBSD__)
+#define OWRITE4(sc, r, x) outl((sc)->sc_iobase + (r), (x))
+#define OREAD4(sc, r) inl((sc)->sc_iobase + (r))
+#define OREAD2(sc, r) inw((sc)->sc_iobase + (r))
+#endif
/* Reverse the bits in a value 0 .. 31 */
static u_int8_t revbits[OHCI_NO_INTRS] =
@@ -303,12 +321,12 @@ ohci_init(sc)
DPRINTF(("ohci_init: start\n"));
rev = OREAD4(sc, OHCI_REVISION);
- printf("%s: OHCI version %d.%d%s\n", sc->sc_bus.bdev.dv_xname,
+ printf("%s: OHCI version %d.%d%s\n", USBDEVNAME(sc->sc_bus.bdev),
OHCI_REV_HI(rev), OHCI_REV_LO(rev),
OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
printf("%s: unsupported OHCI revision\n",
- sc->sc_bus.bdev.dv_xname);
+ USBDEVNAME(sc->sc_bus.bdev));
return (USBD_INVAL);
}
@@ -376,8 +394,8 @@ ohci_init(sc)
ctl = OREAD4(sc, OHCI_CONTROL);
}
if ((ctl & OHCI_IR) == 0) {
- printf("%s: SMM does not respond, resetting\n",
- sc->sc_bus.bdev.dv_xname);
+ printf("%s: SMM does not respond, resetting\n",
+ USBDEVNAME(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
goto reset;
}
@@ -407,7 +425,7 @@ ohci_init(sc)
break;
}
if (hcr) {
- printf("%s: reset timeout\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
r = USBD_IOERROR;
goto bad3;
}
@@ -446,9 +464,6 @@ ohci_init(sc)
OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
- printf("%s: %d downstream port%s\n",
- sc->sc_bus.bdev.dv_xname, sc->sc_noport,
- sc->sc_noport != 1 ? "s" : "");
#ifdef USB_DEBUG
if (ohcidebug > 5)
@@ -524,6 +539,14 @@ ohci_intr(p)
u_int32_t intrs, eintrs;
ohci_physaddr_t done;
+ /* In case the interrupt occurs before initialization has completed. */
+ if (sc->sc_hcca == NULL) {
+#ifdef DIAGNOSTIC
+ printf("ohci_intr: sc->sc_hcca == NULL\n");
+#endif
+ return (0);
+ }
+
done = sc->sc_hcca->hcca_done_head;
if (done != 0) {
intrs = OHCI_WDH;
@@ -545,7 +568,7 @@ ohci_intr(p)
(u_int)eintrs));
if (eintrs & OHCI_SO) {
- printf("%s: scheduling overrun\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: scheduling overrun\n",USBDEVNAME(sc->sc_bus.bdev));
/* XXX do what */
intrs &= ~OHCI_SO;
}
@@ -558,8 +581,8 @@ ohci_intr(p)
/* XXX process resume detect */
}
if (eintrs & OHCI_UE) {
- printf("%s: unrecoverable error, controller halted\n",
- sc->sc_bus.bdev.dv_xname);
+ printf("%s: unrecoverable error, controller halted\n",
+ USBDEVNAME(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
/* XXX what else */
}
@@ -649,26 +672,13 @@ ohci_process_done(sc, done)
else
len = std->td->td_be - std->td->td_cbp + 1;
reqh->actlen += len;
- if (reqh->hcpriv == std) {
- switch (reqh->pipe->endpoint->edesc->
- bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- ohci_ctrl_done(sc, reqh);
- break;
- case UE_INTERRUPT:
- ohci_intr_done(sc, reqh);
- break;
- case UE_BULK:
- ohci_bulk_done(sc, reqh);
- break;
- case UE_ISOCHRONOUS:
- printf("ohci_process_done: ISO done?\n");
- break;
- }
- /* And finally execute callback. */
- reqh->status = USBD_NORMAL_COMPLETION;
- reqh->xfercb(reqh);
- }
+ reqh->status = USBD_NORMAL_COMPLETION;
+ /*
+ * Only do a callback on the last stage of a transfer.
+ * Others have hcpriv = 0.
+ */
+ if (reqh->hcpriv == std)
+ ohci_ii_done(sc, reqh);
} else {
ohci_soft_td_t *p, *n;
struct ohci_pipe *opipe =
@@ -693,7 +703,7 @@ ohci_process_done(sc, done)
reqh->status = USBD_STALLED;
else
reqh->status = USBD_IOERROR;
- reqh->xfercb(reqh);
+ ohci_ii_done(sc, reqh);
}
ohci_hash_rem_td(sc, std);
ohci_free_std(sc, std);
@@ -701,6 +711,30 @@ ohci_process_done(sc, done)
}
void
+ohci_ii_done(sc, reqh)
+ ohci_softc_t *sc;
+ usbd_request_handle reqh;
+{
+ switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
+ case UE_CONTROL:
+ ohci_ctrl_done(sc, reqh);
+ break;
+ case UE_INTERRUPT:
+ ohci_intr_done(sc, reqh);
+ break;
+ case UE_BULK:
+ ohci_bulk_done(sc, reqh);
+ break;
+ case UE_ISOCHRONOUS:
+ printf("ohci_process_done: ISO done?\n");
+ break;
+ }
+
+ /* And finally execute callback. */
+ reqh->xfercb(reqh);
+}
+
+void
ohci_ctrl_done(sc, reqh)
ohci_softc_t *sc;
usbd_request_handle reqh;
@@ -722,7 +756,7 @@ ohci_ctrl_done(sc, reqh)
memcpy(reqh->buffer, KERNADDR(dma), len);
usb_freemem(sc->sc_dmatag, dma);
}
- untimeout(ohci_timeout, reqh);
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
void
@@ -787,7 +821,7 @@ ohci_bulk_done(sc, reqh)
if (reqh->request.bmRequestType & UT_READ)
memcpy(reqh->buffer, KERNADDR(dma), reqh->actlen);
usb_freemem(sc->sc_dmatag, dma);
- untimeout(ohci_timeout, reqh);
+ usb_untimeout(ohci_timeout, reqh, reqh->timo_handle);
}
void
@@ -847,7 +881,7 @@ ohci_waitintr(sc, reqh)
reqh->status = USBD_IN_PROGRESS;
for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
- delay(1000);
+ usbd_delay_ms(&sc->sc_bus, 1);
intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
DPRINTFN(10,("ohci_waitintr: 0x%04x\n", intrs));
#ifdef USB_DEBUG
@@ -860,9 +894,12 @@ ohci_waitintr(sc, reqh)
return;
}
}
+
+ /* Timeout */
DPRINTF(("ohci_waitintr: timeout\n"));
reqh->status = USBD_TIMEOUT;
- reqh->xfercb(reqh);
+ ohci_ii_done(sc, reqh);
+ /* XXX should free TD */
}
void
@@ -992,8 +1029,10 @@ ohci_device_request(reqh)
sed->ed->ed_tailp = tail->physaddr;
opipe->tail = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
- if (reqh->timeout && !sc->sc_bus.use_polling)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
+ if (reqh->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+ }
splx(s);
#if USB_DEBUG
@@ -1298,7 +1337,6 @@ usb_hub_descriptor_t ohci_hubd = {
0,
0,
{0},
- {0},
};
int
@@ -1356,7 +1394,7 @@ ohci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
/*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_STALL are no-ops
+ * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
* for the integrated root hub.
*/
break;
@@ -1521,24 +1559,16 @@ ohci_root_ctrl_transfer(reqh)
v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
hubd = ohci_hubd;
hubd.bNbrPorts = sc->sc_noport;
- USETW(hubd.bHubCharacteristics,
+ USETW(hubd.wHubCharacteristics,
(v & OHCI_NPS ? UHD_PWR_NO_SWITCH :
v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)
/* XXX overcurrent */
);
hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v);
v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
- if (sc->sc_noport < 8) {
- hubd.DeviceRemovable[0] = (u_int8_t)v;
- hubd.PortPowerCtrlMask[0] = (u_int8_t)(v >> 16);
- hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE;
- } else {
- hubd.DeviceRemovable[0] = (u_int8_t)v;
- hubd.DeviceRemovable[1] = (u_int8_t)(v>>8);
- hubd.PortPowerCtrlMask[1] = (u_int8_t)(v >> 16);
- hubd.PortPowerCtrlMask[2] = (u_int8_t)(v >> 24);
- hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + 2;
- }
+ for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
+ hubd.DeviceRemovable[i++] = (u_int8_t)v;
+ hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i;
l = min(len, hubd.bDescLength);
totlen = l;
memcpy(buf, &hubd, l);
@@ -1806,8 +1836,10 @@ ohci_device_bulk_transfer(reqh)
sed->ed->ed_tailp = tail->physaddr;
opipe->tail = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
- if (reqh->timeout && !sc->sc_bus.use_polling)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
+ if (reqh->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+ }
splx(s);
return (USBD_IN_PROGRESS);
@@ -1917,8 +1949,10 @@ ohci_device_intr_transfer(reqh)
sed->ed->ed_tailp = tail->physaddr;
opipe->tail = tail;
#if 0
- if (reqh->timeout && !sc->sc_bus.use_polling)
- timeout(ohci_timeout, reqh, MS_TO_TICKS(reqh->timeout));
+ if (reqh->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(ohci_timeout, reqh,
+ MS_TO_TICKS(reqh->timeout), reqh->timo_handle);
+ }
#endif
sed->ed->ed_flags &= ~OHCI_ED_SKIP;
splx(s);
diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h
index 6fd27b658d8..80d580365f1 100644
--- a/sys/dev/usb/ohcivar.h
+++ b/sys/dev/usb/ohcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ohcivar.h,v 1.3 1998/11/25 22:32:04 augustss Exp $ */
+/* $NetBSD: ohcivar.h,v 1.4 1998/12/26 12:53:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -62,6 +62,7 @@ typedef struct ohci_soft_td {
typedef struct ohci_softc {
struct usbd_bus sc_bus; /* base device */
+#if defined(__NetBSD__)
void *sc_ih; /* interrupt vectoring */
bus_space_tag_t iot;
bus_space_handle_t ioh;
@@ -69,6 +70,11 @@ typedef struct ohci_softc {
bus_dma_tag_t sc_dmatag; /* DMA tag */
/* XXX should keep track of all DMA memory */
+#elif defined(__FreeBSD__)
+ int sc_iobase;
+ int unit;
+#endif /* __FreeBSD__ */
+
usb_dma_t sc_hccadma;
struct ohci_hcca *sc_hcca;
ohci_soft_ed_t *sc_eds[OHCI_NO_EDS];
@@ -101,7 +107,7 @@ int ohci_intr __P((void *));
#ifdef USB_DEBUG
#define DPRINTF(x) if (ohcidebug) printf x
#define DPRINTFN(n,x) if (ohcidebug>(n)) printf x
-int ohcidebug;
+extern int ohcidebug;
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c
index 4bbd80d762d..e12175bce4c 100644
--- a/sys/dev/usb/ucom.c
+++ b/sys/dev/usb/ucom.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ucom.c,v 1.2 1998/12/09 00:18:10 augustss Exp $ */
+/* $NetBSD: ucom.c,v 1.3 1998/12/26 12:53:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,13 +37,21 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <dev/usb/usb_port.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#include <sys/conf.h>
+#endif
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/select.h>
@@ -56,6 +64,7 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -71,29 +80,18 @@ int ucomdebug = 0;
#endif
struct ucom_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
};
-int ucom_match __P((struct device *, struct cfdata *, void *));
-void ucom_attach __P((struct device *, struct device *, void *));
-
void ucom_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void ucom_disco __P((void *));
-extern struct cfdriver ucom_cd;
-
-struct cfattach ucom_ca = {
- sizeof(struct ucom_softc), ucom_match, ucom_attach
-};
+USB_DECLARE_DRIVER(ucom);
-int
-ucom_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ucom)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(ucom, uaa);
usb_interface_descriptor_t *id;
if (!uaa->iface)
@@ -106,14 +104,9 @@ ucom_match(parent, match, aux)
return (UMATCH_IFACECLASS_IFACESUBCLASS);
}
-void
-ucom_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ucom)
{
- struct ucom_softc *sc = (struct ucom_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(ucom, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
char devinfo[1024];
@@ -121,6 +114,29 @@ ucom_attach(parent, self, aux)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
+
+ USB_ATTACH_SUCCESS_RETURN;
+}
+
+#if defined(__FreeBSD__)
+static int
+ucom_detach(device_t self)
+{
+ struct ucom_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
}
+#endif
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(ucom, usb, ucom_driver, ucom_devclass, usb_driver_load, 0);
+#endif
+
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index b8a0f77767b..0195a36029e 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ugen.c,v 1.4 1998/12/12 11:59:28 augustss Exp $ */
+/* $NetBSD: ugen.c,v 1.5 1998/12/26 12:53:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -115,19 +115,11 @@ int ugen_get_alt_index __P((struct ugen_softc *sc, int ifaceidx));
#define UGENUNIT(n) (((n) >> 4) & 0xf)
#define UGENENDPOINT(n) ((n) & 0xf)
-extern struct cfdriver ugen_cd;
+USB_DECLARE_DRIVER(ugen);
-struct cfattach ugen_ca = {
- sizeof(struct ugen_softc), ugen_match, ugen_attach
-};
-
-int
-ugen_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ugen)
{
- struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
+ USB_MATCH_START(ugen, uaa);
if (uaa->usegeneric)
return (UMATCH_GENERIC);
@@ -135,28 +127,25 @@ ugen_match(parent, match, aux)
return (UMATCH_NONE);
}
-void
-ugen_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ugen)
{
- struct ugen_softc *sc = (struct ugen_softc *)self;
- struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
+ USB_ATTACH_START(ugen, sc, uaa);
char devinfo[1024];
usbd_status r;
usbd_devinfo(uaa->device, 0, devinfo);
- printf(": %s\n", devinfo);
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
sc->sc_udev = uaa->device;
- r = ugen_set_config(sc, 1);
+ r = ugen_set_config(sc, 1); /* XXX 1 */
if (r != USBD_NORMAL_COMPLETION) {
- printf("%s: setting configuration 0 failed\n",
- sc->sc_dev.dv_xname);
+ printf("%s: setting configuration 1 failed\n",
+ USBDEVNAME(sc->sc_dev));
sc->sc_disconnected = 1;
- return;
+ USB_ATTACH_ERROR_RETURN;
}
+ USB_ATTACH_SUCCESS_RETURN;
}
int
@@ -173,7 +162,7 @@ ugen_set_config(sc, configno)
usbd_status r;
DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
- sc->sc_dev.dv_xname, configno, sc));
+ USBDEVNAME(sc->sc_dev), configno, sc));
r = usbd_set_config_no(dev, configno, 0);
if (r != USBD_NORMAL_COMPLETION)
return (r);
@@ -687,7 +676,7 @@ ugenioctl(dev, cmd, addr, flag, p)
case USB_SET_CONFIG:
if (!(flag & FWRITE))
return (EPERM);
- r = usbd_set_config_no(sc->sc_udev, *(int *)addr, 0);
+ r = ugen_set_config(sc, *(int *)addr);
if (r != USBD_NORMAL_COMPLETION)
return (EIO);
break;
@@ -915,3 +904,18 @@ ugenpoll(dev, events, p)
splx(s);
return (revents);
}
+
+#if defined(__FreeBSD__)
+static int
+ugen_detach(device_t self)
+{
+ struct ugen_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
+}
+#endif
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index bd7e69690f8..267cf51cffd 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uhci.c,v 1.12 1998/12/10 23:16:47 augustss Exp $ */
+/* $NetBSD: uhci.c,v 1.13 1998/12/26 12:53:01 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -51,7 +51,12 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/select.h>
@@ -67,6 +72,13 @@
#include <dev/usb/uhcireg.h>
#include <dev/usb/uhcivar.h>
+#if defined(__FreeBSD__)
+#include <machine/clock.h>
+#include "dev/usb/queue.addendum.h"
+
+#define delay(d) DELAY(d)
+#endif
+
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
struct uhci_pipe {
@@ -103,7 +115,6 @@ struct uhci_pipe {
* The uhci_intr_info free list can be global since they contain
* no dma specific data. The other free lists do.
*/
-int uhci_global_init_done = 0;
LIST_HEAD(, uhci_intr_info) uhci_ii_free;
void uhci_busreset __P((uhci_softc_t *));
@@ -180,10 +191,17 @@ void uhci_dump __P((void));
void uhci_dump_td __P((uhci_soft_td_t *));
#endif
+#if defined(__NetBSD__)
#define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))
#define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))
#define UREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r))
#define UREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r))
+#elif defined(__FreeBSD__)
+#define UWRITE2(sc,r,x) outw((sc)->sc_iobase + (r), (x))
+#define UWRITE4(sc,r,x) outl((sc)->sc_iobase + (r), (x))
+#define UREAD2(sc,r) inw((sc)->sc_iobase + (r))
+#define UREAD4(sc,r) inl((sc)->sc_iobase + (r))
+#endif
#define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd)
#define UHCISTS(sc) UREAD2(sc, UHCI_STS)
@@ -249,6 +267,7 @@ uhci_init(sc)
uhci_soft_qh_t *csqh, *bsqh, *sqh;
uhci_soft_td_t *std;
usb_dma_t dma;
+ static int uhci_global_init_done = 0;
DPRINTFN(1,("uhci_init: start\n"));
@@ -303,7 +322,7 @@ uhci_init(sc)
std = uhci_alloc_std(sc);
sqh = uhci_alloc_sqh(sc);
if (!std || !sqh)
- return (ENOMEM);
+ return (USBD_NOMEM);
std->td->link.sqh = sqh;
std->td->td_link = sqh->physaddr | UHCI_PTR_Q;
std->td->td_status = UHCI_TD_IOS; /* iso, inactive */
@@ -343,8 +362,9 @@ static void
uhci_dumpregs(sc)
uhci_softc_t *sc;
{
- printf("%s: regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
- sc->sc_bus.bdev.dv_xname,
+ printf("%s; regs: cmd=%04x, sts=%04x, intr=%04x, frnum=%04x, "
+ "flbase=%08x, sof=%04x, portsc1=%04x, portsc2=%04x\n",
+ USBDEVNAME(sc->sc_bus.bdev),
UREAD2(sc, UHCI_CMD),
UREAD2(sc, UHCI_STS),
UREAD2(sc, UHCI_INTR),
@@ -382,7 +402,6 @@ uhci_dump_td(p)
UHCI_TD_GET_ENDPT(p->td->td_token),
UHCI_TD_GET_DT(p->td->td_token),
UHCI_TD_GET_MAXLEN(p->td->td_token));
-
}
void
@@ -393,6 +412,7 @@ uhci_dump_qh(p)
p->qh->qh_hlink, p->qh->qh_elink);
}
+
#if 0
void
uhci_dump()
@@ -448,7 +468,7 @@ uhci_timo(addr)
splx(s);
}
if (reqh->pipe->intrreqh == reqh) {
- timeout(uhci_timo, addr, sc->sc_ival);
+ usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
} else {
usb_freemem(sc->sc_dmatag, &upipe->u.intr.datadma);
}
@@ -601,7 +621,7 @@ uhci_intr(p)
sc->sc_intrs++;
#if defined(USB_DEBUG)
if (uhcidebug > 9) {
- DPRINTF(("uhci_intr %s, %p\n", sc->sc_bus.bdev.dv_xname, sc));
+ printf("uhci_intr %p\n", sc);
uhci_dumpregs(sc);
}
#endif
@@ -617,22 +637,21 @@ uhci_intr(p)
}
if (status & UHCI_STS_RD) {
UWRITE2(sc, UHCI_STS, UHCI_STS_RD); /* acknowledge */
- printf("%s: resume detect\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
if (status & UHCI_STS_HSE) {
UWRITE2(sc, UHCI_STS, UHCI_STS_HSE); /* acknowledge */
- printf("%s: Host System Error\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
if (status & UHCI_STS_HCPE) {
UWRITE2(sc, UHCI_STS, UHCI_STS_HCPE); /* acknowledge */
- printf("%s: Host System Error\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: Host System Error\n", USBDEVNAME(sc->sc_bus.bdev));
ret = 1;
}
- if (status & UHCI_STS_HCH) {
- printf("%s: controller halted\n", sc->sc_bus.bdev.dv_xname);
- }
+ if (status & UHCI_STS_HCH)
+ printf("%s: controller halted\n", USBDEVNAME(sc->sc_bus.bdev));
if (!ret)
return 0;
@@ -692,7 +711,7 @@ uhci_check_intr(sc, ii)
upipe = (struct uhci_pipe *)ii->reqh->pipe;
upipe->pipe.endpoint->toggle = upipe->newtoggle;
uhci_ii_done(ii, 0);
- untimeout(uhci_timeout, ii);
+ usb_untimeout(uhci_timeout, ii, ii->timeout_handle);
}
void
@@ -728,7 +747,7 @@ uhci_ii_done(ii, timo)
status |= tst;
#ifdef USB_DEBUG
if ((tst & UHCI_TD_ERROR) && uhcidebug) {
- printf("uhci_intr: intr error TD:\n");
+ printf("uhci_ii_done: intr error TD:\n");
uhci_dump_td(std);
}
#endif
@@ -739,7 +758,7 @@ uhci_ii_done(ii, timo)
DPRINTFN(10, ("uhci_check_intr: len=%d, status=0x%x\n", len, status));
if (status != 0) {
DPRINTFN(-1+(status==UHCI_TD_STALLED),
- ("uhci_intr: error, status 0x%b\n", (long)status,
+ ("uhci_ii_done: error, status 0x%b\n", (long)status,
"\20\22BITSTUFF\23CRCTO\24NAK\25BABBLE\26DBUFFER\27"
"STALLED\30ACTIVE"));
if (status == UHCI_TD_STALLED)
@@ -758,7 +777,7 @@ uhci_ii_done(ii, timo)
std->td->td_status &= ~UHCI_TD_ACTIVE;
/* XXX should we wait 1 ms */
}
- DPRINTFN(5, ("uhci_intr: calling handler ii=%p\n", ii));
+ DPRINTFN(5, ("uhci_ii_done: calling handler ii=%p\n", ii));
switch (reqh->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
@@ -779,6 +798,9 @@ uhci_ii_done(ii, timo)
reqh->xfercb(reqh);
}
+/*
+ * Called when a request does not complete.
+ */
void
uhci_timeout(addr)
void *addr;
@@ -796,6 +818,7 @@ uhci_timeout(addr)
* Wait here until controller claims to have an interrupt.
* Then call uhci_intr and return. Use timeout to avoid waiting
* too long.
+ * Only used during boot when interrupts are not enabled yet.
*/
void
uhci_waitintr(sc, reqh)
@@ -804,10 +827,13 @@ uhci_waitintr(sc, reqh)
{
int timo = reqh->timeout;
int usecs;
+ uhci_intr_info_t *ii;
+
+ DPRINTFN(10,("uhci_waitintr: timeout = %ds\n", timo));
reqh->status = USBD_IN_PROGRESS;
for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
- delay(1000);
+ usbd_delay_ms(&sc->sc_bus, 1);
DPRINTFN(10,("uhci_waitintr: 0x%04x\n", UREAD2(sc, UHCI_STS)));
if (UREAD2(sc, UHCI_STS) & UHCI_STS_USBINT) {
uhci_intr(sc);
@@ -815,8 +841,17 @@ uhci_waitintr(sc, reqh)
return;
}
}
- reqh->status = USBD_TIMEOUT;
- reqh->xfercb(reqh);
+
+ /* Timeout */
+ DPRINTF(("uhci_waitintr: timeout\n"));
+ for (ii = LIST_FIRST(&sc->sc_intrhead);
+ ii && ii->reqh != reqh;
+ ii = LIST_NEXT(ii, list))
+ ;
+ if (ii)
+ uhci_ii_done(ii, 1);
+ else
+ panic("uhci_waitintr: lost intr_info\n");
}
void
@@ -843,7 +878,8 @@ uhci_reset(p)
(UREAD2(sc, UHCI_CMD) & UHCI_CMD_HCRESET); n++)
delay(100);
if (n >= UHCI_RESET_TIMEOUT)
- printf("%s: controller did not reset\n", sc->sc_bus.bdev.dv_xname);
+ printf("%s: controller did not reset\n",
+ USBDEVNAME(sc->sc_bus.bdev));
}
#endif
@@ -862,17 +898,18 @@ uhci_run(sc, run)
return;
}
UWRITE2(sc, UHCI_CMD, run ? UHCI_CMD_RS : 0);
- for(n = 0; n < 100; n++) {
+ for(n = 0; n < 10; n++) {
running = !(UREAD2(sc, UHCI_STS) & UHCI_STS_HCH);
/* return when we've entered the state we want */
if (run == running) {
splx(s);
return;
}
+ usbd_delay_ms(&sc->sc_bus, 1);
}
splx(s);
- printf("%s: cannot %s\n", sc->sc_bus.bdev.dv_xname,
- run ? "start" : "stop");
+ printf("%s: cannot %s\n", USBDEVNAME(sc->sc_bus.bdev),
+ (run ? "start" : "stop"));
}
/*
@@ -1142,8 +1179,10 @@ uhci_device_bulk_transfer(reqh)
uhci_add_bulk(sc, sqh);
LIST_INSERT_HEAD(&sc->sc_intrhead, ii, list);
- if (reqh->timeout && !sc->sc_bus.use_polling)
- timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout));
+ if (reqh->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(uhci_timeout, ii,
+ MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
+ }
splx(s);
#ifdef USB_DEBUG
@@ -1379,7 +1418,7 @@ uhci_device_request(reqh)
int isread;
int s;
- DPRINTFN(1,("uhci_device_control type=0x%02x, request=0x%02x, "
+ DPRINTFN(3,("uhci_device_control type=0x%02x, request=0x%02x, "
"wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
req->bmRequestType, req->bRequest, UGETW(req->wValue),
UGETW(req->wIndex), UGETW(req->wLength),
@@ -1461,6 +1500,8 @@ uhci_device_request(reqh)
if (uhcidebug > 12) {
uhci_soft_td_t *std;
uhci_soft_qh_t *xqh;
+ uhci_soft_qh_t *sxqh;
+ int maxqh = 0;
uhci_physaddr_t link;
printf("uhci_enter_ctl_q: follow from [0]\n");
for (std = sc->sc_vframes[0].htd, link = 0;
@@ -1469,17 +1510,22 @@ uhci_device_request(reqh)
link = std->td->td_link;
uhci_dump_td(std);
}
- for (xqh = (uhci_soft_qh_t *)std;
+ for (sxqh = xqh = (uhci_soft_qh_t *)std;
xqh;
- xqh = xqh->qh->hlink)
+ xqh = (maxqh++ == 5 || xqh->qh->hlink==sxqh ||
+ xqh->qh->hlink==xqh ? NULL : xqh->qh->hlink)) {
uhci_dump_qh(xqh);
+ uhci_dump_qh(sxqh);
+ }
printf("Enqueued QH:\n");
uhci_dump_qh(sqh);
uhci_dump_tds(sqh->qh->elink);
}
#endif
- if (reqh->timeout && !sc->sc_bus.use_polling)
- timeout(uhci_timeout, ii, MS_TO_TICKS(reqh->timeout));
+ if (reqh->timeout && !sc->sc_bus.use_polling) {
+ usb_timeout(uhci_timeout, ii,
+ MS_TO_TICKS(reqh->timeout), ii->timeout_handle);
+ }
splx(s);
return (USBD_NORMAL_COMPLETION);
@@ -1852,7 +1898,6 @@ usb_hub_descriptor_t uhci_hubd_piix = {
50, /* power on to power good */
0,
{ 0x00 }, /* both ports are removable */
- { 0x00 }, /* no ports can power down individually */
};
int
@@ -1907,7 +1952,7 @@ uhci_root_ctrl_transfer(reqh)
case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
/*
- * DEVICE_REMOTE_WAKEUP and ENDPOINT_STALL are no-ops
+ * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
* for the integrated root hub.
*/
break;
@@ -2211,7 +2256,7 @@ void
uhci_root_ctrl_close(pipe)
usbd_pipe_handle pipe;
{
- untimeout(uhci_timo, pipe->intrreqh);
+ usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
DPRINTF(("uhci_root_ctrl_close\n"));
}
@@ -2220,7 +2265,7 @@ void
uhci_root_intr_abort(reqh)
usbd_request_handle reqh;
{
- untimeout(uhci_timo, reqh);
+ usb_untimeout(uhci_timo, reqh, reqh->timo_handle);
}
/* Start a transfer on the root interrupt pipe */
@@ -2249,7 +2294,7 @@ uhci_root_intr_transfer(reqh)
return (r);
sc->sc_ival = MS_TO_TICKS(reqh->pipe->endpoint->edesc->bInterval);
- timeout(uhci_timo, reqh, sc->sc_ival);
+ usb_timeout(uhci_timo, reqh, sc->sc_ival, reqh->timo_handle);
return (USBD_IN_PROGRESS);
}
@@ -2258,6 +2303,6 @@ void
uhci_root_intr_close(pipe)
usbd_pipe_handle pipe;
{
- untimeout(uhci_timo, pipe->intrreqh);
+ usb_untimeout(uhci_timo, pipe->intrreqh, pipe->intrreqh->timo_handle);
DPRINTF(("uhci_root_intr_close\n"));
}
diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h
index 31d83385c60..aee1a3f6520 100644
--- a/sys/dev/usb/uhcivar.h
+++ b/sys/dev/usb/uhcivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: uhcivar.h,v 1.4 1998/11/25 22:32:05 augustss Exp $ */
+/* $NetBSD: uhcivar.h,v 1.5 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -68,6 +68,9 @@ typedef struct uhci_intr_info {
uhci_soft_td_t *stdstart;
uhci_soft_td_t *stdend;
LIST_ENTRY(uhci_intr_info) list;
+#if defined(__FreeBSD__)
+ struct callout_handle timeout_handle;
+#endif /* defined(__FreeBSD__) */
#ifdef DIAGNOSTIC
int isdone;
#endif
@@ -113,12 +116,17 @@ struct uhci_vframe {
typedef struct uhci_softc {
struct usbd_bus sc_bus; /* base device */
+#if defined(__NetBSD__)
void *sc_ih; /* interrupt vectoring */
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_dma_tag_t sc_dmatag; /* DMA tag */
/* XXX should keep track of all DMA memory */
+#elif defined(__FreeBSD__)
+ int sc_iobase;
+ int unit;
+#endif /* defined(__FreeBSD__) */
uhci_physaddr_t *sc_pframes;
struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT];
@@ -147,7 +155,9 @@ typedef struct uhci_softc {
#define UHCI_HAS_LOCK 1
#define UHCI_WANT_LOCK 2
+#if defined(__NetBSD__)
usb_dma_t *sc_mallocs;
+#endif
char sc_vendor[16];
} uhci_softc_t;
diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c
index 37782b673ca..9e50faa5aad 100644
--- a/sys/dev/usb/uhid.c
+++ b/sys/dev/usb/uhid.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uhid.c,v 1.11 1998/12/10 23:16:47 augustss Exp $ */
+/* $NetBSD: uhid.c,v 1.12 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,6 +42,15 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#include <sys/filio.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/device.h>
#include <sys/ioctl.h>
#include <sys/tty.h>
@@ -49,7 +58,6 @@
#include <sys/select.h>
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <sys/device.h>
#include <sys/poll.h>
#include <dev/usb/usb.h>
@@ -70,7 +78,7 @@ int uhiddebug = 0;
#endif
struct uhid_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -102,9 +110,6 @@ struct uhid_softc {
#define UHID_CHUNK 128 /* chunk size for read */
#define UHID_BSIZE 1020 /* buffer size */
-int uhid_match __P((struct device *, struct cfdata *, void *));
-void uhid_attach __P((struct device *, struct device *, void *));
-
int uhidopen __P((dev_t, int, int, struct proc *));
int uhidclose __P((dev_t, int, int, struct proc *p));
int uhidread __P((dev_t, struct uio *uio, int));
@@ -114,19 +119,11 @@ int uhidpoll __P((dev_t, int, struct proc *));
void uhid_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void uhid_disco __P((void *));
-extern struct cfdriver uhid_cd;
-
-struct cfattach uhid_ca = {
- sizeof(struct uhid_softc), uhid_match, uhid_attach
-};
+USB_DECLARE_DRIVER(uhid);
-int
-uhid_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(uhid)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(uhid, uaa);
usb_interface_descriptor_t *id;
if (!uaa->iface)
@@ -137,14 +134,9 @@ uhid_match(parent, match, aux)
return (UMATCH_IFACECLASS_GENERIC);
}
-void
-uhid_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(uhid)
{
- struct uhid_softc *sc = (struct uhid_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(uhid, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@@ -157,13 +149,15 @@ uhid_attach(parent, self, aux)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
+
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
printf("%s: could not read endpoint descriptor\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
DPRINTFN(10,("uhid_attach: bLength=%d bDescriptorType=%d "
@@ -177,9 +171,8 @@ uhid_attach(parent, self, aux)
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- printf("%s: unexpected endpoint\n",
- sc->sc_dev.dv_xname);
- return;
+ printf("%s: unexpected endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
sc->sc_ep_addr = ed->bEndpointAddress;
@@ -187,8 +180,8 @@ uhid_attach(parent, self, aux)
r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_USB);
if (r != USBD_NORMAL_COMPLETION) {
- printf("%s: no report descriptor\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: no report descriptor\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
(void)usbd_set_idle(iface, 0, 0);
@@ -199,8 +192,25 @@ uhid_attach(parent, self, aux)
sc->sc_repdesc = desc;
sc->sc_repdesc_size = size;
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+#if defined(__FreeBSD__)
+static int
+uhid_detach(device_t self)
+{
+ struct uhid_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
+}
+#endif
+
void
uhid_disco(p)
void *p;
@@ -250,15 +260,11 @@ uhidopen(dev, flag, mode, p)
int mode;
struct proc *p;
{
- int unit = UHIDUNIT(dev);
- struct uhid_softc *sc;
usbd_status r;
+ USB_GET_SC_OPEN(uhid, UHIDUNIT(dev), sc);
- if (unit >= uhid_cd.cd_ndevs)
- return ENXIO;
- sc = uhid_cd.cd_devs[unit];
if (!sc)
- return ENXIO;
+ return (ENXIO);
DPRINTF(("uhidopen: sc=%p, disco=%d\n", sc, sc->sc_disconnected));
@@ -266,10 +272,14 @@ uhidopen(dev, flag, mode, p)
return (EIO);
if (sc->sc_state & UHID_OPEN)
- return EBUSY;
+ return (EBUSY);
+#if defined(__NetBSD__)
if (clalloc(&sc->sc_q, UHID_BSIZE, 0) == -1)
- return ENOMEM;
+ return (ENOMEM);
+#elif defined(__FreeBSD__)
+ clist_alloc_cblocks(&sc->sc_q, UHID_BSIZE, 0);
+#endif
sc->sc_state |= UHID_OPEN;
sc->sc_state &= ~UHID_IMMED;
@@ -290,7 +300,7 @@ uhidopen(dev, flag, mode, p)
}
usbd_set_disco(sc->sc_intrpipe, uhid_disco, sc);
- return 0;
+ return (0);
}
int
@@ -300,7 +310,7 @@ uhidclose(dev, flag, mode, p)
int mode;
struct proc *p;
{
- struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -313,12 +323,16 @@ uhidclose(dev, flag, mode, p)
sc->sc_state &= ~UHID_OPEN;
+#if defined(__NetBSD__)
clfree(&sc->sc_q);
+#elif defined(__FreeBSD__)
+ clist_free_cblocks(&sc->sc_q);
+#endif
free(sc->sc_ibuf, M_USB);
free(sc->sc_obuf, M_USB);
- return 0;
+ return (0);
}
int
@@ -327,12 +341,12 @@ uhidread(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
int s;
int error = 0;
size_t length;
u_char buffer[UHID_CHUNK];
usbd_status r;
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -395,10 +409,10 @@ uhidwrite(dev, uio, flag)
struct uio *uio;
int flag;
{
- struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
int error;
int size;
usbd_status r;
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -435,11 +449,11 @@ uhidioctl(dev, cmd, addr, flag, p)
int flag;
struct proc *p;
{
- struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
struct usb_ctl_report_desc *rd;
struct usb_ctl_report *re;
int size, id;
usbd_status r;
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -465,6 +479,7 @@ uhidioctl(dev, cmd, addr, flag, p)
sc->sc_isize);
if (r != USBD_NORMAL_COMPLETION)
return (EOPNOTSUPP);
+
sc->sc_state |= UHID_IMMED;
} else
sc->sc_state &= ~UHID_IMMED;
@@ -506,9 +521,9 @@ uhidpoll(dev, events, p)
int events;
struct proc *p;
{
- struct uhid_softc *sc = uhid_cd.cd_devs[UHIDUNIT(dev)];
int revents = 0;
int s;
+ USB_GET_SC(uhid, UHIDUNIT(dev), sc);
if (sc->sc_disconnected)
return (EIO);
@@ -526,3 +541,7 @@ uhidpoll(dev, events, p)
splx(s);
return (revents);
}
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(uhid, usb, uhid_driver, uhid_devclass, usb_driver_load, 0);
+#endif
diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c
index 2c1c621c314..befb69176a3 100644
--- a/sys/dev/usb/uhub.c
+++ b/sys/dev/usb/uhub.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uhub.c,v 1.10 1998/12/09 19:24:28 drochner Exp $ */
+/* $NetBSD: uhub.c,v 1.11 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,14 +37,17 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/proc.h>
-#include <sys/device.h>
#include <dev/usb/usb.h>
@@ -63,44 +66,35 @@ extern char *usbd_error_strs[];
#endif
struct uhub_softc {
- struct device sc_dev; /* base device */
- usbd_device_handle sc_hub; /* USB device */
- usbd_pipe_handle sc_ipipe; /* interrupt pipe */
- u_int8_t sc_status[1]; /* XXX more ports */
- u_char sc_running;
+ bdevice sc_dev; /* base device */
+ usbd_device_handle sc_hub; /* USB device */
+ usbd_pipe_handle sc_ipipe; /* interrupt pipe */
+ u_int8_t sc_status[1]; /* XXX more ports */
+ u_char sc_running;
};
-int uhub_match __P((struct device *, struct cfdata *, void *));
-void uhub_attach __P((struct device *, struct device *, void *));
-
-usbd_status uhub_init_port __P((int, struct usbd_port *, usbd_device_handle));
-void uhub_disconnect __P((struct uhub_softc *sc, struct device *parent,
- struct usbd_port *up, int portno));
-usbd_status uhub_explore __P((struct device *parent, usbd_device_handle hub));
+usbd_status uhub_init_port __P((struct usbd_port *));
+void uhub_disconnect __P((struct usbd_port *up));
+usbd_status uhub_explore __P((usbd_device_handle hub));
void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
/*void uhub_disco __P((void *));*/
-extern struct cfdriver uhub_cd;
-
-struct cfattach uhub_ca = {
- sizeof(struct uhub_softc), uhub_match, uhub_attach
-};
+USB_DECLARE_DRIVER_NAME("usb", uhub);
+/* FIXME what does FreeBSD need? */
+#if defined(__NetBSD__)
struct cfattach uhub_uhub_ca = {
sizeof(struct uhub_softc), uhub_match, uhub_attach
};
+#endif
-int
-uhub_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(uhub)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(uhub, uaa);
usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
- DPRINTFN(1,("uhub_match, dd=%p\n", dd));
+ DPRINTFN(5,("uhub_match, dd=%p\n", dd));
/*
* The subclass for hubs seems to be 0 for some and 1 for others,
* so we just ignore the subclass.
@@ -110,40 +104,36 @@ uhub_match(parent, match, aux)
return (UMATCH_NONE);
}
-void
-uhub_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(uhub)
{
- struct uhub_softc *sc = (struct uhub_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(uhub, sc, uaa);
usbd_device_handle dev = uaa->device;
char devinfo[1024];
usbd_status r;
struct usbd_hub *hub;
usb_device_request_t req;
usb_hub_descriptor_t hubdesc;
- int port, nports;
+ int p, port, nports, nremov;
usbd_interface_handle iface;
usb_endpoint_descriptor_t *ed;
DPRINTFN(1,("uhub_attach\n"));
sc->sc_hub = dev;
usbd_devinfo(dev, 1, devinfo);
- printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfo);
+ USB_ATTACH_SETUP;
+ printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
r = usbd_set_config_index(dev, 0, 1);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("%s: configuration failed, error=%d(%s)\n",
- sc->sc_dev.dv_xname, r, usbd_error_strs[r]));
- return;
+ USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ USB_ATTACH_ERROR_RETURN;
}
if (dev->depth > USB_HUB_MAX_DEPTH) {
printf("%s: hub depth (%d) exceeded, hub ignored\n",
- sc->sc_dev.dv_xname, USB_HUB_MAX_DEPTH);
- return;
+ USBDEVNAME(sc->sc_dev), USB_HUB_MAX_DEPTH);
+ USB_ATTACH_ERROR_RETURN;
}
/* Get hub descriptor. */
@@ -153,21 +143,32 @@ uhub_attach(parent, self, aux)
USETW(req.wIndex, 0);
USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE);
DPRINTFN(1,("usb_init_hub: getting hub descriptor\n"));
- /* XXX not correct for hubs with >7 ports */
r = usbd_do_request(dev, &req, &hubdesc);
+ nports = hubdesc.bNbrPorts;
+ if (r == USBD_NORMAL_COMPLETION && nports > 7) {
+ USETW(req.wLength, USB_HUB_DESCRIPTOR_SIZE + (nports+1) / 8);
+ r = usbd_do_request(dev, &req, &hubdesc);
+ }
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("%s: getting hub descriptor failed, error=%d(%s)\n",
- sc->sc_dev.dv_xname, r, usbd_error_strs[r]));
- return;
+ USBDEVNAME(sc->sc_dev), r, usbd_error_strs[r]));
+ USB_ATTACH_ERROR_RETURN;
}
- nports = hubdesc.bNbrPorts;
+ for (nremov = 0, port = 1; port <= nports; port++)
+ if (!UHD_NOT_REMOV(&hubdesc, port))
+ nremov++;
+ printf("%s: %d port%s with %d removable, %s powered\n",
+ USBDEVNAME(sc->sc_dev), nports, nports != 1 ? "s" : "",
+ nremov, dev->self_powered ? "self" : "bus");
+
+
hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
M_USB, M_NOWAIT);
if (hub == 0)
- return;
+ USB_ATTACH_ERROR_RETURN;
dev->hub = hub;
- dev->hub->hubdata = sc;
+ dev->hub->hubsoftc = sc;
hub->explore = uhub_explore;
hub->hubdesc = hubdesc;
@@ -180,24 +181,24 @@ uhub_attach(parent, self, aux)
!dev->powersrc->parent->self_powered) {
printf("%s: bus powered hub connected to bus powered hub, "
"ignored\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
/* Set up interrupt pipe. */
r = usbd_device2interface_handle(dev, 0, &iface);
if (r != USBD_NORMAL_COMPLETION) {
- printf("%s: no interface handle\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: no interface handle\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (ed == 0) {
- printf("%s: no endpoint descriptor\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: no endpoint descriptor\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- printf("%s: bad interrupt endpoint\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: bad interrupt endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
r = usbd_open_pipe_intr(iface, ed->bEndpointAddress,USBD_SHORT_XFER_OK,
@@ -205,37 +206,65 @@ uhub_attach(parent, self, aux)
sizeof(sc->sc_status),
uhub_intr);
if (r != USBD_NORMAL_COMPLETION) {
- printf("%s: cannot open interrupt pipe\n",sc->sc_dev.dv_xname);
- return;
+ printf("%s: cannot open interrupt pipe\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
- for (port = 1; port <= nports; port++) {
- r = uhub_init_port(port, &hub->ports[port-1], dev);
+ /* Wait with power off for a while. */
+ usbd_delay_ms(dev->bus, USB_POWER_DOWN_TIME);
+
+ for (p = 0; p < nports; p++) {
+ struct usbd_port *up = &hub->ports[p];
+ up->device = 0;
+ up->parent = dev;
+ up->portno = p+1;
+ r = uhub_init_port(up);
if (r != USBD_NORMAL_COMPLETION)
printf("%s: init of port %d failed\n",
- sc->sc_dev.dv_xname, port);
+ USBDEVNAME(sc->sc_dev), up->portno);
}
sc->sc_running = 1;
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+#if defined(__FreeBSD__)
+static int
+uhub_detach(device_t self)
+{
+ struct uhub_softc *sc = device_get_softc(self);
+ int nports = sc->sc_hub->hub->hubdesc.bNbrPorts;
+ int p;
+
+ for (p = 0; p < nports; p++) {
+ struct usbd_port *up = &sc->sc_hub->hub->ports[p];
+ if (up->device)
+ uhub_disconnect(up);
+ }
+
+ free(sc->sc_hub->hub, M_USB);
+
+ return 0;
+}
+#endif
+
usbd_status
-uhub_init_port(port, uport, dev)
- int port;
- struct usbd_port *uport;
- usbd_device_handle dev;
+uhub_init_port(up)
+ struct usbd_port *up;
{
+ int port = up->portno;
+ usbd_device_handle dev = up->parent;
usbd_status r;
u_int16_t pstatus;
- uport->device = 0;
- uport->parent = dev;
- r = usbd_get_port_status(dev, port, &uport->status);
+ r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION)
- return r;
- pstatus = UGETW(uport->status.wPortStatus);
+ return (r);
+ pstatus = UGETW(up->status.wPortStatus);
DPRINTF(("usbd_init_port: adding hub port=%d status=0x%04x "
"change=0x%04x\n",
- port, pstatus, UGETW(uport->status.wPortChange)));
+ port, pstatus, UGETW(up->status.wPortChange)));
if ((pstatus & UPS_PORT_POWER) == 0) {
/* Port lacks power, turn it on */
#if 0
@@ -246,38 +275,37 @@ uhub_init_port(port, uport, dev)
r = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
if (r != USBD_NORMAL_COMPLETION)
return (r);
- r = usbd_get_port_status(dev, port, &uport->status);
+ r = usbd_get_port_status(dev, port, &up->status);
if (r != USBD_NORMAL_COMPLETION)
return (r);
DPRINTF(("usb_init_port: turn on port %d power status=0x%04x "
"change=0x%04x\n",
- port, UGETW(uport->status.wPortStatus),
- UGETW(uport->status.wPortChange)));
+ port, UGETW(up->status.wPortStatus),
+ UGETW(up->status.wPortChange)));
/* Wait for stable power. */
usbd_delay_ms(dev->bus, dev->hub->hubdesc.bPwrOn2PwrGood *
UHD_PWRON_FACTOR);
}
if (dev->self_powered)
/* Self powered hub, give ports maximum current. */
- uport->power = USB_MAX_POWER;
+ up->power = USB_MAX_POWER;
else
- uport->power = USB_MIN_POWER;
+ up->power = USB_MIN_POWER;
return (USBD_NORMAL_COMPLETION);
}
usbd_status
-uhub_explore(parent, dev)
- struct device *parent;
+uhub_explore(dev)
usbd_device_handle dev;
{
usb_hub_descriptor_t *hd = &dev->hub->hubdesc;
- struct uhub_softc *sc = dev->hub->hubdata;
+ struct uhub_softc *sc = dev->hub->hubsoftc;
struct usbd_port *up;
usbd_status r;
int port;
int change, status;
- DPRINTF(("uhub_explore dev=%p addr=%d\n", dev, dev->address));
+ DPRINTFN(10, ("uhub_explore dev=%p addr=%d\n", dev, dev->address));
if (!sc->sc_running)
return (USBD_NOT_STARTED);
@@ -299,10 +327,29 @@ uhub_explore(parent, dev)
change = UGETW(up->status.wPortChange);
DPRINTFN(5, ("uhub_explore: port %d status 0x%04x 0x%04x\n",
port, status, change));
- if (!(change & UPS_CURRENT_CONNECT_STATUS)) {
+ if (change & UPS_C_PORT_ENABLED) {
+ usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
+ if (status & UPS_PORT_ENABLED) {
+ printf("%s: illegal enable change, port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ } else {
+ /* Port error condition. */
+ if (up->restartcnt++ < USBD_RESTART_MAX) {
+ printf("%s: port error, restarting "
+ "port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ goto disco;
+ } else {
+ printf("%s: port error, giving up "
+ "port %d\n",
+ USBDEVNAME(sc->sc_dev), port);
+ }
+ }
+ }
+ if (!(change & UPS_C_CONNECT_STATUS)) {
/* No status change, just do recursive explore. */
if (up->device && up->device->hub)
- up->device->hub->explore(parent, up->device);
+ up->device->hub->explore(up->device);
continue;
}
DPRINTF(("uhub_explore: status change hub=%d port=%d\n",
@@ -316,12 +363,13 @@ uhub_explore(parent, dev)
* since a new unit may have been connected before we handle
* the disconnect.
*/
+ disco:
if (up->device) {
/* Disconnected */
DPRINTF(("uhub_explore: device %d disappeared "
"on port %d\n",
up->device->address, port));
- uhub_disconnect(sc, parent, up, port);
+ uhub_disconnect(up);
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
@@ -329,18 +377,18 @@ uhub_explore(parent, dev)
continue;
/* Connected */
+ up->restartcnt = 0;
+
/* Wait for maximum device power up time. */
usbd_delay_ms(dev->bus, USB_PORT_POWERUP_DELAY);
+
/* Reset port, which implies enabling it. */
if (usbd_reset_port(dev, port, &up->status) !=
USBD_NORMAL_COMPLETION)
continue;
- /* Wait for power to settle in device. */
- usbd_delay_ms(dev->bus, USB_POWER_SETTLE);
-
/* Get device info and set its address. */
- r = usbd_new_device((struct device *)sc, dev->bus,
+ r = usbd_new_device(&sc->sc_dev, dev->bus,
dev->depth + 1, status & UPS_LOW_SPEED,
port, up);
/* XXX retry a few times? */
@@ -362,37 +410,43 @@ uhub_explore(parent, dev)
* instead. */
printf("%s: device problem, disabling "
"port %d\n",
- parent->dv_xname, port);
+ USBDEVNAME(sc->sc_dev), port);
usbd_clear_port_feature(dev, port,
UHF_PORT_ENABLE);
+ /* Make sure we don't try to restart it. */
+ up->restartcnt = USBD_RESTART_MAX;
}
} else {
if (up->device->hub)
- up->device->hub->explore(parent, up->device);
+ up->device->hub->explore(up->device);
}
}
return (USBD_NORMAL_COMPLETION);
}
void
-uhub_disconnect(sc, parent, up, portno)
- struct uhub_softc *sc;
- struct device *parent;
+uhub_disconnect(up)
struct usbd_port *up;
- int portno;
{
usbd_device_handle dev = up->device;
usbd_pipe_handle p, n;
- usb_hub_descriptor_t *hd;
- struct usbd_port *spi;
- int i, port;
+ int i;
+ struct softc { bdevice sc_dev; }; /* all softc begin like this */
DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
- up, dev, portno));
+ up, dev, up->portno));
- printf("%s: device addr %d%s on hub addr %d, port %d disconnected\n",
- parent->dv_xname, dev->address, dev->hub ? " (hub)" : "",
- up->parent->address, portno);
+ printf("%s: at %s port %d (addr %d) disconnected\n",
+ USBDEVNAME(((struct softc *)dev->softc)->sc_dev),
+ USBDEVNAME(((struct uhub_softc *)up->parent->softc)->sc_dev),
+ up->portno, dev->address);
+
+ if (!dev->cdesc) {
+ /* Partially attached device, just drop it. */
+ dev->bus->devices[dev->address] = 0;
+ up->device = 0;
+ return;
+ }
for (i = 0; i < dev->cdesc->bNumInterface; i++) {
for (p = LIST_FIRST(&dev->ifaces[i].pipes); p; p = n) {
@@ -404,22 +458,29 @@ uhub_disconnect(sc, parent, up, portno)
}
}
+#if defined(__NetBSD__)
/* XXX Free all data structures and disable further I/O. */
-
-
if (dev->hub) {
+ struct usbd_port *rup;
+ int p, nports;
+
DPRINTFN(3,("usb_disconnect: hub, recursing\n"));
- hd = &dev->hub->hubdesc;
- for(port = 1; port <= hd->bNbrPorts; port++) {
- spi = &dev->hub->ports[port-1];
- if (spi->device)
- uhub_disconnect(sc, parent, spi, port);
+ nports = dev->hub->hubdesc.bNbrPorts;
+ for(p = 0; p < nports; p++) {
+ rup = &dev->hub->ports[p];
+ if (rup->device)
+ uhub_disconnect(rup);
}
}
dev->bus->devices[dev->address] = 0;
up->device = 0;
/* XXX free */
+#elif defined(__FreeBSD__)
+ /* XXX this doesn't work. */
+ /* clean up the kindergarten, get rid of the kids */
+ usbd_remove_device(dev, up);
+#endif
}
void
@@ -430,9 +491,13 @@ uhub_intr(reqh, addr, status)
{
struct uhub_softc *sc = addr;
- DPRINTFN(1,("uhub_intr: sc=%p\n", sc));
+ DPRINTFN(5,("uhub_intr: sc=%p\n", sc));
if (status != USBD_NORMAL_COMPLETION)
usbd_clear_endpoint_stall_async(sc->sc_ipipe);
else
usb_needs_explore(sc->sc_hub->bus);
}
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(uhub, usb, uhub_driver, uhub_devclass, usb_driver_load, 0);
+#endif
diff --git a/sys/dev/usb/ukbd.c b/sys/dev/usb/ukbd.c
index 1e0df9b8c5d..41317bd01b0 100644
--- a/sys/dev/usb/ukbd.c
+++ b/sys/dev/usb/ukbd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ukbd.c,v 1.15 1998/12/10 23:16:47 augustss Exp $ */
+/* $NetBSD: ukbd.c,v 1.16 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,19 +37,23 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <machine/clock.h>
+#endif
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/select.h>
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <sys/device.h>
#include <sys/poll.h>
#include <dev/usb/usb.h>
@@ -60,6 +64,7 @@
#include <dev/usb/usb_quirks.h>
#include <dev/usb/hid.h>
+#if defined(__NetBSD__)
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsksymdef.h>
@@ -68,6 +73,7 @@
#include "opt_pckbd_layout.h"
#include "opt_wsdisplay_compat.h"
+#endif
#ifdef USB_DEBUG
#define DPRINTF(x) if (ukbddebug) printf x
@@ -155,7 +161,7 @@ static u_int8_t ukbd_trtab[256] = {
#define KEY_ERROR 0x01
struct ukbd_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -167,10 +173,12 @@ struct ukbd_softc {
char sc_disconnected; /* device is gone */
int sc_leds;
+#if defined(__NetBSD__)
struct device *sc_wskbddev;
#ifdef WSDISPLAY_COMPAT_RAWKBD
int sc_rawkbd;
#endif
+#endif
int sc_polling;
int sc_pollchar;
@@ -180,22 +188,22 @@ struct ukbd_softc {
#define UKBD_CHUNK 128 /* chunk size for read */
#define UKBD_BSIZE 1020 /* buffer size */
-int ukbd_match __P((struct device *, struct cfdata *, void *));
-void ukbd_attach __P((struct device *, struct device *, void *));
-
void ukbd_cngetc __P((void *, u_int *, int *));
void ukbd_cnpollc __P((void *, int));
+#if defined(__NetBSD__)
const struct wskbd_consops ukbd_consops = {
ukbd_cngetc,
ukbd_cnpollc,
};
+#endif
void ukbd_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void ukbd_disco __P((void *));
int ukbd_enable __P((void *, int));
void ukbd_set_leds __P((void *, int));
+#if defined(__NetBSD__)
int ukbd_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
const struct wskbd_accessops ukbd_accessops = {
@@ -212,20 +220,13 @@ const struct wskbd_mapdata ukbd_keymapdata = {
KB_US,
#endif
};
+#endif
-extern struct cfdriver ukbd_cd;
+USB_DECLARE_DRIVER(ukbd);
-struct cfattach ukbd_ca = {
- sizeof(struct ukbd_softc), ukbd_match, ukbd_attach
-};
-
-int
-ukbd_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ukbd)
{
- struct usb_attach_arg *uaa = (struct usb_attach_arg *)aux;
+ USB_MATCH_START(ukbd, uaa);
usb_interface_descriptor_t *id;
/* Check that this is a keyboard that speaks the boot protocol. */
@@ -240,32 +241,33 @@ ukbd_match(parent, match, aux)
return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
-void
-ukbd_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ukbd)
{
- struct ukbd_softc *sc = (struct ukbd_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(ukbd, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
usbd_status r;
char devinfo[1024];
+#if defined(__NetBSD__)
struct wskbddev_attach_args a;
+#else
+ int i;
+#endif
sc->sc_disconnected = 1;
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
+
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
printf("%s: could not read endpoint descriptor\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
DPRINTFN(10,("ukbd_attach: bLength=%d bDescriptorType=%d "
@@ -280,8 +282,8 @@ ukbd_attach(parent, self, aux)
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
printf("%s: unexpected endpoint\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
if ((usbd_get_quirks(uaa->device)->uq_flags & UQ_NO_SET_PROTO) == 0) {
@@ -289,8 +291,8 @@ ukbd_attach(parent, self, aux)
DPRINTFN(5, ("ukbd_attach: protocol set\n"));
if (r != USBD_NORMAL_COMPLETION) {
printf("%s: set protocol failed\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
}
/* Ignore if SETIDLE fails since it is not crucial. */
@@ -299,6 +301,7 @@ ukbd_attach(parent, self, aux)
sc->sc_ep_addr = ed->bEndpointAddress;
sc->sc_disconnected = 0;
+#if defined(__NetBSD__)
a.console = 0; /* XXX */
a.keymap = &ukbd_keymapdata;
@@ -307,8 +310,45 @@ ukbd_attach(parent, self, aux)
a.accesscookie = sc;
sc->sc_wskbddev = config_found(self, &a, wskbddevprint);
+
+#elif defined(__FreeBSD__)
+ /* XXX why waste CPU in delay() ? */
+ /* It's alive! IT'S ALIVE! Do a little song and dance. */
+ ukbd_set_leds(sc, NUM_LOCK);
+ delay(15000);
+ ukbd_set_leds(sc, CAPS_LOCK);
+ delay(20000);
+ ukbd_set_leds(sc, SCROLL_LOCK);
+ delay(30000);
+ ukbd_set_leds(sc, CAPS_LOCK);
+ delay(50000);
+ ukbd_set_leds(sc, NUM_LOCK);
+
+ ukbd_enable(sc, 1);
+#endif
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+#if defined(__FreeBSD__)
+int
+ukbd_detach(device_t self)
+{
+ struct ukbd_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (sc->sc_enabled)
+ return (ENXIO);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+
+ return 0;
+}
+#endif
+
void
ukbd_disco(p)
void *p;
@@ -433,9 +473,20 @@ ukbd_intr(reqh, addr, status)
}
for (i = 0; i < nkeys; i++) {
c = ibuf[i];
+#if defined(__NetBSD__)
wskbd_input(sc->sc_wskbddev,
c & RELEASE ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN,
c & 0xff);
+#elif defined(__FreeBSD__)
+ printf("%c (%d) %s\n", ((c&0xff) < 32 || (c&0xff) > 126? '.':(c&0xff)), c,
+ (c&RELEASE? "released":"pressed"));
+ if (ud->modifiers)
+ printf("0x%04x\n", ud->modifiers);
+ for (i = 0; i < NKEYCODE; i++)
+ if (ud->keycode[i])
+ printf("%d ", ud->keycode[i]);
+ printf("\n");
+#endif
}
}
@@ -450,6 +501,7 @@ ukbd_set_leds(v, leds)
DPRINTF(("ukbd_set_leds: sc=%p leds=%d\n", sc, leds));
sc->sc_leds = leds;
+#if defined(__NetBSD__)
res = 0;
if (leds & WSKBD_LED_SCROLL)
res |= SCROLL_LOCK;
@@ -457,9 +509,13 @@ ukbd_set_leds(v, leds)
res |= NUM_LOCK;
if (leds & WSKBD_LED_CAPS)
res |= CAPS_LOCK;
+#elif defined(__FreeBSD__)
+ res = leds;
+#endif
usbd_set_report_async(sc->sc_iface, UHID_OUTPUT_REPORT, 0, &res, 1);
}
+#if defined(__NetBSD__)
int
ukbd_ioctl(v, cmd, data, flag, p)
void *v;
@@ -526,3 +582,8 @@ ukbd_cnpollc(v, on)
usbd_set_polling(sc->sc_iface, on);
}
+#endif
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(ukbd, usb, ukbd_driver, ukbd_devclass, usb_driver_load, 0);
+#endif
diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c
index aa0ab11bcf4..23dfe9ab5b7 100644
--- a/sys/dev/usb/ulpt.c
+++ b/sys/dev/usb/ulpt.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ulpt.c,v 1.7 1998/12/09 00:18:11 augustss Exp $ */
+/* $NetBSD: ulpt.c,v 1.8 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -40,17 +40,23 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
-#include <sys/user.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#if defined(__NetBSD__)
+#include <sys/device.h>
#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/ioccom.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/uio.h>
-#include <sys/device.h>
#include <sys/conf.h>
#include <sys/syslog.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -81,7 +87,7 @@ int ulptdebug = 0;
#define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NOPAPER)
struct ulpt_softc {
- struct device sc_dev;
+ bdevice sc_dev;
usbd_device_handle sc_udev; /* device */
usbd_interface_handle sc_iface; /* interface */
int sc_ifaceno;
@@ -97,9 +103,6 @@ struct ulpt_softc {
u_char sc_laststatus;
};
-int ulpt_match __P((struct device *, struct cfdata *, void *));
-void ulpt_attach __P((struct device *, struct device *, void *));
-
int ulptopen __P((dev_t, int, int, struct proc *));
int ulptclose __P((dev_t, int, int, struct proc *p));
int ulptwrite __P((dev_t, struct uio *uio, int));
@@ -110,24 +113,14 @@ int ulpt_status __P((struct ulpt_softc *));
void ulpt_reset __P((struct ulpt_softc *));
int ulpt_statusmsg __P((u_char, struct ulpt_softc *));
-extern struct cfdriver ulpt_cd;
-
#define ULPTUNIT(s) (minor(s) & 0x1f)
#define ULPTFLAGS(s) (minor(s) & 0xe0)
-extern struct cfdriver ulpt_cd;
+USB_DECLARE_DRIVER(ulpt);
-struct cfattach ulpt_ca = {
- sizeof(struct ulpt_softc), ulpt_match, ulpt_attach
-};
-
-int
-ulpt_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(ulpt)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(ulpt, uaa);
usb_interface_descriptor_t *id;
DPRINTFN(10,("ulpt_match\n"));
@@ -143,14 +136,9 @@ ulpt_match(parent, match, aux)
return (UMATCH_NONE);
}
-void
-ulpt_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ulpt)
{
- struct ulpt_softc *sc = (struct ulpt_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(ulpt, sc, uaa);
usbd_device_handle dev = uaa->device;
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface);
@@ -162,9 +150,10 @@ ulpt_attach(parent, self, aux)
usb_endpoint_descriptor_t *ed;
usbd_status r;
- DPRINTFN(2,("ulpt_attach: sc=%p\n", sc));
+ DPRINTFN(10,("ulpt_attach: sc=%p\n", sc));
usbd_devinfo(dev, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
/* Figure out which endpoint is the bulk out endpoint. */
@@ -182,12 +171,12 @@ ulpt_attach(parent, self, aux)
goto nobulk;
}
sc->sc_bulk = ed->bEndpointAddress;
- DPRINTFN(1, ("ulpt_attach: bulk=%d\n", sc->sc_bulk));
+ DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_bulk));
sc->sc_iface = iface;
r = usbd_interface2device_handle(iface, &sc->sc_udev);
if (r != USBD_NORMAL_COMPLETION)
- return;
+ USB_ATTACH_ERROR_RETURN;
sc->sc_ifaceno = id->bInterfaceNumber;
#if 0
@@ -206,17 +195,17 @@ is unknown. usbd_do_request() returns error on a short transfer.
/* devinfo now contains an IEEE-1284 device ID */
idstr = devinfo+2;
idstr[len] = 0;
- printf("%s: device id <%s>\n", sc->sc_dev.dv_xname, idstr);
+ printf("%s: device id <%s>\n", USBDEVNAME(sc->sc_dev), idstr);
} else {
- printf("%s: cannot get device id\n", sc->sc_dev.dv_xname);
+ printf("%s: cannot get device id\n", USBDEVNAME(sc->sc_dev));
}
#endif
- return;
+ USB_ATTACH_SUCCESS_RETURN;
nobulk:
- printf("%s: could not find bulk endpoint\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: could not find bulk endpoint\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
int
@@ -265,15 +254,11 @@ ulptopen(dev, flag, mode, p)
int mode;
struct proc *p;
{
- int unit = ULPTUNIT(dev);
u_char flags = ULPTFLAGS(dev);
- struct ulpt_softc *sc;
usbd_status r;
int spin, error;
+ USB_GET_SC_OPEN(ulpt, ULPTUNIT(dev), sc);
- if (unit >= ulpt_cd.cd_ndevs)
- return ENXIO;
- sc = ulpt_cd.cd_devs[unit];
if (!sc || !sc->sc_iface)
return ENXIO;
@@ -325,11 +310,11 @@ ulpt_statusmsg(status, sc)
sc->sc_laststatus = status;
if (new & LPS_SELECT)
- log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
+ log(LOG_NOTICE, "%s: offline\n", USBDEVNAME(sc->sc_dev));
else if (new & LPS_NOPAPER)
- log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
+ log(LOG_NOTICE, "%s: out of paper\n", USBDEVNAME(sc->sc_dev));
else if (new & LPS_NERR)
- log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
+ log(LOG_NOTICE, "%s: output error\n", USBDEVNAME(sc->sc_dev));
return status;
}
@@ -341,8 +326,7 @@ ulptclose(dev, flag, mode, p)
int mode;
struct proc *p;
{
- int unit = ULPTUNIT(dev);
- struct ulpt_softc *sc = ulpt_cd.cd_devs[unit];
+ USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
usbd_close_pipe(sc->sc_bulkpipe);
@@ -358,12 +342,12 @@ ulptwrite(dev, uio, flags)
struct uio *uio;
int flags;
{
- struct ulpt_softc *sc = ulpt_cd.cd_devs[ULPTUNIT(dev)];
size_t n;
int error = 0;
char buf[ULPT_BSIZE];
usbd_request_handle reqh;
usbd_status r;
+ USB_GET_SC(ulpt, ULPTUNIT(dev), sc);
DPRINTF(("ulptwrite\n"));
reqh = usbd_alloc_request();
@@ -411,3 +395,20 @@ ulptioctl(dev, cmd, data, flag, p)
return error;
}
+
+#if defined(__FreeBSD__)
+static int
+ulpt_detach(device_t self)
+{
+ struct ulpt_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ return 0;
+}
+
+DRIVER_MODULE(ulpt, usb, ulpt_driver, ulpt_devclass, usb_driver_load, 0);
+#endif
diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c
index 5ef2707dfe2..63c35d08798 100644
--- a/sys/dev/usb/umodem.c
+++ b/sys/dev/usb/umodem.c
@@ -1,4 +1,4 @@
-/* $NetBSD: umodem.c,v 1.2 1998/12/09 00:18:11 augustss Exp $ */
+/* $NetBSD: umodem.c,v 1.3 1998/12/26 12:53:02 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,13 +37,19 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#include <sys/conf.h>
+#endif
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/select.h>
@@ -56,6 +62,7 @@
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
@@ -71,35 +78,25 @@ int umodemdebug = 0;
#endif
struct umodem_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
};
-int umodem_match __P((struct device *, struct cfdata *, void *));
-void umodem_attach __P((struct device *, struct device *, void *));
-
void umodem_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void umodem_disco __P((void *));
-extern struct cfdriver umodem_cd;
-
-struct cfattach umodem_ca = {
- sizeof(struct umodem_softc), umodem_match, umodem_attach
-};
+USB_DECLARE_DRIVER(umodem);
-int
-umodem_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_MATCH(umodem)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(umodem, uaa);
+
usb_interface_descriptor_t *id;
if (!uaa->iface)
return (UMATCH_NONE);
id = usbd_get_interface_descriptor(uaa->iface);
- if (id &&
+ if (!id ||
id->bInterfaceClass != UCLASS_CDC ||
id->bInterfaceSubClass != USUBCLASS_ABSTRACT_CONTROL_MODEL ||
id->bInterfaceProtocol != UPROTO_CDC_AT)
@@ -107,14 +104,9 @@ umodem_match(parent, match, aux)
return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
}
-void
-umodem_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(umodem)
{
- struct umodem_softc *sc = (struct umodem_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(umodem, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
char devinfo[1024];
@@ -122,6 +114,30 @@ umodem_attach(parent, self, aux)
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+
+#if defined(__FreeBSD__)
+static int
+umodem_detach(device_t self)
+{
+ struct umodem_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+}
+
+ return 0;
+}
+#endif
+
+#if defined(__FreeBSD__)
+DRIVER_MODULE(umodem, usb, umodem_driver, umodem_devclass, usb_driver_load, 0);
+#endif
+
diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c
index e336b20d1d3..fc4f48ea528 100644
--- a/sys/dev/usb/ums.c
+++ b/sys/dev/usb/ums.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ums.c,v 1.15 1998/12/10 23:16:47 augustss Exp $ */
+/* $NetBSD: ums.c,v 1.16 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,32 +37,42 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#include <sys/conf.h>
+#endif
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/select.h>
#include <sys/proc.h>
#include <sys/vnode.h>
-#include <sys/device.h>
#include <sys/poll.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
#include <dev/usb/hid.h>
+#if defined(__NetBSD__)
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsmousevar.h>
+#elif defined(__FreeBSD__)
+#include <machine/mouse.h>
+#endif
#ifdef USB_DEBUG
#define DPRINTF(x) if (umsdebug) printf x
@@ -73,13 +83,17 @@ int umsdebug = 0;
#define DPRINTFN(n,x)
#endif
-#define PS2LBUTMASK 0x01
-#define PS2RBUTMASK 0x02
-#define PS2MBUTMASK 0x04
+#define UMSUNIT(s) (minor(s)&0x1f)
+
+#define PS2LBUTMASK x01
+#define PS2RBUTMASK x02
+#define PS2MBUTMASK x04
#define PS2BUTMASK 0x0f
+#define QUEUE_BUFSIZE 240 /* MUST be divisible by 3 _and_ 4 */
+
struct ums_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_interface_handle sc_iface; /* interface */
usbd_pipe_handle sc_intrpipe; /* interrupt pipe */
int sc_ep_addr;
@@ -87,28 +101,45 @@ struct ums_softc {
u_char *sc_ibuf;
u_int8_t sc_iid;
int sc_isize;
- struct hid_location sc_loc_x, sc_loc_y, sc_loc_z,
- sc_loc_btn1, sc_loc_btn2, sc_loc_btn3;
+ struct hid_location sc_loc_x, sc_loc_y, sc_loc_z;
+ struct hid_location *sc_loc_btn;
- u_char sc_buttons; /* mouse button status */
+ int sc_enabled;
int sc_disconnected; /* device is gone */
- int sc_enabled;
+ int flags; /* device configuration */
+#define UMS_Z 0x01 /* z direction available */
+ int nbuttons;
+
+#if defined(__NetBSD__)
+ u_char sc_buttons; /* mouse button status */
struct device *sc_wsmousedev;
+#elif defined(__FreeBSD__)
+ u_char qbuf[QUEUE_BUFSIZE];
+ u_char dummy[100]; /* just for safety and for now */
+ int qcount, qhead, qtail;
+ mousehw_t hw;
+ mousemode_t mode;
+ mousestatus_t status;
+
+ int state;
+# define UMS_ASLEEP 0x01 /* readFromDevice is waiting */
+# define UMS_SELECT 0x02 /* select is waiting */
+ struct selinfo rsel; /* process waiting in select */
+#endif
};
#define MOUSE_FLAGS_MASK (HIO_CONST|HIO_RELATIVE)
#define MOUSE_FLAGS (HIO_RELATIVE)
-int ums_match __P((struct device *, struct cfdata *, void *));
-void ums_attach __P((struct device *, struct device *, void *));
-
void ums_intr __P((usbd_request_handle, usbd_private_handle, usbd_status));
void ums_disco __P((void *));
-int ums_enable __P((void *));
-int ums_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
-void ums_disable __P((void *));
+static int ums_enable __P((void *));
+static void ums_disable __P((void *));
+
+#if defined(__NetBSD__)
+static int ums_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
const struct wsmouse_accessops ums_accessops = {
ums_enable,
@@ -116,19 +147,28 @@ const struct wsmouse_accessops ums_accessops = {
ums_disable,
};
-extern struct cfdriver ums_cd;
+#elif defined(__FreeBSD__)
+static d_open_t ums_open;
+static d_close_t ums_close;
+static d_read_t ums_read;
+static d_ioctl_t ums_ioctl;
+static d_poll_t ums_poll;
+
+#define UMS_CDEV_MAJOR 138 /* XXX NWH should be requested */
-struct cfattach ums_ca = {
- sizeof(struct ums_softc), ums_match, ums_attach
+static struct cdevsw ums_cdevsw = {
+ ums_open, ums_close, ums_read, nowrite,
+ ums_ioctl, nostop, nullreset, nodevtotty,
+ ums_poll, nommap,
+ NULL, "ums_", NULL, -1
};
+#endif
-int
-ums_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+USB_DECLARE_DRIVER(ums);
+
+USB_MATCH(ums)
{
- struct usb_attach_arg *uaa = aux;
+ USB_MATCH_START(ums, uaa);
usb_interface_descriptor_t *id;
int size, ret;
void *desc;
@@ -154,14 +194,9 @@ ums_match(parent, match, aux)
return (ret);
}
-void
-ums_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(ums)
{
- struct ums_softc *sc = (struct ums_softc *)self;
- struct usb_attach_arg *uaa = aux;
+ USB_ATTACH_START(ums, sc, uaa);
usbd_interface_handle iface = uaa->iface;
usb_interface_descriptor_t *id;
usb_endpoint_descriptor_t *ed;
@@ -171,18 +206,21 @@ ums_attach(parent, self, aux)
usbd_status r;
char devinfo[1024];
u_int32_t flags;
+ int i;
+ struct hid_location loc_btn;
sc->sc_disconnected = 1;
sc->sc_iface = iface;
id = usbd_get_interface_descriptor(iface);
usbd_devinfo(uaa->device, 0, devinfo);
- printf("\n%s: %s, iclass %d/%d\n", sc->sc_dev.dv_xname,
+ USB_ATTACH_SETUP;
+ printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (!ed) {
printf("%s: could not read endpoint descriptor\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
DPRINTFN(10,("ums_attach: bLength=%d bDescriptorType=%d "
@@ -197,76 +235,151 @@ ums_attach(parent, self, aux)
if ((ed->bEndpointAddress & UE_IN) != UE_IN ||
(ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
printf("%s: unexpected endpoint\n",
- sc->sc_dev.dv_xname);
- return;
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
r = usbd_alloc_report_desc(uaa->iface, &desc, &size, M_TEMP);
if (r != USBD_NORMAL_COMPLETION)
- return;
+ USB_ATTACH_ERROR_RETURN;
+
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
hid_input, &sc->sc_loc_x, &flags)) {
- printf("%s: mouse has no X report\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: mouse has no X report\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("%s: X report 0x%04x not supported\n",
+ USBDEVNAME(sc->sc_dev), flags);
+ USB_ATTACH_ERROR_RETURN;
}
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS)
- printf("%s: sorry, X report 0x%04x not supported yet\n",
- sc->sc_dev.dv_xname, flags);
if (!hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
hid_input, &sc->sc_loc_y, &flags)) {
- printf("%s: mouse has no Y report\n", sc->sc_dev.dv_xname);
- return;
+ printf("%s: mouse has no Y report\n", USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
+ }
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ printf("%s: Y report 0x%04x not supported\n",
+ USBDEVNAME(sc->sc_dev), flags);
+ USB_ATTACH_ERROR_RETURN;
}
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS)
- printf("%s: sorry, Y report 0x%04x not supported yet\n",
- sc->sc_dev.dv_xname, flags);
+ /* try to guess the Z activator: first check Z, then WHEEL */
if (hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Z),
hid_input, &sc->sc_loc_z, &flags) ||
hid_locate(desc, size, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
hid_input, &sc->sc_loc_z, &flags)) {
- if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS)
- /* Bad Z coord, ignore it */
- sc->sc_loc_z.size = 0;
+ if ((flags & MOUSE_FLAGS_MASK) != MOUSE_FLAGS) {
+ sc->sc_loc_z.size = 0; /* Bad Z coord, ignore it */
+ } else {
+ sc->flags |= UMS_Z;
+ }
}
- hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 1), /* left */
- hid_input, &sc->sc_loc_btn1, 0);
- hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 2), /* right */
- hid_input, &sc->sc_loc_btn2, 0);
- hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, 3), /* middle */
- hid_input, &sc->sc_loc_btn3, 0);
- DPRINTF(("ums_attach: sc=%p\n", sc));
- DPRINTF(("ums_attach: X %d/%d\n",
- sc->sc_loc_x.pos, sc->sc_loc_x.size));
- DPRINTF(("ums_attach: Y %d/%d\n",
- sc->sc_loc_x.pos, sc->sc_loc_x.size));
- DPRINTF(("ums_attach: Z %d/%d\n",
- sc->sc_loc_z.pos, sc->sc_loc_z.size));
- DPRINTF(("ums_attach: B1 %d/%d\n",
- sc->sc_loc_btn1.pos,sc->sc_loc_btn1.size));
- DPRINTF(("ums_attach: B2 %d/%d\n",
- sc->sc_loc_btn2.pos,sc->sc_loc_btn2.size));
- DPRINTF(("ums_attach: B3 %d/%d\n",
- sc->sc_loc_btn3.pos,sc->sc_loc_btn3.size));
+ /* figure out the number of buttons, 7 is an arbitrary limit */
+ for (i = 1; i <= 7; i++)
+ if (!hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
+ hid_input, &loc_btn, 0))
+ break;
+ sc->nbuttons = i - 1;
+ sc->sc_loc_btn = malloc(sizeof(struct hid_location)*sc->nbuttons,
+ M_USBDEV, M_NOWAIT);
+ if (!sc->sc_loc_btn)
+ USB_ATTACH_ERROR_RETURN;
+
+ printf("%s: %d buttons%s\n", USBDEVNAME(sc->sc_dev),
+ sc->nbuttons, (sc->flags & UMS_Z? " and Z dir." : ""));
+
+ for (i = 1; i <= sc->nbuttons; i++)
+ hid_locate(desc, size, HID_USAGE2(HUP_BUTTON, i),
+ hid_input, &sc->sc_loc_btn[i-1], 0);
sc->sc_isize = hid_report_size(desc, size, hid_input, &sc->sc_iid);
- DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid));
sc->sc_ibuf = malloc(sc->sc_isize, M_USB, M_NOWAIT);
- if (!sc->sc_ibuf)
- return;
+ if (!sc->sc_ibuf) {
+ free(sc->sc_loc_btn, M_USB);
+ USB_ATTACH_ERROR_RETURN;
+ }
sc->sc_ep_addr = ed->bEndpointAddress;
sc->sc_disconnected = 0;
free(desc, M_TEMP);
+#ifdef USB_DEBUG
+ DPRINTF(("ums_attach: sc=%p\n", sc));
+ DPRINTF(("ums_attach: X\t%d/%d\n",
+ sc->sc_loc_x.pos, sc->sc_loc_x.size));
+ DPRINTF(("ums_attach: Y\t%d/%d\n",
+ sc->sc_loc_x.pos, sc->sc_loc_x.size));
+ if (sc->flags & UMS_Z)
+ DPRINTF(("ums_attach: Z\t%d/%d\n",
+ sc->sc_loc_z.pos, sc->sc_loc_z.size));
+ for (i = 1; i <= sc->nbuttons; i++) {
+ DPRINTF(("ums_attach: B%d\t%d/%d\n",
+ i, sc->sc_loc_btn[i-1].pos,sc->sc_loc_btn[i-1].size));
+ }
+ DPRINTF(("ums_attach: size=%d, id=%d\n", sc->sc_isize, sc->sc_iid));
+#endif
+
+#if defined(__NetBSD__)
a.accessops = &ums_accessops;
a.accesscookie = sc;
sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
+#elif defined(__FreeBSD__)
+ sc->hw.buttons = 2; /* XXX hw&mode values are bogus */
+ sc->hw.iftype = MOUSE_IF_PS2;
+ sc->hw.type = MOUSE_MOUSE;
+ if (sc->flags & UMS_Z)
+ sc->hw.model = MOUSE_MODEL_INTELLI;
+ else
+ sc->hw.model = MOUSE_MODEL_GENERIC;
+ sc->hw.hwid = 0;
+ sc->mode.protocol = MOUSE_PROTO_PS2;
+ sc->mode.rate = -1;
+ sc->mode.resolution = MOUSE_RES_DEFAULT;
+ sc->mode.accelfactor = 1;
+ sc->mode.level = 0;
+ if (sc->flags & UMS_Z) {
+ sc->mode.packetsize = MOUSE_INTELLI_PACKETSIZE;
+ sc->mode.syncmask[0] = 0xc8;
+ } else {
+ sc->mode.packetsize = MOUSE_PS2_PACKETSIZE;
+ sc->mode.syncmask[0] = 0xc0;
+ }
+ sc->mode.syncmask[1] = 0;
+
+ sc->status.flags = 0;
+ sc->status.button = sc->status.obutton = 0;
+ sc->status.dx = sc->status.dy = sc->status.dz = 0;
+
+ sc->rsel.si_flags = 0;
+ sc->rsel.si_pid = 0;
+#endif
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+
+#if defined(__FreeBSD__)
+static int
+ums_detach(device_t self)
+{
+ struct ums_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+ free(sc->sc_loc_btn, M_USB);
+ free(sc->sc_ibuf, M_USB);
+
+ return 0;
+}
+#endif
+
void
ums_disco(p)
void *p;
@@ -287,7 +400,13 @@ ums_intr(reqh, addr, status)
struct ums_softc *sc = addr;
u_char *ibuf;
int dx, dy, dz;
- u_char buttons;
+ u_char buttons = 0;
+ int i;
+#if defined(__NetBSD__)
+#define UMS_BUT(i) ((i) == 1 || (i) == 2 ? 3 - (i) : i)
+#elif defined(__FreeBSD__)
+#define UMS_BUT(i) (i)
+#endif
DPRINTFN(5, ("ums_intr: sc=%p status=%d\n", sc, status));
DPRINTFN(5, ("ums_intr: data = %02x %02x %02x\n",
@@ -310,31 +429,100 @@ ums_intr(reqh, addr, status)
dx = hid_get_data(ibuf, &sc->sc_loc_x);
dy = -hid_get_data(ibuf, &sc->sc_loc_y);
dz = hid_get_data(ibuf, &sc->sc_loc_z);
- buttons = 0;
- if (hid_get_data(ibuf, &sc->sc_loc_btn1)) buttons |= 1 << 0;
- if (hid_get_data(ibuf, &sc->sc_loc_btn2)) buttons |= 1 << 2;
- if (hid_get_data(ibuf, &sc->sc_loc_btn3)) buttons |= 1 << 1;
-
+ /* NWH Why are you modifying the button assignments here?
+ * That's the purpose of a high level mouse driver
+ */
+ for (i = 0; i < sc->nbuttons; i++)
+ if (hid_get_data(ibuf, &sc->sc_loc_btn[i]))
+ buttons |= (1 << UMS_BUT(i));
+
+#if defined(__NetBSD__)
if (dx || dy || buttons != sc->sc_buttons) {
+ DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n",
+ dx, dy, dz, buttons));
sc->sc_buttons = buttons;
if (sc->sc_wsmousedev)
wsmouse_input(sc->sc_wsmousedev, buttons, dx, dy, dz);
+#elif defined(__FreeBSD__)
+ if (dx || dy || buttons != sc->status.button) {
+ DPRINTFN(10, ("ums_intr: x:%d y:%d z:%d buttons:0x%x\n",
+ dx, dy, dz, buttons));
+
+ sc->status.button = buttons;
+ sc->status.dx += dx;
+ sc->status.dy += dy;
+ sc->status.dz += dz;
+
+ /* Discard data in case of full buffer */
+ if (sc->qcount == sizeof(sc->qbuf)) {
+ DPRINTF(("Buffer full, discarded packet"));
+ return;
+ }
+
+ sc->qbuf[sc->qhead] = MOUSE_PS2_SYNC;
+ if (dx < 0)
+ sc->qbuf[sc->qhead] |= MOUSE_PS2_XNEG;
+ if (dx > 255 || dx < -255)
+ sc->qbuf[sc->qhead] |= MOUSE_PS2_XOVERFLOW;
+ if (dy < 0)
+ sc->qbuf[sc->qhead] |= MOUSE_PS2_YNEG;
+ if (dy > 255 || dy < -255)
+ sc->qbuf[sc->qhead] |= MOUSE_PS2_YOVERFLOW;
+ sc->qbuf[sc->qhead++] |= buttons;
+ sc->qbuf[sc->qhead++] = dx;
+ sc->qbuf[sc->qhead++] = dy;
+ sc->qcount += 3;
+ if (sc->flags & UMS_Z) {
+ sc->qbuf[sc->qhead++] = dz;
+ sc->qcount++;
+ }
+#ifdef USB_DEBUG
+ if (sc->qhead > sizeof(sc->qbuf))
+ DPRINTF(("Buffer overrun! %d %d\n",
+ sc->qhead, sizeof(sc->qbuf)));
+#endif
+ /* wrap round at end of buffer */
+ if (sc->qhead >= sizeof(sc->qbuf))
+ sc->qhead = 0;
+
+ /* someone waiting for data */
+ if (sc->state & UMS_ASLEEP)
+ wakeup(sc);
+ /* wake up any pending selects */
+ selwakeup(&sc->rsel);
+ sc->state &= ~UMS_SELECT;
+#endif
}
}
-/* wscons routines */
-int
+
+static int
ums_enable(v)
void *v;
{
struct ums_softc *sc = v;
+
usbd_status r;
if (sc->sc_enabled)
return EBUSY;
sc->sc_enabled = 1;
+#if defined(__NetBSD__)
sc->sc_buttons = 0;
+#elif defined(__FreeBSD__)
+ sc->qcount = 0;
+ sc->qhead = sc->qtail = 0;
+#ifdef USB_DEBUG
+ if (sizeof(sc->qbuf) % 4 || sizeof(sc->qbuf) % 3) {
+ DPRINTF(("Buffer size not divisible by 3 or 4\n"));
+ return ENXIO;
+ }
+#endif
+ sc->status.flags = 0;
+ sc->status.button = sc->status.obutton = 0;
+ sc->status.dx = sc->status.dy = sc->status.dz = 0;
+#endif
/* Set up interrupt pipe. */
r = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ep_addr,
@@ -350,7 +538,7 @@ ums_enable(v)
return (0);
}
-void
+static void
ums_disable(v)
void *v;
{
@@ -361,25 +549,188 @@ ums_disable(v)
usbd_close_pipe(sc->sc_intrpipe);
sc->sc_enabled = 0;
+
+#if defined(USBVERBOSE) && defined(__FreeBSD__)
+ if (sc->qcount != 0)
+ DPRINTF(("Discarded %d bytes in queue\n", sc->qcount));
+#endif
}
-int
+#if defined(__NetBSD__)
+static int
ums_ioctl(v, cmd, data, flag, p)
void *v;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
-{
-#if 0
- struct ums_softc *sc = v;
-#endif
+{
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(u_int *)data = WSMOUSE_TYPE_PS2;
return (0);
}
+
return (-1);
}
+#elif defined(__FreeBSD__)
+static int
+ums_open(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+
+ if (!sc) {
+ DPRINTF(("sc not found at open"));
+ return EINVAL;
+ }
+
+ return ums_enable(sc);
+}
+
+static int
+ums_close(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+
+ if (!sc) {
+ DPRINTF(("sc not found at close"));
+ return EINVAL;
+ }
+
+ if (sc->sc_enabled)
+ ums_disable(sc);
+ return 0;
+}
+
+static int
+ums_read(dev_t dev, struct uio *uio, int flag)
+{
+ struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+ int s;
+ char buf[sizeof(sc->qbuf)];
+ int l = 0;
+ int error;
+
+ if (!sc || !sc->sc_enabled) {
+ DPRINTF(("sc not found at read"));
+ return EINVAL;
+ }
+
+ s = splusb();
+ while (sc->qcount == 0 ) {
+ /* NWH XXX non blocking I/O ??
+ if (non blocking I/O ) {
+ splx(s);
+ return EWOULDBLOCK;
+ } else {
+ */
+ sc->state |= UMS_ASLEEP;
+ error = tsleep(sc, PZERO | PCATCH, "umsrea", 0);
+ sc->state &= ~UMS_ASLEEP;
+ if (error) {
+ splx(s);
+ return error;
+ }
+ }
+
+ while ((sc->qcount > 0) && (uio->uio_resid > 0)) {
+ l = (sc->qcount < uio->uio_resid? sc->qcount:uio->uio_resid);
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ if (l > sizeof(sc->qbuf) - sc->qtail) /* transfer till end of buf */
+ l = sizeof(sc->qbuf) - sc->qtail;
+
+ splx(s);
+ uiomove(&sc->qbuf[sc->qtail], l, uio);
+ s = splusb();
+
+ if ( sc->qcount - l < 0 ) {
+ DPRINTF(("qcount below 0, count=%d l=%d\n", sc->qcount, l));
+ sc->qcount = l;
+ }
+ sc->qcount -= l; /* remove the bytes from the buffer */
+ sc->qtail = (sc->qtail + l) % sizeof(sc->qbuf);
+ }
+ splx(s);
+
+ return 0;
+}
+
+static int
+ums_poll(dev_t dev, int events, struct proc *p)
+{
+ struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+ int revents = 0;
+ int s;
+
+ if (!sc) {
+ DPRINTF(("sc not found at poll"));
+ return 0; /* just to make sure */
+ }
+
+ s = splusb();
+ if (events & (POLLIN | POLLRDNORM))
+ if (sc->qcount) {
+ revents = events & (POLLIN | POLLRDNORM);
+ } else {
+ sc->state |= UMS_SELECT;
+ selrecord(p, &sc->rsel);
+ }
+ splx(s);
+
+ return revents;
+}
+
+int
+ums_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
+{
+ struct ums_softc *sc = devclass_get_softc(ums_devclass, UMSUNIT(dev));
+ int error = 0;
+ int s;
+
+ if (!sc) {
+ DPRINTF(("sc not found at ioctl"));
+ return ENOENT;
+ }
+
+ switch(cmd) {
+ case MOUSE_GETHWINFO:
+ *(mousehw_t *)addr = sc->hw;
+ break;
+ case MOUSE_GETMODE:
+ *(mousemode_t *)addr = sc->mode;
+ break;
+ case MOUSE_GETLEVEL:
+ *(int *)addr = sc->mode.level;
+ break;
+ case MOUSE_GETSTATUS: {
+ mousestatus_t *status = (mousestatus_t *) addr;
+
+ s = splusb();
+ *status = sc->status;
+ sc->status.obutton = sc->status.button;
+ sc->status.button = 0;
+ sc->status.dx = sc->status.dy = sc->status.dz = 0;
+ splx(s);
+
+ if (status->dx || status->dy || status->dz)
+ status->flags |= MOUSE_POSCHANGED;
+ if (status->button != status->obutton)
+ status->flags |= MOUSE_BUTTONSCHANGED;
+ break;
+ }
+ default:
+ error = ENOTTY;
+ }
+
+ return error;
+}
+#endif
+
+#if defined(__FreeBSD__)
+CDEV_DRIVER_MODULE(ums, usb, ums_driver, ums_devclass,
+ UMS_CDEV_MAJOR, ums_cdevsw, usb_driver_load, 0);
+#endif
+
diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c
index 3b7012b305b..9b6f4d423ef 100644
--- a/sys/dev/usb/usb.c
+++ b/sys/dev/usb/usb.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usb.c,v 1.6 1998/12/09 00:18:11 augustss Exp $ */
+/* $NetBSD: usb.c,v 1.7 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,19 +42,32 @@
* More USB specs at http://www.usb.org/developers/index.shtml
*/
-#include "opt_usbverbose.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#include <sys/uio.h>
+#include <sys/conf.h>
+#endif
#include <sys/poll.h>
#include <sys/proc.h>
#include <sys/select.h>
#include <dev/usb/usb.h>
+#if defined(__FreeBSD__)
+MALLOC_DEFINE(M_USB, "USB", "USB");
+MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
+
+#include "usb_if.h"
+#endif /* defined(__FreeBSD__) */
+
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdivar.h>
#include <dev/usb/usb_quirks.h>
@@ -73,7 +86,7 @@ int ohcidebug;
#define USBUNIT(dev) (minor(dev))
struct usb_softc {
- struct device sc_dev; /* base device */
+ bdevice sc_dev; /* base device */
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
char sc_running;
@@ -81,42 +94,56 @@ struct usb_softc {
struct selinfo sc_consel; /* waiting for connect change */
};
-int usb_match __P((struct device *, struct cfdata *, void *));
-void usb_attach __P((struct device *, struct device *, void *));
+#if defined(__NetBSD__)
int usbopen __P((dev_t, int, int, struct proc *));
int usbclose __P((dev_t, int, int, struct proc *));
int usbioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
int usbpoll __P((dev_t, int, struct proc *));
-usbd_status usb_discover __P((struct usb_softc *));
+#elif defined(__FreeBSD__)
+static device_probe_t usb_match;
+static device_attach_t usb_attach;
+static bus_print_child_t usb_print_child;
-extern struct cfdriver usb_cd;
+d_open_t usbopen;
+d_close_t usbclose;
+d_ioctl_t usbioctl;
+int usbpoll __P((dev_t, int, struct proc *));
-struct cfattach usb_ca = {
- sizeof(struct usb_softc), usb_match, usb_attach
+struct cdevsw usb_cdevsw = {
+ usbopen, usbclose, noread, nowrite,
+ usbioctl, nullstop, nullreset, nodevtotty,
+ usbpoll, nommap, nostrat,
+ "usb", NULL, -1
};
+#endif
-int
-usb_match(parent, match, aux)
- struct device *parent;
- struct cfdata *match;
- void *aux;
+usbd_status usb_discover __P((struct usb_softc *));
+
+USB_DECLARE_DRIVER_INIT(usb, DEVMETHOD(bus_print_child, usb_print_child));
+
+USB_MATCH(usb)
{
DPRINTF(("usbd_match\n"));
- return (1);
+ return (UMATCH_GENERIC);
}
-void
-usb_attach(parent, self, aux)
- struct device *parent;
- struct device *self;
- void *aux;
+USB_ATTACH(usb)
{
+#if defined(__NetBSD__)
struct usb_softc *sc = (struct usb_softc *)self;
+#elif defined(__FreeBSD__)
+ struct usb_softc *sc = device_get_softc(device);
+ void *aux = device_get_ivars(device);
+#endif
usbd_device_handle dev;
usbd_status r;
+#if defined(__NetBSD__)
printf("\n");
+#elif defined(__FreeBSD__)
+ sc->sc_dev = device;
+#endif
DPRINTF(("usbd_attach\n"));
usbd_init();
@@ -126,24 +153,28 @@ usb_attach(parent, self, aux)
sc->sc_bus->use_polling = 1;
sc->sc_port.power = USB_MAX_POWER;
r = usbd_new_device(&sc->sc_dev, sc->sc_bus, 0, 0, 0, &sc->sc_port);
+
if (r == USBD_NORMAL_COMPLETION) {
dev = sc->sc_port.device;
if (!dev->hub) {
sc->sc_running = 0;
- printf("%s: root device is not a hub\n",
- sc->sc_dev.dv_xname);
- return;
+ printf("%s: root device is not a hub\n",
+ USBDEVNAME(sc->sc_dev));
+ USB_ATTACH_ERROR_RETURN;
}
sc->sc_bus->root_hub = dev;
- dev->hub->explore(&sc->sc_dev, sc->sc_bus->root_hub);
+ dev->hub->explore(sc->sc_bus->root_hub);
} else {
printf("%s: root hub problem, error=%d\n",
- sc->sc_dev.dv_xname, r);
+ USBDEVNAME(sc->sc_dev), r);
sc->sc_running = 0;
}
sc->sc_bus->use_polling = 0;
+
+ USB_ATTACH_SUCCESS_RETURN;
}
+#if defined(__NetBSD__)
int
usbctlprint(aux, pnp)
void *aux;
@@ -156,18 +187,114 @@ usbctlprint(aux, pnp)
return (UNCONF);
}
+#elif defined(__FreeBSD__)
+static void
+usb_print_child(device_t parent, device_t child)
+{
+ struct usb_softc *sc = device_get_softc(child);
+
+ printf(" at %s%d", device_get_name(parent), device_get_unit(parent));
+
+ /* How do we get to the usbd_device_handle???
+ usbd_device_handle dev = invalidadosch;
+
+ printf(" addr %d", dev->addr);
+
+ if (bootverbose) {
+ if (dev->lowspeed)
+ printf(", lowspeed");
+ if (dev->self_powered)
+ printf(", self powered");
+ else
+ printf(", %dmA", dev->power);
+ printf(", config %d", dev->config);
+ }
+ */
+}
+
+/* Reconfigure all the USB busses in the system. */
+int
+usb_driver_load(module_t mod, int what, void *arg)
+{
+ /* subroutine is there but inactive at the moment
+ * the reconfiguration process has not been thought through yet.
+ */
+ devclass_t ugen_devclass = devclass_find("ugen");
+ device_t *devlist;
+ int devcount;
+ int error;
+
+ switch (what) {
+ case MOD_LOAD:
+ case MOD_UNLOAD:
+ if (!usb_devclass)
+ return 0; /* just ignore call */
+
+ if (ugen_devclass) {
+ /* detach devices from generic driver if possible
+ */
+ error = devclass_get_devices(ugen_devclass, &devlist,
+ &devcount);
+ if (!error)
+ for (devcount--; devcount >= 0; devcount--)
+ (void)DEVICE_DETACH(devlist[devcount]);
+ }
+
+ error = devclass_get_devices(usb_devclass, &devlist, &devcount);
+ if (error)
+ return 0; /* XXX maybe transient, or error? */
+
+ for (devcount--; devcount >= 0; devcount--)
+ USB_RECONFIGURE(devlist[devcount]);
+
+ free(devlist, M_TEMP);
+ return 0;
+ }
+
+ return 0; /* nothing to do by us */
+}
+
+/* Set the description of the device including a malloc and copy. */
+void
+usb_device_set_desc(device_t device, char *devinfo)
+{
+ size_t l;
+ char *desc;
+
+ if ( devinfo ) {
+ l = strlen(devinfo);
+ desc = malloc(l+1, M_USB, M_NOWAIT);
+ if (desc)
+ memcpy(desc, devinfo, l+1);
+ } else
+ desc = NULL;
+
+ device_set_desc(device, desc);
+}
+
+/*
+ * A static buffer is a loss if this routine is used from an interrupt,
+ * but it's not fatal.
+ */
+char *
+usb_devname(struct device *bdev)
+{
+ static char buf[20];
+
+ sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev));
+ return (buf);
+}
+
+#endif
+
int
usbopen(dev, flag, mode, p)
dev_t dev;
int flag, mode;
struct proc *p;
{
- int unit = USBUNIT(dev);
- struct usb_softc *sc;
+ USB_GET_SC_OPEN(usb, USBUNIT(dev), sc);
- if (unit >= usb_cd.cd_ndevs)
- return (ENXIO);
- sc = usb_cd.cd_devs[unit];
if (sc == 0 || !sc->sc_running)
return (ENXIO);
@@ -191,8 +318,7 @@ usbioctl(dev, cmd, data, flag, p)
int flag;
struct proc *p;
{
- int unit = USBUNIT(dev);
- struct usb_softc *sc = usb_cd.cd_devs[unit];
+ USB_GET_SC(usb, USBUNIT(dev), sc);
if (sc == 0 || !sc->sc_running)
return (ENXIO);
@@ -257,7 +383,6 @@ usbioctl(dev, cmd, data, flag, p)
if (ptr)
free(ptr, M_TEMP);
return (error);
- break;
}
case USB_DEVICEINFO:
@@ -291,9 +416,8 @@ usbpoll(dev, events, p)
int events;
struct proc *p;
{
- int unit = USBUNIT(dev);
- struct usb_softc *sc = usb_cd.cd_devs[unit];
int revents, s;
+ USB_GET_SC(usb, USBUNIT(dev), sc);
DPRINTFN(2, ("usbpoll: sc=%p events=0x%x\n", sc, events));
s = splusb();
@@ -353,7 +477,7 @@ usb_discover(sc)
sc->sc_bus->needs_explore = 0;
splx(s);
- sc->sc_bus->root_hub->hub->explore(&sc->sc_dev, sc->sc_bus->root_hub);
+ sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
s = splusb();
sc->sc_exploring = 0;
@@ -370,3 +494,21 @@ usb_needs_explore(bus)
bus->needs_explore = 1;
selwakeup(&bus->usbctl->sc_consel);
}
+
+#if defined(__FreeBSD__)
+int
+usb_detach(device_t self)
+{
+ struct usb_softc *sc = device_get_softc(self);
+ char *devinfo = (char *) device_get_desc(self);
+
+ if (devinfo) {
+ device_set_desc(self, NULL);
+ free(devinfo, M_USB);
+ }
+
+ return (0);
+}
+
+DRIVER_MODULE(usb, root, usb_driver, usb_devclass, 0, 0);
+#endif
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index 20bdf5a0748..b5546851699 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usb.h,v 1.7 1998/12/09 00:18:11 augustss Exp $ */
+/* $NetBSD: usb.h,v 1.8 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,7 +42,26 @@
#define _USB_H_
#include <sys/types.h>
+#if defined(__NetBSD__)
#include <sys/ioctl.h>
+#endif
+
+#if defined(__NetBSD__)
+#if defined(_KERNEL)
+#include <dev/usb/usb_port.h>
+#endif /* _KERNEL */
+
+#elif defined(__FreeBSD__)
+#include <sys/malloc.h>
+
+#if defined(KERNEL)
+MALLOC_DECLARE(M_USB);
+MALLOC_DECLARE(M_USBDEV);
+
+#include <dev/usb/usb_port.h>
+#endif /* KERNEL */
+#endif /* __FreeBSD__ */
+
#define USB_MAX_DEVICES 128
#define USB_START_ADDR 0
@@ -120,7 +139,7 @@ typedef struct {
#define UR_SYNCH_FRAME 0x0c
/* Feature numbers */
-#define UF_ENDPOINT_STALL 0
+#define UF_ENDPOINT_HALT 0
#define UF_DEVICE_REMOTE_WAKEUP 1
#define USB_MAX_IPACKET 8 /* maximum size of the initial packet */
@@ -229,7 +248,7 @@ typedef struct {
uByte bDescLength;
uByte bDescriptorType;
uByte bNbrPorts;
- uWord bHubCharacteristics;
+ uWord wHubCharacteristics;
#define UHD_PWR 0x03
#define UHD_PWR_GANGED 0x00
#define UHD_PWR_INDIVIDUAL 0x01
@@ -242,17 +261,20 @@ typedef struct {
uByte bPwrOn2PwrGood; /* delay in 2 ms units */
#define UHD_PWRON_FACTOR 2
uByte bHubContrCurrent;
- uByte DeviceRemovable[1];
- /* this is only correct with 1-7 ports on the hub */
- uByte PortPowerCtrlMask[3];
+ uByte DeviceRemovable[32]; /* max 255 ports */
+#define UHD_NOT_REMOV(desc, i) \
+ (((desc)->DeviceRemovable[(i)/8] >> ((i) % 8)) & 1)
+ /* deprecated uByte PortPowerCtrlMask[]; */
} usb_hub_descriptor_t;
-#define USB_HUB_DESCRIPTOR_SIZE 9
+#define USB_HUB_DESCRIPTOR_SIZE 8
typedef struct {
uWord wStatus;
/* Device status flags */
#define UDS_SELF_POWERED 0x0001
#define UDS_REMOTE_WAKEUP 0x0002
+/* Endpoint status flags */
+#define UES_HALT 0x0001
} usb_status_t;
typedef struct {
@@ -301,7 +323,7 @@ typedef struct {
#define UPROTO_PRINTER_UNI 1
#define UPROTO_PRINTER_BI 2
#define UCLASS_HUB 9
-#define USUBCLASS_HUB 1
+#define USUBCLASS_HUB 0
#define UCLASS_DATA 10
#define USB_HUB_MAX_DEPTH 5
@@ -312,9 +334,19 @@ typedef struct {
*/
#define USB_POWER_DOWN_TIME 1000 /* ms */
+#if 0
+/* These are the value from the spec. */
#define USB_PORT_RESET_DELAY 10 /* ms */
+#define USB_PORT_RESET_SETTLE 10 /* ms */
#define USB_PORT_POWERUP_DELAY 100 /* ms */
-#define USB_POWER_SETTLE 100 /* ms */
+#define USB_SET_ADDRESS_SETTLE 2 /* ms */
+#else
+/* Allow for bad device */
+#define USB_PORT_RESET_DELAY 10 /* ms */
+#define USB_PORT_RESET_RECOVERY 20 /* ms */
+#define USB_PORT_POWERUP_DELAY 200 /* ms */
+#define USB_SET_ADDRESS_SETTLE 10 /* ms */
+#endif
#define USB_MIN_POWER 100 /* mA */
#define USB_MAX_POWER 500 /* mA */
diff --git a/sys/dev/usb/usb_mem.h b/sys/dev/usb/usb_mem.h
index b09d5e22e94..092ddc4fb69 100644
--- a/sys/dev/usb/usb_mem.h
+++ b/sys/dev/usb/usb_mem.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_mem.h,v 1.2 1998/11/25 22:32:05 augustss Exp $ */
+/* $NetBSD: usb_mem.h,v 1.3 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,6 +37,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(__NetBSD__)
typedef struct usb_block_dma {
bus_dma_tag_t tag;
bus_dmamap_t map;
@@ -59,3 +60,34 @@ typedef struct {
usbd_status usb_allocmem __P((bus_dma_tag_t, size_t, size_t, usb_dma_t *));
void usb_freemem __P((bus_dma_tag_t, usb_dma_t *));
+
+#elif define(__FreeBSD__)
+
+/*
+ * FreeBSD does not have special functions for dma memory, so let's keep it
+ * simple for now.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/queue.h>
+#include <sys/proc.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pmap.h> /* for vtophys */
+
+
+
+typedef void * usb_dma_t;
+
+#define usb_allocmem(t,s,a,p) (*(p) = malloc(s, M_USB, M_NOWAIT), (*(p) == NULL? USBD_NOMEM: USBD_NORMAL_COMPLETION))
+#define usb_freemem(t,p) (free(*(p), M_USB))
+
+#define DMAADDR(dma) (vtophys(*(dma)))
+#define KERNADDR(dma) ((void *) *(dma))
+#endif
+
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
new file mode 100644
index 00000000000..ecb1ad17f34
--- /dev/null
+++ b/sys/dev/usb/usb_port.h
@@ -0,0 +1,180 @@
+/* Macro's to cope with the differences between NetBSD and FreeBSD
+ */
+
+/*
+ * NetBSD
+ */
+
+#if defined(__NetBSD__)
+#include "opt_usbverbose.h"
+
+#define USBDEVNAME(bdev) ((bdev).dv_xname)
+
+typedef struct device bdevice; /* base device */
+
+#define usb_timeout(f, d, t, h) timeout((f), (d), (t))
+#define usb_untimeout(f, d, h) untimeout((f), (d))
+
+#define USB_DECLARE_DRIVER_NAME_INIT(_1, dname, _2) \
+int __CONCAT(dname,_match) __P((struct device *, struct cfdata *, void *)); \
+void __CONCAT(dname,_attach) __P((struct device *, struct device *, void *)); \
+\
+extern struct cfdriver __CONCAT(dname,_cd); \
+\
+struct cfattach __CONCAT(dname,_ca) = { \
+ sizeof(struct __CONCAT(dname,_softc)), \
+ __CONCAT(dname,_match), \
+ __CONCAT(dname,_attach) \
+}
+
+#define USB_MATCH(dname) \
+int \
+__CONCAT(dname,_match)(parent, match, aux) \
+ struct device *parent; \
+ struct cfdata *match; \
+ void *aux;
+
+#define USB_MATCH_START(dname, uaa) \
+ struct usb_attach_arg *uaa = aux
+
+#define USB_ATTACH(dname) \
+void \
+__CONCAT(dname,_attach)(parent, self, aux) \
+ struct device *parent; \
+ struct device *self; \
+ void *aux;
+
+#define USB_ATTACH_START(dname, sc, uaa) \
+ struct __CONCAT(dname,_softc) *sc = (struct __CONCAT(dname,_softc) *)self; \
+ struct usb_attach_arg *uaa = aux
+
+/* Returns from attach */
+#define USB_ATTACH_ERROR_RETURN return
+#define USB_ATTACH_SUCCESS_RETURN return
+
+#define USB_ATTACH_SETUP printf("\n")
+
+#define USB_GET_SC_OPEN(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc; \
+ if (unit >= __CONCAT(dname,_cd).cd_ndevs) \
+ return (ENXIO); \
+ sc = __CONCAT(dname,_cd).cd_devs[unit]; \
+ if (!sc) \
+ return (ENXIO)
+
+#define USB_GET_SC(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = __CONCAT(dname,_cd).cd_devs[unit]
+
+#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \
+ ((dev)->softc = config_found_sm(parent, args, print, sub))
+
+#elif defined(__FreeBSD__)
+/*
+ * FreeBSD
+ */
+
+#include "opt_usb.h"
+char *usb_devname(struct device *);
+#define USBDEVNAME(bdev) usb_devname(&bdev)
+
+/* XXX Change this when FreeBSD has memset
+ */
+#define memset(d, v, s) \
+ do{ \
+ if ((v) == 0) \
+ bzero((d), (s)); \
+ else \
+ panic("Non zero filler for memset, cannot handle!"); \
+ } while (0)
+
+typedef device_t bdevice;
+
+/*
+ * To avoid race conditions we first initialise the struct
+ * before we use it. The timeout might happen between the
+ * setting of the timeout and the setting of timo_handle
+ */
+#define usb_timeout(f, d, t, h) \
+ (callout_handle_init(&(h)), (h) = timeout((f), (d), (t)))
+#define usb_untimeout(f, d, h) untimeout((f), (d), (h))
+
+#define USB_DECLARE_DRIVER_NAME_INIT(name, dname, init) \
+static device_probe_t __CONCAT(dname,_match); \
+static device_attach_t __CONCAT(dname,_attach); \
+static device_detach_t __CONCAT(dname,_detach); \
+\
+static devclass_t __CONCAT(dname,_devclass); \
+\
+static device_method_t __CONCAT(dname,_methods)[] = { \
+ DEVMETHOD(device_probe, __CONCAT(dname,_match)), \
+ DEVMETHOD(device_attach, __CONCAT(dname,_attach)), \
+ DEVMETHOD(device_detach, __CONCAT(dname,_detach)), \
+ init, \
+ {0,0} \
+}; \
+\
+static driver_t __CONCAT(dname,_driver) = { \
+ name, \
+ __CONCAT(dname,_methods), \
+ DRIVER_TYPE_MISC, \
+ sizeof(struct __CONCAT(dname,_softc)) \
+}
+
+#define USB_MATCH(dname) \
+static int \
+__CONCAT(dname,_match)(device_t device)
+
+#define USB_MATCH_START(dname, uaa) \
+ struct usb_attach_arg *uaa = device_get_ivars(device)
+
+#define USB_ATTACH(dname) \
+static int
+__CONCAT(dname,_attach)(device_t self)
+
+#define USB_ATTACH_START(dname, sc, uaa) \
+ struct __CONCAT(dname,_softc) *sc = device_get_softc(self); \
+ struct usb_attach_arg *uaa = device_get_ivars(self)
+
+/* Returns from attach */
+#define USB_ATTACH_ERROR_RETURN return ENXIO
+#define USB_ATTACH_SUCCESS_RETURN return 0
+
+#define USB_ATTACH_SETUP \
+ usb_device_set_desc(self, devinfo); \
+ sc->sc_dev = self
+
+#define USB_GET_SC_OPEN(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = \
+ devclass_get_softc(__CONCAT(dname,_devclass), unit);
+ if (!sc)
+ return (ENXIO)
+
+#define USB_GET_SC(dname, unit, sc) \
+ struct __CONCAT(dname,_softc) *sc = \
+ devclass_get_softc(__CONCAT(dname,_devclass), unit)
+
+#define USB_DO_ATTACH(dev, bdev, parent, args, print, sub) \
+ (device_probe_and_attach((bdev)) == 0 ? ((dev)->softc = (bdev)) : 0)
+
+/* conversion from one type of queue to the other */
+#define SIMPLEQ_REMOVE_HEAD STAILQ_REMOVE_HEAD_QUEUE
+#define SIMPLEQ_INSERT_HEAD STAILQ_INSERT_HEAD
+#define SIMPLEQ_INSERT_TAIL STAILQ_INSERT_TAIL
+#define SIMPLEQ_NEXT STAILQ_NEXT
+#define SIMPLEQ_FIRST STAILQ_FIRST
+#define SIMPLEQ_HEAD STAILQ_HEAD
+#define SIMPLEQ_INIT STAILQ_INIT
+#define SIMPLEQ_ENTRY STAILQ_ENTRY
+
+#endif /* __FreeBSD */
+
+#define NONE {0,0}
+
+#define USB_DECLARE_DRIVER_NAME(name, dname) \
+ USB_DECLARE_DRIVER_NAME_INIT(name, dname, NONE )
+#define USB_DECLARE_DRIVER_INIT(dname, init) \
+ USB_DECLARE_DRIVER_NAME_INIT(##dname, dname, init)
+#define USB_DECLARE_DRIVER(dname) \
+ USB_DECLARE_DRIVER_NAME_INIT(##dname, dname, NONE )
+
+#undef NONE
diff --git a/sys/dev/usb/usb_quirks.c b/sys/dev/usb/usb_quirks.c
index dad2ce0c827..3a84389a7b3 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.3 1998/12/02 22:57:08 augustss Exp $ */
+/* $NetBSD: usb_quirks.c,v 1.4 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -39,7 +39,6 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/device.h>
#include <sys/select.h>
#include <dev/usb/usb.h>
@@ -58,6 +57,7 @@ struct usbd_quirk_entry {
0x094, { UQ_SWAP_UNICODE}},
{ USB_VENDOR_UNIXTAR, USB_PRODUCT_UNIXTAR_UTUSB41, 0x100, { UQ_HUB_POWER }},
{ USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932, 0x100, { UQ_NO_STRINGS }},
+ { USB_VENDOR_ADS, USB_PRODUCT_ADS_ENET, 0x002, { UQ_NO_STRINGS }},
{ 0, 0, 0, { 0 } }
};
@@ -78,7 +78,7 @@ usbd_find_quirk(d)
#ifdef USB_DEBUG
{ extern int usbdebug;
if (usbdebug && t->quirks.uq_flags)
- printf("quirk %d/%d/%x: %d\n",
+ printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
UGETW(d->idVendor), UGETW(d->idProduct),
UGETW(d->bcdDevice), t->quirks.uq_flags);
}
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 9f0f6cd27a9..273ca31a367 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.17 1998/12/12 12:18:26 augustss Exp $ */
+/* $NetBSD: usb_subr.c,v 1.18 1998/12/26 12:53:03 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -41,7 +41,12 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#if defined(__NetBSD__)
#include <sys/device.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#endif
#include <sys/proc.h>
#include <sys/select.h>
@@ -53,8 +58,6 @@
#include <dev/usb/usbdevs.h>
#include <dev/usb/usb_quirks.h>
-#include "opt_usbverbose.h"
-
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
@@ -66,15 +69,17 @@ extern int usbdebug;
static usbd_status usbd_set_config __P((usbd_device_handle, int));
char *usbd_get_string __P((usbd_device_handle, int, char *));
-usbd_status usbd_get_desc __P((usbd_device_handle dev, int type,
- int index, int len, void *desc));
int usbd_getnewaddr __P((usbd_bus_handle bus));
int usbd_print __P((void *aux, const char *pnp));
+#if defined(__NetBSD__)
int usbd_submatch __P((struct device *, struct cfdata *cf, void *));
+#endif
usb_interface_descriptor_t *usbd_find_idesc __P((usb_config_descriptor_t *cd,
int ifaceidx, int altidx));
void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno));
void usbd_kill_pipe __P((usbd_pipe_handle));
+usbd_status usbd_probe_and_attach
+ __P((bdevice *parent, usbd_device_handle dev, int port, int addr));
#ifdef USBVERBOSE
typedef u_int16_t usb_vendor_id_t;
@@ -306,6 +311,9 @@ usbd_reset_port(dev, port, ps)
if (r != USBD_NORMAL_COMPLETION)
DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r));
#endif
+
+ /* Wait for the device to recover from reset. */
+ usbd_delay_ms(dev->bus, USB_PORT_RESET_RECOVERY);
return (r);
}
@@ -322,6 +330,10 @@ usbd_find_idesc(cd, ifaceidx, altidx)
for (curidx = lastno = -1; p < end; ) {
d = (usb_interface_descriptor_t *)p;
+ DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d "
+ "type=%d\n",
+ ifaceidx, curidx, altidx, curaidx,
+ d->bLength, d->bDescriptorType));
if (d->bLength == 0) /* bad descriptor */
break;
p += d->bLength;
@@ -387,7 +399,7 @@ usbd_fill_iface_data(dev, ifaceidx, altidx)
int endpt, nendpt;
usbd_status r;
- DPRINTFN(5,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
+ DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n",
ifaceidx, altidx));
ifc->device = dev;
ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx);
@@ -523,6 +535,12 @@ usbd_set_config_index(dev, index, msg)
r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
if (r != USBD_NORMAL_COMPLETION)
goto bad;
+ if (cdp->bDescriptorType != UDESC_CONFIG) {
+ DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
+ cdp->bDescriptorType));
+ r = USBD_INVAL;
+ goto bad;
+ }
selfpowered = 0;
if (cdp->bmAttributes & UC_SELF_POWERED) {
/* May be self powered. */
@@ -561,9 +579,9 @@ usbd_set_config_index(dev, index, msg)
if (power > dev->powersrc->power) {
/* XXX print nicer message. */
if (msg)
- printf("%s: device addr %d (config %d) exceeds "
- "power budget, %d mA > %d mA\n",
- dev->bus->bdev.dv_xname, dev->address,
+ printf("%s: device addr %d (config %d) exceeds power "
+ "budget, %d mA > %d mA\n",
+ USBDEVNAME(dev->bus->bdev), dev->address,
cdp->bConfigurationValue,
power, dev->powersrc->power);
r = USBD_NO_POWER;
@@ -572,6 +590,8 @@ usbd_set_config_index(dev, index, msg)
dev->power = power;
dev->self_powered = selfpowered;
+ DPRINTF(("usbd_set_config_index: set config %d\n",
+ cdp->bConfigurationValue));
r = usbd_set_config(dev, cdp->bConfigurationValue);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTF(("usbd_set_config_index: setting config=%d failed, "
@@ -659,14 +679,102 @@ int
usbd_getnewaddr(bus)
usbd_bus_handle bus;
{
- int i;
+ int addr;
- for (i = 1; i < USB_MAX_DEVICES; i++)
- if (bus->devices[i] == 0)
- return (i);
+ for (addr = 1; addr < USB_MAX_DEVICES; addr++)
+ if (bus->devices[addr] == 0)
+ return (addr);
return (-1);
}
+
+usbd_status
+usbd_probe_and_attach(parent, dev, port, addr)
+ bdevice *parent;
+ usbd_device_handle dev;
+ int port;
+ int addr;
+{
+ struct usb_attach_arg uaa;
+ usb_device_descriptor_t *dd = &dev->ddesc;
+ int r, found, i, confi;
+
+#if defined(__FreeBSD__)
+/* XXX isn't it bad to build &uaa into a value that has a lifetime
+ longer than this function call? */
+ bdevice bdev;
+ bdev = device_add_child(*parent, NULL, -1, &uaa);
+ if (bdev) {
+ printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
+ return (USBD_INVAL);
+ }
+#endif
+
+ uaa.device = dev;
+ uaa.iface = 0;
+ uaa.usegeneric = 0;
+ uaa.port = port;
+ uaa.configno = UHUB_UNK_CONFIGURATION;
+ uaa.ifaceno = UHUB_UNK_INTERFACE;
+
+ /* First try with device specific drivers. */
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
+ return (USBD_NORMAL_COMPLETION);
+
+ DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
+
+ /* Next try with interface drivers. */
+ for (confi = 0; confi < dd->bNumConfigurations; confi++) {
+ DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
+ confi));
+ r = usbd_set_config_index(dev, confi, 1);
+ if (r != USBD_NORMAL_COMPLETION) {
+#ifdef USB_DEBUG
+ DPRINTF(("%s: port %d, set config at addr %d failed, "
+ "error=%d(%s)\n", USBDEVNAME(*parent), port,
+ addr, r, usbd_error_strs[r]));
+#else
+ printf("%s: port %d, set config at addr %d failed\n",
+ USBDEVNAME(*parent), port, addr);
+#endif
+ return (r);
+ }
+ uaa.configno = confi;
+ for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
+ uaa.iface = &dev->ifaces[i];
+ uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,
+ usbd_submatch))
+ found++;
+ }
+ if (found != 0)
+ return (USBD_NORMAL_COMPLETION);
+ }
+ /* No interfaces were attach in any of the configurations. */
+ if (dd->bNumConfigurations > 0)
+ usbd_set_config_index(dev, 0, 0);
+
+ DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
+
+ /* Finally try the generic driver. */
+ uaa.iface = 0;
+ uaa.usegeneric = 1;
+ uaa.configno = UHUB_UNK_CONFIGURATION;
+ uaa.ifaceno = UHUB_UNK_INTERFACE;
+ if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch))
+ return (USBD_NORMAL_COMPLETION);
+
+ /*
+ * The generic attach failed, but leave the device as it is.
+ * We just did not find any drivers, that's all. The device is
+ * fully operational and not harming anyone.
+ */
+ DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
+ return (USBD_NORMAL_COMPLETION);
+}
+
+
+
/*
* Called when a new device has been put in the powered state,
* but not yet in the addressed state.
@@ -675,7 +783,7 @@ usbd_getnewaddr(bus)
*/
usbd_status
usbd_new_device(parent, bus, depth, lowspeed, port, up)
- struct device *parent;
+ bdevice *parent;
usbd_bus_handle bus;
int depth;
int lowspeed;
@@ -683,18 +791,17 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
struct usbd_port *up;
{
usbd_device_handle dev;
- usb_device_descriptor_t *d;
+ usb_device_descriptor_t *dd;
usbd_status r;
- struct usb_attach_arg uaa;
int addr;
- int found, i, confi;
+ int i;
DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
bus, depth, lowspeed));
addr = usbd_getnewaddr(bus);
if (addr < 0) {
- printf("%s: No free USB addresses, new device ignored.\n",
- bus->bdev.dv_xname);
+ printf("%s: No free USB addresses, new device ignored.\n",
+ USBDEVNAME(bus->bdev));
return (USBD_NO_ADDR);
}
@@ -708,8 +815,6 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
/* Set up default endpoint handle. */
dev->def_ep.edesc = &dev->def_ep_desc;
dev->def_ep.state = USBD_ENDPOINT_ACTIVE;
- dev->def_ep.refcnt = 0;
- dev->def_ep.toggle = 0; /* XXX */
/* Set up default endpoint descriptor. */
dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
@@ -729,15 +834,17 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
/* Establish the the default pipe. */
r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe);
- if (r != USBD_NORMAL_COMPLETION)
- goto bad1;
+ if (r != USBD_NORMAL_COMPLETION) {
+ usbd_remove_device(dev, up);
+ return r;
+ }
up->device = dev;
- d = &dev->ddesc;
+ dd = &dev->ddesc;
/* Try a few times in case the device is slow (i.e. outside specs.) */
for (i = 0; i < 5; i++) {
/* Get the first 8 bytes of the device descriptor. */
- r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, d);
+ r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (r == USBD_NORMAL_COMPLETION)
break;
usbd_delay_ms(dev->bus, 200);
@@ -746,34 +853,48 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
"failed\n",
addr));
- goto bad;
+ usbd_remove_device(dev, up);
+ return (r);
+ }
+
+ if (dd->bDescriptorType != UDESC_DEVICE) {
+ /* Illegal device descriptor */
+ DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n",
+ dd->bDescriptorType));
+ usbd_remove_device(dev, up);
+ return (USBD_INVAL);
}
DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, "
"subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",
- addr, UGETW(d->bcdUSB), d->bDeviceClass, d->bDeviceSubClass,
- d->bDeviceProtocol, d->bMaxPacketSize, dev->lowspeed));
+ addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass,
+ dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed));
- USETW(dev->def_ep_desc.wMaxPacketSize, d->bMaxPacketSize);
+ USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
/* Get the full device descriptor. */
- r = usbd_get_device_desc(dev, d);
+ r = usbd_get_device_desc(dev, dd);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
"failed\n", addr));
- goto bad;
+ usbd_remove_device(dev, up);
+ return (r);
}
/* Figure out what's wrong with this device. */
- dev->quirks = usbd_find_quirk(d);
+ dev->quirks = usbd_find_quirk(dd);
/* Set the address */
r = usbd_set_address(dev, addr);
if (r != USBD_NORMAL_COMPLETION) {
DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr));
r = USBD_SET_ADDR_FAILED;
- goto bad;
+ usbd_remove_device(dev, up);
+ return (r);
}
+ /* Allow device time to set new address */
+ usbd_delay_ms(dev->bus, USB_SET_ADDRESS_SETTLE);
+
dev->address = addr; /* New device address now */
dev->state = USBD_DEVICE_ADDRESSED;
bus->devices[addr] = dev;
@@ -785,72 +906,44 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",
addr, dev, parent));
- uaa.device = dev;
- uaa.iface = 0;
- uaa.usegeneric = 0;
- uaa.port = port;
- uaa.configno = UHUB_UNK_CONFIGURATION;
- uaa.ifaceno = UHUB_UNK_INTERFACE;
- /* First try with device specific drivers. */
- if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
- return (USBD_NORMAL_COMPLETION);
-
- DPRINTF(("usbd_new_device: no device driver found\n"));
+ r = usbd_probe_and_attach(parent, dev, port, addr);
+ if (r != USBD_NORMAL_COMPLETION) {
+ usbd_remove_device(dev, up);
+ return (r);
+ }
+
+ return (USBD_NORMAL_COMPLETION);
+}
- /* Next try with interface drivers. */
- for (confi = 0; confi < d->bNumConfigurations; confi++) {
- DPRINTFN(1,("usbd_new_device: trying config idx=%d\n", confi));
- r = usbd_set_config_index(dev, confi, 1);
- if (r != USBD_NORMAL_COMPLETION) {
-#ifdef USB_DEBUG
- DPRINTF(("%s: set config at addr %d failed, "
- "error=%d(%s)\n",
- parent->dv_xname, addr, r,
- usbd_error_strs[r]));
-#else
- printf("%s: set config at addr %d failed\n",
- parent->dv_xname, addr);
+void
+usbd_remove_device(dev, up)
+ usbd_device_handle dev;
+ struct usbd_port *up;
+{
+ DPRINTF(("usbd_remove_device: %p\n", dev));
+
+#if defined(__NetBSD__)
+ /* XXX bit of a hack, only for hubs the detach is called
+ *
+ * easiest solution, register a detach method in the softc, call that
+ * one and pass the device struct to it, or the softc. Whatever.
+ */
+ /*if (dev->bdev && dev->hub)
+ uhub_detach(dev->hub->hubdata);*/
+#elif defined(__FreeBSD__)
+ if (dev->bdev)
+ device_delete_child(device_get_parent(dev->bdev), dev->bdev);
#endif
- goto bad;
- }
- uaa.configno = confi;
- for (found = i = 0; i < dev->cdesc->bNumInterface; i++) {
- uaa.iface = &dev->ifaces[i];
- uaa.ifaceno = dev->ifaces[i].idesc->bInterfaceNumber;
- if (config_found_sm(parent, &uaa, usbd_print,
- usbd_submatch))
- found++;
- }
- if (found != 0)
- return (USBD_NORMAL_COMPLETION);
- }
- /* No interfaces were attached in any of the configurations. */
- if (d->bNumConfigurations > 0)
- usbd_set_config_index(dev, 0, 0);
-
- DPRINTF(("usbd_new_device: no interface drivers found\n"));
-
- /* Finally try the generic driver. */
- uaa.iface = 0;
- uaa.usegeneric = 1;
- uaa.configno = UHUB_UNK_CONFIGURATION;
- uaa.ifaceno = UHUB_UNK_INTERFACE;
- if (config_found_sm(parent, &uaa, usbd_print, usbd_submatch) != 0)
- return (USBD_NORMAL_COMPLETION);
-
- DPRINTF(("usbd_new_device: generic attach failed\n"));
-
- return (USBD_NORMAL_COMPLETION);
-
- bad:
- usbd_kill_pipe(dev->default_pipe);
- bad1:
+
+ if (dev->default_pipe)
+ usbd_kill_pipe(dev->default_pipe);
up->device = 0;
- bus->devices[addr] = 0;
+ dev->bus->devices[dev->address] = 0;
+
free(dev, M_USB);
- return (r);
}
+#if defined(__NetBSD__)
int
usbd_print(aux, pnp)
void *aux;
@@ -896,6 +989,15 @@ usbd_submatch(parent, cf, aux)
return ((*cf->cf_attach->ca_match)(parent, cf, aux));
}
+#elif defined(__FreeBSD__)
+static void
+usbd_bus_print_child(device_t bus, device_t dev)
+{
+ /* FIXME print the device address and the configuration used
+ */
+}
+#endif
+
void
usbd_fill_deviceinfo(dev, di)
usbd_device_handle dev;
diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c
index 838240ce55b..9af92aa186f 100644
--- a/sys/dev/usb/usbdi.c
+++ b/sys/dev/usb/usbdi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi.c,v 1.14 1998/12/10 23:16:48 augustss Exp $ */
+/* $NetBSD: usbdi.c,v 1.15 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,14 +37,18 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include "opt_usbverbose.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#if defined(__NetBSD__)
+#include <sys/device.h>
+#else
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#endif
#include <sys/malloc.h>
#include <sys/proc.h>
-#include <sys/device.h>
#include <dev/usb/usb.h>
@@ -72,6 +76,12 @@ void usbd_do_request_async_cb
static SIMPLEQ_HEAD(, usbd_request) usbd_free_requests;
+#if defined(__FreeBSD__)
+#define USB_CDEV_MAJOR 79
+
+extern struct cdevsw usb_cdevsw;
+#endif
+
usbd_status
usbd_open_pipe(iface, address, flags, pipe)
usbd_interface_handle iface;
@@ -235,7 +245,7 @@ usbd_start(pipe)
{
usbd_request_handle reqh;
- DPRINTFN(1, ("usbd_start: pipe=%p, running=%d\n",
+ DPRINTFN(5, ("usbd_start: pipe=%p, running=%d\n",
pipe, pipe->running));
if (pipe->running)
return (USBD_IN_PROGRESS);
@@ -513,7 +523,7 @@ usbd_clear_endpoint_stall(pipe)
req.bmRequestType = UT_WRITE_ENDPOINT;
req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_STALL);
+ USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
r = usbd_do_request(dev, &req, 0);
@@ -537,7 +547,7 @@ usbd_clear_endpoint_stall_async(pipe)
req.bmRequestType = UT_WRITE_ENDPOINT;
req.bRequest = UR_CLEAR_FEATURE;
- USETW(req.wValue, UF_ENDPOINT_STALL);
+ USETW(req.wValue, UF_ENDPOINT_HALT);
USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
USETW(req.wLength, 0);
r = usbd_do_request_async(dev, &req, 0);
@@ -933,9 +943,18 @@ static int usbd_global_init_done = 0;
void
usbd_init()
{
+#if defined(__FreeBSD__)
+ dev_t dev;
+#endif
+
if (!usbd_global_init_done) {
usbd_global_init_done = 1;
SIMPLEQ_INIT(&usbd_free_requests);
+
+#if defined(__FreeBSD__)
+ dev = makedev(USB_CDEV_MAJOR, 0);
+ cdevsw_add(&dev, &usb_cdevsw, NULL);
+#endif
}
}
@@ -956,7 +975,7 @@ usbd_transfer_cb(reqh)
if (reqh->status == USBD_NORMAL_COMPLETION &&
reqh->actlen < reqh->length &&
!(reqh->flags & USBD_SHORT_XFER_OK)) {
- DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d < %d\n",
+ DPRINTFN(-1, ("usbd_transfer_cb: short xfer %d+1<%d+1 (bytes)\n",
reqh->actlen, reqh->length));
reqh->status = USBD_SHORT_XFER;
}
@@ -1034,10 +1053,8 @@ usbd_do_request(dev, req, data)
r = usbd_setup_default_request(
reqh, dev, 0, USBD_DEFAULT_TIMEOUT, req, data,
UGETW(req->wLength), 0, 0);
- if (r != USBD_NORMAL_COMPLETION) {
- usbd_free_request(reqh);
- return (r);
- }
+ if (r != USBD_NORMAL_COMPLETION)
+ goto bad;
r = usbd_sync_transfer(reqh);
#if defined(USB_DEBUG) || defined(DIAGNOSTIC)
if (reqh->actlen > reqh->length)
@@ -1049,6 +1066,50 @@ usbd_do_request(dev, req, data)
UGETW(reqh->request.wLength),
reqh->length, reqh->actlen);
#endif
+ if (r == USBD_STALLED) {
+ /*
+ * The control endpoint has stalled. Control endpoints
+ * should not halt, but some may do so anyway so clear
+ * any halt condition.
+ */
+ usb_device_request_t treq;
+ usb_status_t status;
+ u_int16_t s;
+ usbd_status nr;
+
+ treq.bmRequestType = UT_READ_ENDPOINT;
+ treq.bRequest = UR_GET_STATUS;
+ USETW(treq.wValue, 0);
+ USETW(treq.wIndex, 0);
+ USETW(treq.wLength, sizeof(usb_status_t));
+ nr = usbd_setup_default_request(
+ reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
+ sizeof(usb_status_t), 0, 0);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ nr = usbd_sync_transfer(reqh);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ s = UGETW(status.wStatus);
+ DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
+ if (!(s & UES_HALT))
+ goto bad;
+ treq.bmRequestType = UT_WRITE_ENDPOINT;
+ treq.bRequest = UR_CLEAR_FEATURE;
+ USETW(treq.wValue, UF_ENDPOINT_HALT);
+ USETW(treq.wIndex, 0);
+ USETW(treq.wLength, 0);
+ nr = usbd_setup_default_request(
+ reqh, dev, 0, USBD_DEFAULT_TIMEOUT, &treq, &status,
+ 0, 0, 0);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ nr = usbd_sync_transfer(reqh);
+ if (nr != USBD_NORMAL_COMPLETION)
+ goto bad;
+ }
+
+ bad:
usbd_free_request(reqh);
return (r);
}
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index fb3235e7798..80dddbb78f2 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi.h,v 1.11 1998/12/10 23:16:48 augustss Exp $ */
+/* $NetBSD: usbdi.h,v 1.12 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -251,6 +251,7 @@ struct usb_attach_arg {
int usegeneric;
};
+#if defined(__NetBSD__)
/* Match codes. */
/* First five codes is for a whole device. */
#define UMATCH_VENDOR_PRODUCT_REV 14
@@ -272,6 +273,47 @@ struct usb_attach_arg {
/* No match */
#define UMATCH_NONE 0
+#elif defined(__FreeBSD__)
+/* FreeBSD needs values less than zero */
+/* for the moment disabled
+#define UMATCH_VENDOR_PRODUCT_REV -14
+#define UMATCH_VENDOR_PRODUCT -13
+#define UMATCH_VENDOR_DEVCLASS_DEVPROTO -12
+#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO -11
+#define UMATCH_DEVCLASS_DEVSUBCLASS -10
+#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE -9
+#define UMATCH_VENDOR_PRODUCT_CONF_IFACE -8
+#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO -7
+#define UMATCH_VENDOR_IFACESUBCLASS -6
+#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO -5
+#define UMATCH_IFACECLASS_IFACESUBCLASS -4
+#define UMATCH_IFACECLASS -3
+#define UMATCH_IFACECLASS_GENERIC -2
+#define UMATCH_GENERIC -1
+#define UMATCH_NONE ENXIO
+
+* For the moment we use Yes/No answers with appropriate
+* sorting in the config file
+*/
+#define UMATCH_VENDOR_PRODUCT_REV 0
+#define UMATCH_VENDOR_PRODUCT 0
+#define UMATCH_VENDOR_DEVCLASS_DEVPROTO 0
+#define UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO 0
+#define UMATCH_DEVCLASS_DEVSUBCLASS 0
+#define UMATCH_VENDOR_PRODUCT_REV_CONF_IFACE 0
+#define UMATCH_VENDOR_PRODUCT_CONF_IFACE 0
+#define UMATCH_VENDOR_IFACESUBCLASS_IFACEPROTO 0
+#define UMATCH_VENDOR_IFACESUBCLASS 0
+#define UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO 0
+#define UMATCH_IFACECLASS_IFACESUBCLASS 0
+#define UMATCH_IFACECLASS 0
+#define UMATCH_IFACECLASS_GENERIC 0
+#define UMATCH_GENERIC 0
+#define UMATCH_NONE ENXIO
+
+
+#endif
+
void usbd_devinfo __P((usbd_device_handle, int, char *));
struct usbd_quirks *usbd_get_quirks __P((usbd_device_handle));
void usbd_set_disco __P((usbd_pipe_handle, void (*)(void *), void *));
diff --git a/sys/dev/usb/usbdi_util.c b/sys/dev/usb/usbdi_util.c
index 67c2645ce2f..7549321bbe7 100644
--- a/sys/dev/usb/usbdi_util.c
+++ b/sys/dev/usb/usbdi_util.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi_util.c,v 1.8 1998/12/09 00:18:12 augustss Exp $ */
+/* $NetBSD: usbdi_util.c,v 1.9 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -41,7 +41,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
-#include <sys/device.h>
#include <sys/proc.h>
#include <sys/select.h>
@@ -51,8 +50,6 @@
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
-#include "opt_usbverbose.h"
-
#ifdef USB_DEBUG
#define DPRINTF(x) if (usbdebug) printf x
#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
@@ -85,9 +82,19 @@ usbd_get_config_desc(dev, conf, d)
int conf;
usb_config_descriptor_t *d;
{
+ usbd_status r;
+
DPRINTFN(3,("usbd_get_config_desc: conf=%d\n", conf));
- return (usbd_get_desc(dev, UDESC_CONFIG,
- conf, USB_CONFIG_DESCRIPTOR_SIZE, d));
+ r = usbd_get_desc(dev, UDESC_CONFIG, conf,
+ USB_CONFIG_DESCRIPTOR_SIZE, d);
+ if (r != USBD_NORMAL_COMPLETION)
+ return (r);
+ if (d->bDescriptorType != UDESC_CONFIG) {
+ DPRINTFN(-1,("usbd_get_config_desc: conf %d, bad desc %d\n",
+ conf, d->bDescriptorType));
+ return (USBD_INVAL);
+ }
+ return (USBD_NORMAL_COMPLETION);
}
usbd_status
@@ -398,7 +405,12 @@ usbd_alloc_report_desc(ifc, descp, sizep, mem)
usbd_interface_handle ifc;
void **descp;
int *sizep;
+#if defined(__NetBSD__)
int mem;
+#elif defined(__FreeBSD__)
+ struct malloc_type *mem;
+#endif
+
{
usb_interface_descriptor_t *id;
usb_hid_descriptor_t *hid;
diff --git a/sys/dev/usb/usbdi_util.h b/sys/dev/usb/usbdi_util.h
index df798cebd1a..c42bea94219 100644
--- a/sys/dev/usb/usbdi_util.h
+++ b/sys/dev/usb/usbdi_util.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdi_util.h,v 1.9 1998/12/10 23:16:48 augustss Exp $ */
+/* $NetBSD: usbdi_util.h,v 1.10 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -66,8 +66,13 @@ usbd_status usbd_get_report
__P((usbd_interface_handle iface,int type,int id,void *data,int len));
usbd_status usbd_set_idle
__P((usbd_interface_handle iface, int duration, int id));
+#if defined(__NetBSD__)
usbd_status usbd_alloc_report_desc
__P((usbd_interface_handle ifc, void **descp, int *sizep, int mem));
+#elif defined(__FreeBSD__)
+usbd_status usbd_alloc_report_desc
+ __P((usbd_interface_handle ifc, void **descp, int *sizep, struct malloc_type * mem));
+#endif
usbd_status usbd_get_config
__P((usbd_device_handle dev, u_int8_t *conf));
usbd_status usbd_get_string_desc
diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h
index b6226b58ab2..a6b3a82cae1 100644
--- a/sys/dev/usb/usbdivar.h
+++ b/sys/dev/usb/usbdivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdivar.h,v 1.10 1998/12/09 00:18:12 augustss Exp $ */
+/* $NetBSD: usbdivar.h,v 1.11 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -59,15 +59,17 @@ struct usbd_methods {
struct usbd_port {
usb_port_status_t status;
- int power; /* mA of current on port */
+ u_int16_t power; /* mA of current on port */
+ u_int8_t portno;
+ u_int8_t restartcnt;
+#define USBD_RESTART_MAX 5
struct usbd_device *device;
struct usbd_device *parent; /* The ports hub */
};
struct usbd_hub {
- usbd_status (*explore)__P((struct device *parent,
- usbd_device_handle hub));
- void *hubdata;
+ usbd_status (*explore)__P((usbd_device_handle hub));
+ void *hubsoftc;
usb_hub_descriptor_t hubdesc;
struct usbd_port ports[1];
};
@@ -78,7 +80,7 @@ struct usb_softc;
struct usbd_bus {
/* Filled by HC driver */
- struct device bdev; /* base device */
+ bdevice bdev; /* base device, host adapter */
usbd_status (*open_pipe)__P((struct usbd_pipe *pipe));
u_int32_t pipe_size; /* size of a pipe struct */
void (*do_poll)__P((struct usbd_bus *));
@@ -109,6 +111,7 @@ struct usbd_device {
usb_config_descriptor_t *cdesc; /* full config descr */
struct usbd_quirks *quirks;
struct usbd_hub *hub; /* only if this is a hub */
+ void *softc; /* device softc if attached */
};
struct usbd_interface {
@@ -162,6 +165,10 @@ struct usbd_request {
SIMPLEQ_ENTRY(usbd_request) next;
void *hcpriv; /* XXX private use by the HC driver */
+
+#if defined(__FreeBSD__)
+ struct callout_handle timo_handle;
+#endif
};
void usbd_init __P((void));
@@ -177,10 +184,12 @@ usbd_status usbd_setup_pipe __P((usbd_device_handle dev,
usbd_interface_handle iface,
struct usbd_endpoint *,
usbd_pipe_handle *pipe));
-usbd_status usbd_new_device __P((struct device *parent,
+usbd_status usbd_new_device __P((bdevice *parent,
usbd_bus_handle bus, int depth,
int lowspeed, int port,
struct usbd_port *));
+void usbd_remove_device __P((usbd_device_handle,
+ struct usbd_port *));
int usbd_printBCD __P((char *cp, int bcd));
usbd_status usbd_fill_iface_data __P((usbd_device_handle dev,
int i, int a));
@@ -190,11 +199,18 @@ int usb_bus_count __P((void));
usbd_status usb_get_bus_handle __P((int, usbd_bus_handle *));
void usb_needs_explore __P((usbd_bus_handle));
+#if defined(__FreeBSD__)
+int usb_driver_load __P((module_t mod, int what, void *arg));
+void usb_device_set_desc __P((device_t device, char *devinfo));
+#endif
+
extern int usbd_use_polling;
/* Locator stuff. */
+#if defined(__NetBSD__)
#include "locators.h"
+#endif
#define uhubcf_port cf_loc[UHUBCF_PORT]
#define uhubcf_configuration cf_loc[UHUBCF_CONFIGURATION]
diff --git a/sys/dev/usb/usbhid.h b/sys/dev/usb/usbhid.h
index 317f57e6c21..02231b578fb 100644
--- a/sys/dev/usb/usbhid.h
+++ b/sys/dev/usb/usbhid.h
@@ -1,4 +1,4 @@
-/* $NetBSD: usbhid.h,v 1.2 1998/11/25 22:32:05 augustss Exp $ */
+/* $NetBSD: usbhid.h,v 1.3 1998/12/26 12:53:04 augustss Exp $ */
/*
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -73,11 +73,46 @@ typedef struct usb_hid_descriptor {
#define HUP_BUTTON 0x0009
/* Usages, generic desktop */
+#define HUG_POINTER 0x0001
#define HUG_MOUSE 0x0002
+#define HUG_JOYSTICK 0x0004
+#define HUG_GAME_PAD 0x0005
+#define HUG_KEYBOARD 0x0006
+#define HUG_KEYPAD 0x0007
#define HUG_X 0x0030
#define HUG_Y 0x0031
#define HUG_Z 0x0032
+#define HUG_RX 0x0033
+#define HUG_RY 0x0034
+#define HUG_RZ 0x0035
+#define HUG_SLIDER 0x0036
+#define HUG_DIAL 0x0037
#define HUG_WHEEL 0x0038
+#define HUG_HAT_SWITCH 0x0039
+#define HUG_COUNTED_BUFFER 0x003a
+#define HUG_BYTE_COUNT 0x003b
+#define HUG_MOTION_WAKEUP 0x003c
+#define HUG_VX 0x0040
+#define HUG_VY 0x0041
+#define HUG_VZ 0x0042
+#define HUG_VBRX 0x0043
+#define HUG_VBRY 0x0044
+#define HUG_VBRZ 0x0045
+#define HUG_VNO 0x0046
+#define HUG_SYSTEM_CONTROL 0x0080
+#define HUG_SYSTEM_POWER_DOWN 0x0081
+#define HUG_SYSTEM_SLEEP 0x0082
+#define HUG_SYSTEM_WAKEUP 0x0083
+#define HUG_SYSTEM_CONTEXT_MENU 0x0084
+#define HUG_SYSTEM_MAIN_MENU 0x0085
+#define HUG_SYSTEM_APP_MENU 0x0086
+#define HUG_SYSTEM_MENU_HELP 0x0087
+#define HUG_SYSTEM_MENU_EXIT 0x0088
+#define HUG_SYSTEM_MENU_SELECT 0x0089
+#define HUG_SYSTEM_MENU_RIGHT 0x008a
+#define HUG_SYSTEM_MENU_LEFT 0x008b
+#define HUG_SYSTEM_MENU_UP 0x008c
+#define HUG_SYSTEM_MENU_DOWN 0x008d
#define HID_USAGE2(p,u) (((p) << 16) | u)