USB patches
Michael Neumann
mneumann at ntecs.de
Mon May 19 03:58:39 PDT 2008
Hi,
A patch (usb.diff) that brings in all recent FreeBSD-current USB changes
(no devices yet). Tested on two laptops and qemu. All three paniced
before with the same message as in this thread:
http://leaf.dragonflybsd.org/mailarchive/kernel/2007-11/msg00034.html
This should be easily reproducable using qemu with -usb and -usbdevice
options.
After the patches, all three boot up and I can use USB without problems.
One problem is not yet fixed: When I boot with a USB device connected,
it sometimes hangs.
The second diff (freebsd.usb.diff) is against FreeBSD-current as of
yesterday.
Regards,
Michael
Index: ehci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ehci.c,v
retrieving revision 1.32
diff -u -r1.32 ehci.c
--- ehci.c 29 Jun 2007 22:56:31 -0000 1.32
+++ ehci.c 19 May 2008 11:21:42 -0000
@@ -198,9 +198,10 @@
static void ehci_free_sqtd(ehci_softc_t *, ehci_soft_qtd_t *);
static usbd_status ehci_alloc_sqtd_chain(struct ehci_pipe *,
ehci_softc_t *, int, int, usbd_xfer_handle,
+ ehci_soft_qtd_t *, ehci_soft_qtd_t *,
ehci_soft_qtd_t **, ehci_soft_qtd_t **);
-static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qtd_t *,
- ehci_soft_qtd_t *);
+static void ehci_free_sqtd_chain(ehci_softc_t *, ehci_soft_qh_t *,
+ ehci_soft_qtd_t *, ehci_soft_qtd_t *);
static usbd_status ehci_device_request(usbd_xfer_handle xfer);
@@ -210,7 +211,7 @@
static void ehci_add_qh(ehci_soft_qh_t *, ehci_soft_qh_t *);
static void ehci_rem_qh(ehci_softc_t *, ehci_soft_qh_t *,
ehci_soft_qh_t *);
-static void ehci_set_qh_qtd(ehci_soft_qh_t *, ehci_soft_qtd_t *);
+static void ehci_activate_qh(ehci_soft_qh_t *, ehci_soft_qtd_t *);
static void ehci_sync_hc(ehci_softc_t *);
static void ehci_close_pipe(usbd_pipe_handle, ehci_soft_qh_t *);
@@ -307,10 +308,43 @@
ehci_device_isoc_done,
};
+static usbd_status
+ehci_hcreset(ehci_softc_t *sc)
+{
+ u_int32_t hcr;
+ u_int i;
+
+ EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
+ for (i = 0; i < 100; i++) {
+ usb_delay_ms(&sc->sc_bus, 1);
+ hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH;
+ if (hcr)
+ break;
+ }
+ if (!hcr)
+ /*
+ * Fall through and try reset anyway even though
+ * Table 2-9 in the EHCI spec says this will result
+ * in undefined behavior.
+ */
+ kprintf("%s: stop timeout\n",
+ device_get_nameunit(sc->sc_bus.bdev));
+
+ EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+ for (i = 0; i < 100; i++) {
+ usb_delay_ms(&sc->sc_bus, 1);
+ hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
+ if (!hcr)
+ return (USBD_NORMAL_COMPLETION);
+ }
+ kprintf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
+ return (USBD_IOERROR);
+}
+
usbd_status
ehci_init(ehci_softc_t *sc)
{
- u_int32_t vers, sparams, cparams, hcr;
+ u_int32_t version, sparams, cparams, hcr;
u_int i;
usbd_status err;
ehci_soft_qh_t *sqh;
@@ -324,9 +358,9 @@
sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
- vers = EREAD2(sc, EHCI_HCIVERSION);
+ version = EREAD2(sc, EHCI_HCIVERSION);
kprintf("%s: EHCI version %x.%x\n", device_get_nameunit(sc->sc_bus.bdev),
- vers >> 8, vers & 0xff);
+ version >> 8, version & 0xff);
sparams = EREAD4(sc, EHCI_HCSPARAMS);
DPRINTF(("ehci_init: sparams=0x%x\n", sparams));
@@ -361,20 +395,9 @@
/* Reset the controller */
DPRINTF(("%s: resetting\n", device_get_nameunit(sc->sc_bus.bdev)));
- EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
- usb_delay_ms(&sc->sc_bus, 1);
- EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
- for (i = 0; i < 100; i++) {
- usb_delay_ms(&sc->sc_bus, 1);
- hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET;
- if (!hcr)
- break;
- }
- if (hcr) {
- kprintf("%s: reset timeout\n",
- device_get_nameunit(sc->sc_bus.bdev));
- return (USBD_IOERROR);
- }
+ err = ehci_hcreset(sc);
+ if (err != USBD_NORMAL_COMPLETION)
+ return (err);
/* frame list size at default, read back what we got and use that */
switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))) {
@@ -431,7 +454,6 @@
sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- sqh->sqtd = NULL;
}
/* Point the frame list at the last level (128ms). */
for (i = 0; i < sc->sc_flsize; i++) {
@@ -457,8 +479,7 @@
/* Fill the overlay qTD */
sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
- sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED);
- sqh->sqtd = NULL;
+ sqh->qh.qh_qtd.qtd_status = htole32(0);
#ifdef EHCI_DEBUG
if (ehcidebug) {
ehci_dump_sqh(sqh);
@@ -515,7 +536,7 @@
{
ehci_softc_t *sc = v;
- if (sc->sc_dying || (sc->sc_flags & EHCI_SCFLG_DONEINIT) == 0)
+ if (sc == NULL || sc->sc_dying)
return (0);
/* If we get an interrupt while polling, then just ignore it. */
@@ -540,6 +561,14 @@
DPRINTFN(20,("ehci_intr1: enter\n"));
+ /* In case the interrupt occurs before initialization has completed. */
+ if (sc == NULL) {
+#ifdef DIAGNOSTIC
+ kprintf("ehci_intr1: sc == NULL\n");
+#endif
+ return (0);
+ }
+
intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS));
if (!intrs)
return (0);
@@ -615,6 +644,24 @@
ehci_pcd_able(sc, 1);
}
+/*
+ * XXX write back xfer data for architectures with a write-back
+ * data cache; this is a hack because usb is mis-architected
+ * in blindly mixing bus_dma w/ PIO.
+ */
+static __inline void
+hacksync(usbd_xfer_handle xfer)
+{
+ bus_dma_tag_t tag;
+ struct usb_dma_mapping *dmap;
+
+ if (xfer->length == 0)
+ return;
+ tag = xfer->pipe->device->bus->buffer_dmatag;
+ dmap = &xfer->dmamap;
+ bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE);
+}
+
void
ehci_pcd(ehci_softc_t *sc, usbd_xfer_handle xfer)
{
@@ -629,7 +676,7 @@
pipe = xfer->pipe;
- p = KERNADDR(&xfer->dmabuf, 0);
+ p = xfer->buffer;
m = min(sc->sc_noport, xfer->length * 8 - 1);
memset(p, 0, xfer->length);
for (i = 1; i <= m; i++) {
@@ -641,6 +688,7 @@
xfer->actlen = xfer->length;
xfer->status = USBD_NORMAL_COMPLETION;
+ hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
}
@@ -669,8 +717,8 @@
/* Schedule a callout to catch any dropped transactions. */
if ((sc->sc_flags & EHCI_SCFLG_LOSTINTRBUG) &&
!LIST_EMPTY(&sc->sc_intrhead))
- callout_reset(&sc->sc_tmo_intrlist, hz / 5, ehci_intrlist_timeout,
- sc);
+ callout_reset(&sc->sc_tmo_intrlist, hz / 5,
+ ehci_intrlist_timeout, sc);
#ifdef USB_USE_SOFTINTR
if (sc->sc_softwake) {
@@ -736,11 +784,10 @@
ehci_idone(struct ehci_xfer *ex)
{
usbd_xfer_handle xfer = &ex->xfer;
-#ifdef USB_DEBUG
struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
-#endif
ehci_soft_qtd_t *sqtd, *lsqtd;
u_int32_t status = 0, nstatus = 0;
+ ehci_physaddr_t nextphys, altnextphys;
int actlen, cerr;
DPRINTFN(/*12*/2, ("ehci_idone: ex=%p\n", ex));
@@ -774,6 +821,30 @@
ehci_dump_sqtds(ex->sqtdstart);
#endif
+ /*
+ * Make sure that the QH overlay qTD does not reference any
+ * of the qTDs we are about to free. This is probably only
+ * necessary if the transfer is marked as HALTED.
+ */
+ nextphys = EHCI_LINK_ADDR(le32toh(epipe->sqh->qh.qh_qtd.qtd_next));
+ altnextphys =
+ EHCI_LINK_ADDR(le32toh(epipe->sqh->qh.qh_qtd.qtd_altnext));
+ for (sqtd = ex->sqtdstart; sqtd != ex->sqtdend->nextqtd;
+ sqtd = sqtd->nextqtd) {
+ if (sqtd->physaddr == nextphys) {
+ epipe->sqh->qh.qh_qtd.qtd_next =
+ htole32(ex->sqtdend->nextqtd->physaddr);
+ DPRINTFN(4, ("ehci_idone: updated overlay next ptr\n"));
+
+ }
+ if (sqtd->physaddr == altnextphys) {
+ DPRINTFN(4,
+ ("ehci_idone: updated overlay altnext ptr\n"));
+ epipe->sqh->qh.qh_qtd.qtd_altnext =
+ htole32(ex->sqtdend->nextqtd->physaddr);
+ }
+ }
+
/* The transfer is done, compute actual length and status. */
lsqtd = ex->sqtdend;
actlen = 0;
@@ -784,8 +855,7 @@
status = nstatus;
/* halt is ok if descriptor is last, and complete */
- if (sqtd->qtd.qtd_next == EHCI_NULL &&
- EHCI_QTD_GET_BYTES(status) == 0)
+ if (sqtd == lsqtd && EHCI_QTD_GET_BYTES(status) == 0)
status &= ~EHCI_QTD_HALTED;
if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP)
actlen += sqtd->len - EHCI_QTD_GET_BYTES(status);
@@ -890,8 +960,7 @@
sc->sc_dying = 1;
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
- EOWRITE4(sc, EHCI_USBCMD, 0);
- EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+ (void) ehci_hcreset(sc);
callout_stop(&sc->sc_tmo_intrlist);
callout_stop(&sc->sc_tmo_pcd);
@@ -927,6 +996,7 @@
switch (why) {
case PWR_SUSPEND:
+ case PWR_STANDBY:
sc->sc_bus.use_polling++;
for (i = 1; i <= sc->sc_noport; i++) {
@@ -1024,6 +1094,10 @@
sc->sc_bus.use_polling--;
break;
+ case PWR_SOFTSUSPEND:
+ case PWR_SOFTSTANDBY:
+ case PWR_SOFTRESUME:
+ break;
}
crit_exit();
@@ -1043,8 +1117,7 @@
ehci_softc_t *sc = v;
DPRINTF(("ehci_shutdown: stopping the HC\n"));
- EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
- EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
+ (void) ehci_hcreset(sc);
}
usbd_status
@@ -1082,7 +1155,7 @@
}
#endif
} else {
- xfer = kmalloc(sizeof(struct ehci_xfer), M_USB, M_INTWAIT);
+ xfer = kmalloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT);
}
if (xfer != NULL) {
memset(xfer, 0, sizeof(struct ehci_xfer));
@@ -1163,7 +1236,7 @@
* debugger.
*/
void
-ehci_dump(void)
+ehci_dump()
{
ehci_dump_regs(theehci);
}
@@ -1240,6 +1313,7 @@
u_int32_t endp, endphub;
kprintf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
+ kprintf(" sqtd=%p inactivesqtd=%p\n", sqh->sqtd, sqh->inactivesqtd);
kprintf(" link="); ehci_dump_link(qh->qh_link, 1); kprintf("\n");
endp = le32toh(qh->qh_endp);
kprintf(" endp=0x%08x\n", endp);
@@ -1351,9 +1425,7 @@
EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x01 : 0)
);
sqh->qh.qh_curqtd = EHCI_NULL;
- /* Fill the overlay qTD */
- sqh->qh.qh_qtd.qtd_next = EHCI_NULL;
- sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+ /* The overlay qTD was already set up by ehci_alloc_sqh(). */
sqh->qh.qh_qtd.qtd_status =
htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle));
@@ -1439,27 +1511,38 @@
ehci_sync_hc(sc);
}
+/* Restart a QH following the addition of a qTD. */
void
-ehci_set_qh_qtd(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd)
+ehci_activate_qh(ehci_soft_qh_t *sqh, ehci_soft_qtd_t *sqtd)
{
- int i;
- u_int32_t status;
+ KASSERT((sqtd->qtd.qtd_status & htole32(EHCI_QTD_ACTIVE)) == 0,
+ ("ehci_activate_qh: already active"));
- /* Save toggle bit and ping status. */
- status = sqh->qh.qh_qtd.qtd_status &
- htole32(EHCI_QTD_TOGGLE_MASK |
- EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE));
- /* Set HALTED to make hw leave it alone. */
- sqh->qh.qh_qtd.qtd_status =
- htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED));
- sqh->qh.qh_curqtd = 0;
- sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
- sqh->qh.qh_qtd.qtd_altnext = 0;
- for (i = 0; i < EHCI_QTD_NBUFFERS; i++)
- sqh->qh.qh_qtd.qtd_buffer[i] = 0;
- sqh->sqtd = sqtd;
- /* Set !HALTED && !ACTIVE to start execution, preserve some fields */
- sqh->qh.qh_qtd.qtd_status = status;
+ /*
+ * When a QH is idle, the overlay qTD should be marked as not
+ * halted and not active. This causes the host controller to
+ * retrieve the real qTD on each pass (rather than just examinig
+ * the overlay), so it will notice when we activate the qTD.
+ */
+ if (sqtd == sqh->sqtd) {
+ /* Check that the hardware is in the state we expect. */
+ if (EHCI_LINK_ADDR(le32toh(sqh->qh.qh_qtd.qtd_next)) !=
+ sqtd->physaddr) {
+#ifdef EHCI_DEBUG
+ kprintf("ehci_activate_qh: unexpected next ptr\n");
+ ehci_dump_sqh(sqh);
+ ehci_dump_sqtds(sqh->sqtd);
+#endif
+ sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
+ sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+ }
+ /* Ensure the flags are correct. */
+ sqh->qh.qh_qtd.qtd_status &= htole32(EHCI_QTD_PINGSTATE |
+ EHCI_QTD_TOGGLE_MASK);
+ }
+
+ /* Now activate the qTD. */
+ sqtd->qtd.qtd_status |= htole32(EHCI_QTD_ACTIVE);
}
/*
@@ -1637,7 +1720,7 @@
index = UGETW(req->wIndex);
if (len != 0)
- buf = KERNADDR(&xfer->dmabuf, 0);
+ buf = xfer->buffer;
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
@@ -1989,6 +2072,7 @@
ret:
xfer->status = err;
crit_enter();
+ hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
crit_exit();
return (USBD_IN_PROGRESS);
@@ -2106,6 +2190,7 @@
ehci_alloc_sqh(ehci_softc_t *sc)
{
ehci_soft_qh_t *sqh;
+ ehci_soft_qtd_t *sqtd;
usbd_status err;
int i, offs;
usb_dma_t dma;
@@ -2128,17 +2213,36 @@
sc->sc_freeqhs = sqh;
}
}
+ /* Allocate the initial inactive sqtd. */
+ sqtd = ehci_alloc_sqtd(sc);
+ if (sqtd == NULL)
+ return (NULL);
+ sqtd->qtd.qtd_status = htole32(0);
+ sqtd->qtd.qtd_next = EHCI_NULL;
+ sqtd->qtd.qtd_altnext = EHCI_NULL;
+
sqh = sc->sc_freeqhs;
sc->sc_freeqhs = sqh->next;
- memset(&sqh->qh, 0, sizeof(ehci_qh_t));
+
+ /* The overlay QTD should begin zeroed. */
+ sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr);
+ sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+ sqh->qh.qh_qtd.qtd_status = 0;
+ for (i = 0; i < EHCI_QTD_NBUFFERS; i++) {
+ sqh->qh.qh_qtd.qtd_buffer[i] = 0;
+ sqh->qh.qh_qtd.qtd_buffer_hi[i] = 0;
+ }
sqh->next = NULL;
sqh->prev = NULL;
+ sqh->sqtd = sqtd;
+ sqh->inactivesqtd = sqtd;
return (sqh);
}
void
ehci_free_sqh(ehci_softc_t *sc, ehci_soft_qh_t *sqh)
{
+ ehci_free_sqtd(sc, sqh->inactivesqtd);
sqh->next = sc->sc_freeqhs;
sc->sc_freeqhs = sqh;
}
@@ -2175,7 +2279,13 @@
crit_enter();
sqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd->nextqtd;
- memset(&sqtd->qtd, 0, sizeof(ehci_qtd_t));
+ sqtd->qtd.qtd_next = EHCI_NULL;
+ sqtd->qtd.qtd_altnext = EHCI_NULL;
+ sqtd->qtd.qtd_status = 0;
+ for (i = 0; i < EHCI_QTD_NBUFFERS; i++) {
+ sqtd->qtd.qtd_buffer[i] = 0;
+ sqtd->qtd.qtd_buffer_hi[i] = 0;
+ }
sqtd->nextqtd = NULL;
sqtd->xfer = NULL;
crit_exit();
@@ -2194,15 +2304,15 @@
usbd_status
ehci_alloc_sqtd_chain(struct ehci_pipe *epipe, ehci_softc_t *sc,
- int alen, int rd, usbd_xfer_handle xfer,
- ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep)
+ int alen, int rd, usbd_xfer_handle xfer, ehci_soft_qtd_t *start,
+ ehci_soft_qtd_t *newinactive, ehci_soft_qtd_t **sp, ehci_soft_qtd_t **ep)
{
ehci_soft_qtd_t *next, *cur;
- ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys;
+ ehci_physaddr_t dataphys, nextphys;
u_int32_t qtdstatus;
- int len, curlen, mps, offset;
- int i, iscontrol;
- usb_dma_t *dma = &xfer->dmabuf;
+ int adj, len, curlen, mps, offset, pagelen, seg, segoff;
+ int i, iscontrol, forceshort;
+ struct usb_dma_mapping *dma = &xfer->dmamap;
DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen));
@@ -2210,8 +2320,6 @@
len = alen;
iscontrol = (epipe->pipe.endpoint->edesc->bmAttributes & UE_XFERTYPE) ==
UE_CONTROL;
- dataphys = DMAADDR(dma, 0);
- dataphyslastpage = EHCI_PAGE(DMAADDR(dma, len - 1));
qtdstatus = EHCI_QTD_ACTIVE |
EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT) |
EHCI_QTD_SET_CERR(3)
@@ -2219,6 +2327,8 @@
/* BYTES set below */
;
mps = UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize);
+ forceshort = ((xfer->flags & USBD_FORCE_SHORT_XFER) || len == 0) &&
+ len % mps == 0;
/*
* The control transfer data stage always starts with a toggle of 1.
* For other transfers we let the hardware track the toggle state.
@@ -2226,38 +2336,77 @@
if (iscontrol)
qtdstatus |= EHCI_QTD_SET_TOGGLE(1);
- cur = ehci_alloc_sqtd(sc);
- *sp = cur;
- if (cur == NULL)
- goto nomem;
- for (;;) {
- dataphyspage = EHCI_PAGE(dataphys);
- /* XXX This is pretty broken: Because we do not allocate
- * a contiguous buffer (contiguous in physical pages) we
- * can only transfer one page in one go.
- * So check whether the start and end of the buffer are on
- * the same page.
+ if (start != NULL) {
+ /*
+ * If we are given a starting qTD, assume it is linked into
+ * an active QH so be careful not to mark it active.
*/
- if (dataphyspage == dataphyslastpage) {
- curlen = len;
+ cur = start;
+ *sp = cur;
+ qtdstatus &= ~EHCI_QTD_ACTIVE;
+ } else {
+ cur = ehci_alloc_sqtd(sc);
+ *sp = cur;
+ if (cur == NULL)
+ goto nomem;
+ }
+ seg = 0;
+ segoff = 0;
+ for (;;) {
+ curlen = 0;
+
+ /* The EHCI hardware can handle at most 5 pages. */
+ for (i = 0; i < EHCI_QTD_NBUFFERS && curlen < len; i++) {
+ KASSERT(seg < dma->nsegs,
+ ("ehci_alloc_sqtd_chain: overrun"));
+ dataphys = dma->segs[seg].ds_addr + segoff;
+ pagelen = dma->segs[seg].ds_len - segoff;
+ if (pagelen > len - curlen)
+ pagelen = len - curlen;
+ if (pagelen > EHCI_PAGE_SIZE -
+ EHCI_PAGE_OFFSET(dataphys))
+ pagelen = EHCI_PAGE_SIZE -
+ EHCI_PAGE_OFFSET(dataphys);
+ segoff += pagelen;
+ if (segoff >= dma->segs[seg].ds_len) {
+ KASSERT(segoff == dma->segs[seg].ds_len,
+ ("ehci_alloc_sqtd_chain: overlap"));
+ seg++;
+ segoff = 0;
+ }
+
+ cur->qtd.qtd_buffer[i] = htole32(dataphys);
+ cur->qtd.qtd_buffer_hi[i] = 0;
+ curlen += pagelen;
+
+ /*
+ * Must stop if there is any gap before or after
+ * the page boundary.
+ */
+ if (EHCI_PAGE_OFFSET(dataphys + pagelen) != 0)
+ break;
+ if (seg < dma->nsegs && EHCI_PAGE_OFFSET(segoff +
+ dma->segs[seg].ds_addr) != 0)
+ break;
}
- else {
- /* See comment above (XXX) */
- curlen = EHCI_PAGE_SIZE -
- EHCI_PAGE_MASK(dataphys);
- /* the length must be a multiple of the max size */
- curlen -= curlen % mps;
- DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, "
- "curlen=%d\n", curlen));
- KASSERT(curlen != 0, ("ehci_alloc_std: curlen == 0"));
- }
- DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x "
- "dataphyslastpage=0x%08x len=%d curlen=%d\n",
- dataphys, dataphyslastpage,
- len, curlen));
+ /* Adjust down to a multiple of mps if not at the end. */
+ if (curlen < len && curlen % mps != 0) {
+ adj = curlen % mps;
+ curlen -= adj;
+ KASSERT(curlen > 0,
+ ("ehci_alloc_sqtd_chain: need to copy"));
+ segoff -= adj;
+ if (segoff < 0) {
+ seg--;
+ segoff += dma->segs[seg].ds_len;
+ }
+ KASSERT(seg >= 0 && segoff >= 0,
+ ("ehci_alloc_sqtd_chain: adjust to mps"));
+ }
+
len -= curlen;
- if (len != 0) {
+ if (len != 0 || forceshort) {
next = ehci_alloc_sqtd(sc);
if (next == NULL)
goto nomem;
@@ -2267,40 +2416,31 @@
nextphys = EHCI_NULL;
}
- for (i = 0; i * EHCI_PAGE_SIZE < curlen; i++) {
- ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE;
- if (i != 0) /* use offset only in first buffer */
- a = EHCI_PAGE(a);
- cur->qtd.qtd_buffer[i] = htole32(a);
- cur->qtd.qtd_buffer_hi[i] = 0;
-#ifdef DIAGNOSTIC
- if (i >= EHCI_QTD_NBUFFERS) {
- kprintf("ehci_alloc_sqtd_chain: i=%d\n", i);
- goto nomem;
- }
-#endif
- }
cur->nextqtd = next;
- cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys;
+ cur->qtd.qtd_next = nextphys;
+ /* Make sure to stop after a short transfer. */
+ cur->qtd.qtd_altnext = htole32(newinactive->physaddr);
cur->qtd.qtd_status =
htole32(qtdstatus | EHCI_QTD_SET_BYTES(curlen));
cur->xfer = xfer;
cur->len = curlen;
- DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n",
- dataphys, dataphys + curlen));
+ DPRINTFN(10,("ehci_alloc_sqtd_chain: curlen=%d\n", curlen));
if (iscontrol) {
/*
* adjust the toggle based on the number of packets
* in this qtd
*/
- if (((curlen + mps - 1) / mps) & 1)
+ if ((((curlen + mps - 1) / mps) & 1) || curlen == 0)
qtdstatus ^= EHCI_QTD_TOGGLE_MASK;
}
- if (len == 0)
- break;
+ qtdstatus |= EHCI_QTD_ACTIVE;
+ if (len == 0) {
+ if (!forceshort)
+ break;
+ forceshort = 0;
+ }
DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
offset += curlen;
- dataphys = DMAADDR(dma, offset);
cur = next;
}
cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC);
@@ -2317,16 +2457,27 @@
return (USBD_NOMEM);
}
+/* Free the chain starting at sqtd and end at the qTD before sqtdend */
static void
-ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd,
- ehci_soft_qtd_t *sqtdend)
+ehci_free_sqtd_chain(ehci_softc_t *sc, ehci_soft_qh_t *sqh,
+ ehci_soft_qtd_t *sqtd, ehci_soft_qtd_t *sqtdend)
{
- ehci_soft_qtd_t *p;
+ ehci_soft_qtd_t *p, **prevp;
int i;
DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p sqtdend=%p\n",
sqtd, sqtdend));
+ /* First unlink the chain from the QH's software qTD list. */
+ prevp = &sqh->sqtd;
+ for (p = sqh->sqtd; p != NULL; p = p->nextqtd) {
+ if (p == sqtd) {
+ *prevp = sqtdend;
+ break;
+ }
+ prevp = &p->nextqtd;
+ }
+ KASSERT(p != NULL, ("ehci_free_sqtd_chain: chain not found"));
for (i = 0; sqtd != sqtdend; sqtd = p, i++) {
p = sqtd->nextqtd;
ehci_free_sqtd(sc, sqtd);
@@ -2363,7 +2514,6 @@
* have happened since the hardware runs concurrently.
* If the transaction has already happened we rely on the ordinary
* interrupt processing to process it.
- * XXX This is most probably wrong.
*/
void
ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
@@ -2372,9 +2522,9 @@
struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
ehci_softc_t *sc = (ehci_softc_t *)epipe->pipe.device->bus;
ehci_soft_qh_t *sqh = epipe->sqh;
- ehci_soft_qtd_t *sqtd, *snext, **psqtd;
+ ehci_soft_qtd_t *sqtd, *snext;
ehci_physaddr_t cur, us, next;
- int hit;
+ int hit, i;
/* int count = 0; */
ehci_soft_qh_t *psqh;
@@ -2467,13 +2617,12 @@
/* We will change them to point here */
snext = exfer->sqtdend->nextqtd;
- next = snext ? htole32(snext->physaddr) : EHCI_NULL;
+ next = htole32(snext->physaddr);
/*
* Now loop through any qTDs before us and keep track of the pointer
* that points to us for the end.
*/
- psqtd = &sqh->sqtd;
sqtd = sqh->sqtd;
while (sqtd && sqtd != exfer->sqtdstart) {
hit |= (cur == sqtd->physaddr);
@@ -2481,11 +2630,8 @@
sqtd->qtd.qtd_next = next;
if (EHCI_LINK_ADDR(le32toh(sqtd->qtd.qtd_altnext)) == us)
sqtd->qtd.qtd_altnext = next;
- psqtd = &sqtd->nextqtd;
sqtd = sqtd->nextqtd;
}
- /* make the software pointer bypass us too */
- *psqtd = exfer->sqtdend->nextqtd;
/*
* If we already saw the active one then we are pretty much done.
@@ -2498,7 +2644,6 @@
* (if there is one). We only need to do this if
* it was previously pointing to us.
*/
- sqtd = exfer->sqtdstart;
for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
if (cur == sqtd->physaddr) {
hit++;
@@ -2512,17 +2657,13 @@
* that we are removing.
*/
if (hit) {
- if (snext) {
- ehci_set_qh_qtd(sqh, snext);
- } else {
-
- sqh->qh.qh_curqtd = 0; /* unlink qTDs */
- sqh->qh.qh_qtd.qtd_status &=
- htole32(EHCI_QTD_TOGGLE_MASK);
- sqh->qh.qh_qtd.qtd_next =
- sqh->qh.qh_qtd.qtd_altnext
- = EHCI_NULL;
- DPRINTFN(1,("ehci_abort_xfer: no hit\n"));
+ sqh->qh.qh_qtd.qtd_next = htole32(snext->physaddr);
+ sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL;
+ sqh->qh.qh_qtd.qtd_status &=
+ htole32(EHCI_QTD_TOGGLE_MASK);
+ for (i = 0; i < EHCI_QTD_NBUFFERS; i++) {
+ sqh->qh.qh_qtd.qtd_buffer[i] = 0;
+ sqh->qh.qh_qtd.qtd_buffer_hi[i] = 0;
}
}
}
@@ -2647,7 +2788,7 @@
{
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
- /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+ struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
DPRINTFN(10,("ehci_ctrl_done: xfer=%p\n", xfer));
@@ -2659,7 +2800,8 @@
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
- ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ ehci_free_sqtd_chain(sc, epipe->sqh, ex->sqtdstart,
+ ex->sqtdend->nextqtd);
}
DPRINTFN(5, ("ehci_ctrl_done: length=%d\n", xfer->actlen));
@@ -2692,8 +2834,7 @@
usb_device_request_t *req = &xfer->request;
usbd_device_handle dev = epipe->pipe.device;
ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
- int addr = dev->address;
- ehci_soft_qtd_t *setup, *stat, *next;
+ ehci_soft_qtd_t *newinactive, *setup, *stat, *next;
ehci_soft_qh_t *sqh;
int isread;
int len;
@@ -2705,14 +2846,17 @@
DPRINTFN(3,("ehci_device_request: 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), len, addr,
+ UGETW(req->wIndex), len, dev->address,
epipe->pipe.endpoint->edesc->bEndpointAddress));
- setup = ehci_alloc_sqtd(sc);
- if (setup == NULL) {
+ newinactive = ehci_alloc_sqtd(sc);
+ if (newinactive == NULL) {
err = USBD_NOMEM;
goto bad1;
}
+ newinactive->qtd.qtd_status = htole32(0);
+ newinactive->qtd.qtd_next = EHCI_NULL;
+ newinactive->qtd.qtd_altnext = EHCI_NULL;
stat = ehci_alloc_sqtd(sc);
if (stat == NULL) {
err = USBD_NOMEM;
@@ -2720,40 +2864,30 @@
}
sqh = epipe->sqh;
+ setup = sqh->inactivesqtd;
+ sqh->inactivesqtd = newinactive;
epipe->u.ctl.length = len;
- /* Update device address and length since they may have changed
- during the setup of the control pipe in usbd_new_device(). */
- /* XXX This only needs to be done once, but it's too early in open. */
- /* XXXX Should not touch ED here! */
- sqh->qh.qh_endp =
- (sqh->qh.qh_endp & htole32(~(EHCI_QH_ADDRMASK | EHCI_QH_MPLMASK))) |
- htole32(
- EHCI_QH_SET_ADDR(addr) |
- EHCI_QH_SET_MPL(UGETW(epipe->pipe.endpoint->edesc->wMaxPacketSize))
- );
-
/* Set up data transaction */
if (len != 0) {
ehci_soft_qtd_t *end;
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
- &next, &end);
+ NULL, newinactive, &next, &end);
if (err)
goto bad3;
end->qtd.qtd_status &= htole32(~EHCI_QTD_IOC);
end->nextqtd = stat;
- end->qtd.qtd_next =
- end->qtd.qtd_altnext = htole32(stat->physaddr);
+ end->qtd.qtd_next = htole32(stat->physaddr);
+ end->qtd.qtd_altnext = htole32(newinactive->physaddr);
} else {
next = stat;
}
memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof *req);
- /* Clear toggle */
+ /* Clear toggle, and do not activate until complete */
setup->qtd.qtd_status = htole32(
- EHCI_QTD_ACTIVE |
EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) |
EHCI_QTD_SET_CERR(3) |
EHCI_QTD_SET_TOGGLE(0) |
@@ -2762,7 +2896,8 @@
setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0));
setup->qtd.qtd_buffer_hi[0] = 0;
setup->nextqtd = next;
- setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr);
+ setup->qtd.qtd_next = htole32(next->physaddr);
+ setup->qtd.qtd_altnext = htole32(newinactive->physaddr);
setup->xfer = xfer;
setup->len = sizeof *req;
@@ -2775,8 +2910,9 @@
);
stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */
stat->qtd.qtd_buffer_hi[0] = 0; /* XXX not needed? */
- stat->nextqtd = NULL;
- stat->qtd.qtd_next = stat->qtd.qtd_altnext = EHCI_NULL;
+ stat->nextqtd = newinactive;
+ stat->qtd.qtd_next = htole32(newinactive->physaddr);
+ stat->qtd.qtd_altnext = htole32(newinactive->physaddr);
stat->xfer = xfer;
stat->len = 0;
@@ -2797,9 +2933,9 @@
exfer->isdone = 0;
#endif
- /* Insert qTD in QH list. */
+ /* Activate the new qTD in the QH list. */
crit_enter();
- ehci_set_qh_qtd(sqh, setup);
+ ehci_activate_qh(sqh, setup);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
ehci_timeout, xfer);
@@ -2823,9 +2959,10 @@
return (USBD_NORMAL_COMPLETION);
bad3:
+ sqh->inactivesqtd = setup;
ehci_free_sqtd(sc, stat);
bad2:
- ehci_free_sqtd(sc, setup);
+ ehci_free_sqtd(sc, newinactive);
bad1:
DPRINTFN(-1,("ehci_device_request: no memory\n"));
xfer->status = err;
@@ -2857,7 +2994,7 @@
struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
usbd_device_handle dev = epipe->pipe.device;
ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
- ehci_soft_qtd_t *data, *dataend;
+ ehci_soft_qtd_t *data, *dataend, *newinactive;
ehci_soft_qh_t *sqh;
usbd_status err;
int len, isread, endpt;
@@ -2880,14 +3017,30 @@
epipe->u.bulk.length = len;
- err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data,
- &dataend);
+ newinactive = ehci_alloc_sqtd(sc);
+ if (newinactive == NULL) {
+ DPRINTFN(-1,("ehci_device_bulk_start: no sqtd memory\n"));
+ err = USBD_NOMEM;
+ xfer->status = err;
+ usb_transfer_complete(xfer);
+ return (err);
+ }
+ newinactive->qtd.qtd_status = htole32(0);
+ newinactive->qtd.qtd_next = EHCI_NULL;
+ newinactive->qtd.qtd_altnext = EHCI_NULL;
+ err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
+ sqh->inactivesqtd, newinactive, &data, &dataend);
if (err) {
DPRINTFN(-1,("ehci_device_bulk_start: no memory\n"));
+ ehci_free_sqtd(sc, newinactive);
xfer->status = err;
usb_transfer_complete(xfer);
return (err);
}
+ dataend->nextqtd = newinactive;
+ dataend->qtd.qtd_next = htole32(newinactive->physaddr);
+ dataend->qtd.qtd_altnext = htole32(newinactive->physaddr);
+ sqh->inactivesqtd = newinactive;
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -2908,7 +3061,7 @@
#endif
crit_enter();
- ehci_set_qh_qtd(sqh, data);
+ ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
ehci_timeout, xfer);
@@ -2964,14 +3117,15 @@
{
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
- /*struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;*/
+ struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
DPRINTFN(10,("ehci_bulk_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
- ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ ehci_free_sqtd_chain(sc, epipe->sqh, ex->sqtdstart,
+ ex->sqtdend->nextqtd);
}
DPRINTFN(5, ("ehci_bulk_done: length=%d\n", xfer->actlen));
@@ -3025,7 +3179,7 @@
struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
usbd_device_handle dev = xfer->pipe->device;
ehci_softc_t *sc = (ehci_softc_t *)dev->bus;
- ehci_soft_qtd_t *data, *dataend;
+ ehci_soft_qtd_t *data, *dataend, *newinactive;
ehci_soft_qh_t *sqh;
usbd_status err;
int len, isread, endpt;
@@ -3048,14 +3202,29 @@
epipe->u.intr.length = len;
- err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data,
- &dataend);
+ newinactive = ehci_alloc_sqtd(sc);
+ if (newinactive == NULL) {
+ DPRINTFN(-1,("ehci_device_intr_start: no sqtd memory\n"));
+ err = USBD_NOMEM;
+ xfer->status = err;
+ usb_transfer_complete(xfer);
+ return (err);
+ }
+ newinactive->qtd.qtd_status = htole32(0);
+ newinactive->qtd.qtd_next = EHCI_NULL;
+ newinactive->qtd.qtd_altnext = EHCI_NULL;
+ err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
+ sqh->inactivesqtd, newinactive, &data, &dataend);
if (err) {
DPRINTFN(-1, ("ehci_device_intr_start: no memory\n"));
xfer->status = err;
usb_transfer_complete(xfer);
return (err);
}
+ dataend->nextqtd = newinactive;
+ dataend->qtd.qtd_next = htole32(newinactive->physaddr);
+ dataend->qtd.qtd_altnext = htole32(newinactive->physaddr);
+ sqh->inactivesqtd = newinactive;
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
@@ -3076,7 +3245,7 @@
#endif
crit_enter();
- ehci_set_qh_qtd(sqh, data);
+ ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
ehci_timeout, xfer);
@@ -3133,7 +3302,7 @@
struct ehci_xfer *ex = EXFER(xfer);
ehci_softc_t *sc = (ehci_softc_t *)xfer->pipe->device->bus;
struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
- ehci_soft_qtd_t *data, *dataend;
+ ehci_soft_qtd_t *data, *dataend, *newinactive;
ehci_soft_qh_t *sqh;
usbd_status err;
int len, isread, endpt;
@@ -3141,22 +3310,38 @@
DPRINTFN(10, ("ehci_device_intr_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
+ sqh = epipe->sqh;
if (xfer->pipe->repeat) {
- ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
-
+ ehci_free_sqtd_chain(sc, sqh, ex->sqtdstart,
+ ex->sqtdend->nextqtd);
+
len = epipe->u.intr.length;
xfer->length = len;
endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
isread = UE_GET_DIR(endpt) == UE_DIR_IN;
- sqh = epipe->sqh;
+ newinactive = ehci_alloc_sqtd(sc);
+ if (newinactive == NULL) {
+ DPRINTFN(-1,
+ ("ehci_device_intr_done: no sqtd memory\n"));
+ err = USBD_NOMEM;
+ xfer->status = err;
+ return;
+ }
+ newinactive->qtd.qtd_status = htole32(0);
+ newinactive->qtd.qtd_next = EHCI_NULL;
+ newinactive->qtd.qtd_altnext = EHCI_NULL;
err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer,
- &data, &dataend);
+ sqh->inactivesqtd, newinactive, &data, &dataend);
if (err) {
DPRINTFN(-1, ("ehci_device_intr_done: no memory\n"));
xfer->status = err;
return;
}
+ dataend->nextqtd = newinactive;
+ dataend->qtd.qtd_next = htole32(newinactive->physaddr);
+ dataend->qtd.qtd_altnext = htole32(newinactive->physaddr);
+ sqh->inactivesqtd = newinactive;
/* Set up interrupt info. */
exfer->sqtdstart = data;
@@ -3170,7 +3355,7 @@
#endif
crit_enter();
- ehci_set_qh_qtd(sqh, data);
+ ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle,
MS_TO_TICKS(xfer->timeout), ehci_timeout, xfer);
@@ -3180,36 +3365,16 @@
xfer->status = USBD_IN_PROGRESS;
} else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
ehci_del_intr_list(ex); /* remove from active list */
- ehci_free_sqtd_chain(sc, ex->sqtdstart, NULL);
+ ehci_free_sqtd_chain(sc, sqh, ex->sqtdstart,
+ ex->sqtdend->nextqtd);
}
#undef exfer
}
/************************/
-static usbd_status
-ehci_device_isoc_transfer(usbd_xfer_handle xfer)
-{
- return USBD_IOERROR;
-}
-
-static usbd_status
-ehci_device_isoc_start(usbd_xfer_handle xfer)
-{
- return USBD_IOERROR;
-}
-
-static void
-ehci_device_isoc_abort(usbd_xfer_handle xfer)
-{
-}
-
-static void
-ehci_device_isoc_close(usbd_pipe_handle pipe)
-{
-}
-
-static void
-ehci_device_isoc_done(usbd_xfer_handle xfer)
-{
-}
+static usbd_status ehci_device_isoc_transfer(usbd_xfer_handle xfer) { return USBD_IOERROR; }
+static usbd_status ehci_device_isoc_start(usbd_xfer_handle xfer) { return USBD_IOERROR; }
+static void ehci_device_isoc_abort(usbd_xfer_handle xfer) { }
+static void ehci_device_isoc_close(usbd_pipe_handle pipe) { }
+static void ehci_device_isoc_done(usbd_xfer_handle xfer) { }
Index: ehci_pci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ehci_pci.c,v
retrieving revision 1.18
diff -u -r1.18 ehci_pci.c
--- ehci_pci.c 14 Aug 2007 20:06:13 -0000 1.18
+++ ehci_pci.c 19 May 2008 10:32:14 -0000
@@ -93,7 +93,7 @@
static const char *ehci_device_m5239 = "ALi M5239 USB 2.0 controller";
/* AMD */
-#define PCI_EHCI_DEVICEID_8111 0x74631022
+#define PCI_EHCI_DEVICEID_8111 0x10227463
#define PCI_EHCI_DEVICEID_CS5536 0x20951022
static const char *ehci_device_8111 = "AMD 8111 USB 2.0 controller";
static const char *ehci_device_CS5536 = "AMD CS5536 USB 2.0 controller";
@@ -108,13 +108,22 @@
#define PCI_EHCI_DEVICEID_6300 0x25ad8086
static const char *ehci_device_6300 = "Intel 6300ESB USB 2.0 controller";
#define PCI_EHCI_DEVICEID_ICH4 0x24cd8086
-static const char *ehci_device_ich4 = "Intel 82801DB/L/M USB 2.0 controller";
+static const char *ehci_device_ich4 = "Intel 82801DB/L/M (ICH4) USB 2.0 controller";
#define PCI_EHCI_DEVICEID_ICH5 0x24dd8086
-static const char *ehci_device_ich5 = "Intel 82801EB/R USB 2.0 controller";
+static const char *ehci_device_ich5 = "Intel 82801EB/R (ICH5) USB 2.0 controller";
#define PCI_EHCI_DEVICEID_ICH6 0x265c8086
-static const char *ehci_device_ich6 = "Intel 82801FB USB 2.0 controller";
+static const char *ehci_device_ich6 = "Intel 82801FB (ICH6) USB 2.0 controller";
#define PCI_EHCI_DEVICEID_ICH7 0x27cc8086
-static const char *ehci_device_ich7 = "Intel 82801GB/R USB 2.0 controller";
+static const char *ehci_device_ich7 = "Intel 82801GB/R (ICH7) USB 2.0 controller";
+#define PCI_EHCI_DEVICEID_ICH8_A 0x28368086
+static const char *ehci_device_ich8_a = "Intel 82801H (ICH8) USB 2.0 controller USB2-A";
+#define PCI_EHCI_DEVICEID_ICH8_B 0x283a8086
+static const char *ehci_device_ich8_b = "Intel 82801H (ICH8) USB 2.0 controller USB2-B";
+#define PCI_EHCI_DEVICEID_ICH9_A 0x293a8086
+#define PCI_EHCI_DEVICEID_ICH9_B 0x293c8086
+static const char *ehci_device_ich9 = "Intel 82801I (ICH9) USB 2.0 controller";
+#define PCI_EHCI_DEVICEID_63XX 0x268c8086
+static const char *ehci_device_63XX = "Intel 63XXESB USB 2.0 controller";
/* NEC */
#define PCI_EHCI_DEVICEID_NEC 0x00e01033
@@ -153,11 +162,11 @@
#define DPRINTF(x)
#endif
-static int ehci_pci_attach(device_t self);
-static int ehci_pci_detach(device_t self);
-static int ehci_pci_shutdown(device_t self);
-static int ehci_pci_suspend(device_t self);
-static int ehci_pci_resume(device_t self);
+static device_attach_t ehci_pci_attach;
+static device_detach_t ehci_pci_detach;
+static device_shutdown_t ehci_pci_shutdown;
+static device_suspend_t ehci_pci_suspend;
+static device_resume_t ehci_pci_resume;
static void ehci_pci_givecontroller(device_t self);
static void ehci_pci_takecontroller(device_t self);
@@ -220,6 +229,8 @@
return (ehci_device_sb400);
case PCI_EHCI_DEVICEID_6300:
return (ehci_device_6300);
+ case PCI_EHCI_DEVICEID_63XX:
+ return (ehci_device_63XX);
case PCI_EHCI_DEVICEID_ICH4:
return (ehci_device_ich4);
case PCI_EHCI_DEVICEID_ICH5:
@@ -228,6 +239,13 @@
return (ehci_device_ich6);
case PCI_EHCI_DEVICEID_ICH7:
return (ehci_device_ich7);
+ case PCI_EHCI_DEVICEID_ICH8_A:
+ return (ehci_device_ich8_a);
+ case PCI_EHCI_DEVICEID_ICH8_B:
+ return (ehci_device_ich8_b);
+ case PCI_EHCI_DEVICEID_ICH9_A:
+ case PCI_EHCI_DEVICEID_ICH9_B:
+ return (ehci_device_ich9);
case PCI_EHCI_DEVICEID_NEC:
return (ehci_device_nec);
case PCI_EHCI_DEVICEID_NF2:
@@ -262,8 +280,7 @@
if (desc) {
device_set_desc(self, desc);
- device_set_async_attach(self, TRUE);
- return 0;
+ return BUS_PROBE_DEFAULT;
} else {
return ENXIO;
}
@@ -273,6 +290,7 @@
ehci_pci_attach(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
+ devclass_t dc;
device_t parent;
device_t *neighbors;
device_t *nbus;
@@ -290,7 +308,7 @@
case PCI_USBREV_1_0:
case PCI_USBREV_1_1:
sc->sc_bus.usbrev = USBREV_UNKNOWN;
- kprintf("pre-2.0 USB rev\n");
+ device_printf(self, "pre-2.0 USB rev\n");
return ENXIO;
case PCI_USBREV_2_0:
sc->sc_bus.usbrev = USBREV_2_0;
@@ -406,6 +424,7 @@
return ENXIO;
}
ncomp = 0;
+ dc = devclass_find("usb");
slot = pci_get_slot(self);
function = pci_get_function(self);
for (i = 0; i < count; i++) {
@@ -413,11 +432,18 @@
pci_get_function(neighbors[i]) < function) {
res = device_get_children(neighbors[i],
&nbus, &buscount);
- if (res != 0 || buscount != 1)
+ if (res != 0)
continue;
- bsc = device_get_softc(nbus[0]);
- if (bsc == NULL || bsc->bdev == NULL)
+ if (buscount != 1) {
+ kfree(nbus, M_TEMP);
+ continue;
+ }
+ if (device_get_devclass(nbus[0]) != dc) {
+ kfree(nbus, M_TEMP);
continue;
+ }
+ bsc = device_get_softc(nbus[0]);
+ kfree(nbus, M_TEMP);
DPRINTF(("ehci_pci_attach: companion %s\n",
device_get_nameunit(bsc->bdev)));
sc->sc_comps[ncomp++] = bsc;
@@ -427,6 +453,30 @@
}
sc->sc_ncomp = ncomp;
+ /* Allocate a parent dma tag for DMA maps */
+ err = bus_dma_tag_create(/*XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.parent_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate parent DMA tag (%d)\n",
+ err);
+ ehci_pci_detach(self);
+ return ENXIO;
+ }
+
+ /* Allocate a dma tag for transfer buffers */
+ err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.buffer_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate buffer DMA tag (%d)\n",
+ err);
+ ehci_pci_detach(self);
+ return ENXIO;
+ }
+
ehci_pci_takecontroller(self);
err = ehci_init(sc);
if (!err) {
@@ -457,7 +507,11 @@
*/
if (sc->iot && sc->ioh)
bus_space_write_4(sc->iot, sc->ioh, EHCI_USBINTR, 0);
-
+ if (sc->sc_bus.parent_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
+ if (sc->sc_bus.buffer_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
+
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
@@ -500,8 +554,9 @@
if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP)
continue;
legsup = eec;
- pci_write_config(self, eecp, legsup | EHCI_LEGSUP_OSOWNED, 4);
if (legsup & EHCI_LEGSUP_BIOSOWNED) {
+ pci_write_config(self, eecp,
+ legsup | EHCI_LEGSUP_OSOWNED, 4);
kprintf("%s: waiting for BIOS to give up control\n",
device_get_nameunit(sc->sc_bus.bdev));
for (i = 0; i < 5000; i++) {
@@ -520,6 +575,7 @@
static void
ehci_pci_givecontroller(device_t self)
{
+#if 0
ehci_softc_t *sc = device_get_softc(self);
u_int32_t cparams, eec, legsup;
int eecp;
@@ -533,6 +589,7 @@
legsup = eec;
pci_write_config(self, eecp, legsup & ~EHCI_LEGSUP_OSOWNED, 4);
}
+#endif
}
static device_method_t ehci_methods[] = {
Index: ehcivar.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ehcivar.h,v
retrieving revision 1.11
diff -u -r1.11 ehcivar.h
--- ehcivar.h 30 Jun 2007 20:39:22 -0000 1.11
+++ ehcivar.h 19 May 2008 10:17:44 -0000
@@ -54,6 +54,7 @@
struct ehci_soft_qh *next;
struct ehci_soft_qh *prev;
struct ehci_soft_qtd *sqtd;
+ struct ehci_soft_qtd *inactivesqtd;
ehci_physaddr_t physaddr;
int islot; /* Interrupt list slot. */
} ehci_soft_qh_t;
@@ -76,13 +77,15 @@
#define EXFER(xfer) ((struct ehci_xfer *)(xfer))
-/* Information about an entry in the interrupt list. */
+/*
+ * Information about an entry in the interrupt list.
+ */
struct ehci_soft_islot {
ehci_soft_qh_t *sqh; /* Queue Head. */
};
#define EHCI_FRAMELIST_MAXCOUNT 1024
-#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 .. 128) */
+#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 ... 128) */
#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1)
#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1))
#define EHCI_IQHIDX(lev, pos) \
Index: hid.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/hid.c,v
retrieving revision 1.13
diff -u -r1.13 hid.c
--- hid.c 28 Jun 2007 13:55:12 -0000 1.13
+++ hid.c 18 May 2008 17:51:14 -0000
@@ -95,7 +95,7 @@
{
struct hid_data *s;
- s = kmalloc(sizeof *s, M_TEMP, M_INTWAIT|M_ZERO);
+ s = kmalloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO);
s->start = s->p = d;
s->end = (char *)d + len;
s->kindset = kindset;
@@ -287,7 +287,7 @@
c->loc.count = dval;
break;
case 10: /* Push */
- hi = kmalloc(sizeof *hi, M_TEMP, M_INTWAIT);
+ hi = kmalloc(sizeof *hi, M_TEMP, M_WAITOK);
*hi = s->cur;
c->next = hi;
break;
Index: ohci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ohci.c,v
retrieving revision 1.25
diff -u -r1.25 ohci.c
--- ohci.c 20 Apr 2008 13:44:25 -0000 1.25
+++ ohci.c 19 May 2008 01:15:42 -0000
@@ -182,6 +182,8 @@
static usbd_status ohci_device_setintr(ohci_softc_t *sc,
struct ohci_pipe *pipe, int ival);
+static usbd_status ohci_device_intr_insert(ohci_softc_t *sc,
+ usbd_xfer_handle xfer);
static int ohci_str(usb_string_descriptor_t *, int, const char *);
@@ -437,35 +439,36 @@
int alen, int rd, usbd_xfer_handle xfer,
ohci_soft_td_t *sp, ohci_soft_td_t **ep)
{
- ohci_soft_td_t *next, *cur;
- ohci_physaddr_t dataphys;
+ ohci_soft_td_t *next, *cur, *end;
+ ohci_physaddr_t dataphys, physend;
u_int32_t tdflags;
int offset = 0;
- int len, curlen;
- usb_dma_t *dma = &xfer->dmabuf;
+ int len, maxp, curlen, curlen2, seg, segoff;
+ struct usb_dma_mapping *dma = &xfer->dmamap;
u_int16_t flags = xfer->flags;
DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
len = alen;
cur = sp;
+ end = NULL;
+ maxp = UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
tdflags = htole32(
(rd ? OHCI_TD_IN : OHCI_TD_OUT) |
(flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_SET_DI(6));
- for (;;) {
+ seg = 0;
+ segoff = 0;
+ while (len > 0) {
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
- dataphys = DMAADDR(dma, offset);
-
/*
* The OHCI hardware can handle at most one 4k crossing.
- * XXX - currently we only allocate contigous buffers, but
- * the OHCI spec says: If during the data transfer the buffer
+ * The OHCI spec says: If during the data transfer the buffer
* address contained in the HC's working copy of
* CurrentBufferPointer crosses a 4K boundary, the upper 20
* bits of Buffer End are copied to the working value of
@@ -490,17 +493,66 @@
* each TD except the last one must cover an exact multiple
* of the maximal packet length.
*/
- if (OHCI_PAGE_OFFSET(dataphys) + len <= (2 * OHCI_PAGE_SIZE)) {
- /* We can handle all that remains in this TD */
+ KASSERT(seg < dma->nsegs, ("ohci_alloc_std_chain: overrun"));
+ dataphys = dma->segs[seg].ds_addr + segoff;
+ curlen = dma->segs[seg].ds_len - segoff;
+ if (curlen > len)
curlen = len;
- } else {
- /* must use multiple TDs, fill as much as possible. */
+ physend = dataphys + curlen - 1;
+ if (OHCI_PAGE(dataphys) != OHCI_PAGE(physend)) {
+ /* Truncate to two OHCI pages if there are more. */
+ if (curlen > 2 * OHCI_PAGE_SIZE -
+ OHCI_PAGE_OFFSET(dataphys))
curlen = 2 * OHCI_PAGE_SIZE -
OHCI_PAGE_OFFSET(dataphys);
- /* the length must be a multiple of the max size */
- curlen -= curlen %
- UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize);
- KASSERT((curlen != 0), ("ohci_alloc_std: curlen == 0"));
+ if (curlen < len)
+ curlen -= curlen % maxp;
+ physend = dataphys + curlen - 1;
+ } else if (OHCI_PAGE_OFFSET(physend + 1) == 0 && curlen < len &&
+ curlen + segoff == dma->segs[seg].ds_len) {
+ /* We can possibly include another segment. */
+ KASSERT(seg + 1 < dma->nsegs,
+ ("ohci_alloc_std_chain: overrun2"));
+ seg++;
+
+ /* Determine how much of the second segment to use. */
+ curlen2 = dma->segs[seg].ds_len;
+ if (curlen + curlen2 > len)
+ curlen2 = len - curlen;
+ if (OHCI_PAGE(dma->segs[seg].ds_addr) !=
+ OHCI_PAGE(dma->segs[seg].ds_addr + curlen2 - 1))
+ curlen2 = OHCI_PAGE_SIZE -
+ OHCI_PAGE_OFFSET(dma->segs[seg].ds_addr);
+ if (curlen + curlen2 < len)
+ curlen2 -= (curlen + curlen2) % maxp;
+
+ if (curlen2 > 0) {
+ /* We can include a second segment */
+ segoff = curlen2;
+ physend = dma->segs[seg].ds_addr + curlen2 - 1;
+ curlen += curlen2;
+ } else {
+ /* Second segment not usable now. */
+ seg--;
+ segoff += curlen;
+ }
+ } else {
+ /* Simple case where there is just one OHCI page. */
+ segoff += curlen;
+ }
+ if (curlen == 0 && len != 0) {
+ /*
+ * A maxp length packet would need to be split.
+ * This shouldn't be possible if PAGE_SIZE >= 4k
+ * and the buffer is contiguous in virtual memory.
+ */
+ panic("ohci_alloc_std_chain: XXX need to copy");
+ }
+ if (segoff >= dma->segs[seg].ds_len) {
+ KASSERT(segoff == dma->segs[seg].ds_len,
+ ("ohci_alloc_std_chain: overlap"));
+ seg++;
+ segoff = 0;
}
DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
"len=%d curlen=%d\n",
@@ -511,27 +563,24 @@
cur->td.td_cbp = htole32(dataphys);
cur->nexttd = next;
cur->td.td_nexttd = htole32(next->physaddr);
- cur->td.td_be = htole32(DMAADDR(dma, offset + curlen - 1));
+ cur->td.td_be = htole32(physend);
cur->len = curlen;
cur->flags = OHCI_ADD_LEN;
cur->xfer = xfer;
DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
dataphys, dataphys + curlen - 1));
- if (len == 0)
- break;
if (len < 0)
panic("Length went negative: %d curlen %d dma %p offset %08x", len, curlen, dma, (int)0);
DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
offset += curlen;
+ end = cur;
cur = next;
}
- if ((flags & USBD_FORCE_SHORT_XFER) &&
+ if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
/* Force a 0 length transfer at the end. */
- cur = next;
-
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
@@ -545,8 +594,9 @@
cur->flags = 0;
cur->xfer = xfer;
DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
+ end = cur;
}
- *ep = cur;
+ *ep = end;
return (USBD_NORMAL_COMPLETION);
@@ -577,10 +627,9 @@
int i, offs;
usb_dma_t dma;
- crit_enter();
+ /* XXX: crit section? */
if (sc->sc_freeitds == NULL) {
DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
- crit_exit();
err = usb_allocmem(&sc->sc_bus,
OHCI_SITD_SIZE * OHCI_SITD_CHUNK,
OHCI_ITD_ALIGN, &dma);
@@ -594,7 +643,10 @@
sitd->nextitd = sc->sc_freeitds;
sc->sc_freeitds = sitd;
}
+ crit_exit();
}
+
+ crit_enter();
sitd = sc->sc_freeitds;
sc->sc_freeitds = sitd->nextitd;
memset(&sitd->itd, 0, sizeof(ohci_itd_t));
@@ -907,7 +959,7 @@
}
#endif
} else {
- xfer = kmalloc(sizeof(struct ohci_xfer), M_USB, M_INTWAIT);
+ xfer = kmalloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT);
}
if (xfer != NULL) {
memset(xfer, 0, sizeof (struct ohci_xfer));
@@ -925,16 +977,6 @@
ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
{
struct ohci_softc *sc = (struct ohci_softc *)bus;
- struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer;
- ohci_soft_itd_t *sitd;
-
- if (oxfer->ohci_xfer_flags & OHCI_ISOC_DIRTY) {
- crit_enter();
- for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer;
- sitd = sitd->nextitd)
- ohci_free_sitd(sc, sitd);
- crit_exit();
- }
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
@@ -1061,23 +1103,23 @@
static int ohci_intr1(ohci_softc_t *);
-int
+void
ohci_intr(void *p)
{
ohci_softc_t *sc = p;
- if (sc->sc_dying || (sc->sc_flags & OHCI_SCFLG_DONEINIT) == 0)
- return (0);
+ if (sc == NULL || sc->sc_dying)
+ return;
/* If we get an interrupt while polling, then just ignore it. */
if (sc->sc_bus.use_polling) {
#ifdef DIAGNOSTIC
- DPRINTFN(16, ("ohci_intr: ignored interrupt while polling\n"));
+ kprintf("ohci_intr: ignored interrupt while polling\n");
#endif
- return (0);
+ return;
}
- return (ohci_intr1(sc));
+ ohci_intr1(sc);
}
static int
@@ -1089,7 +1131,7 @@
DPRINTFN(14,("ohci_intr1: enter\n"));
/* In case the interrupt occurs before initialization has completed. */
- if (sc->sc_hcca == NULL) {
+ if (sc == NULL || sc->sc_hcca == NULL) {
#ifdef DIAGNOSTIC
kprintf("ohci_intr: sc->sc_hcca == NULL\n");
#endif
@@ -1451,6 +1493,11 @@
if (sitd->flags & OHCI_CALL_DONE)
break;
}
+ for (sitd = xfer->hcpriv; sitd->xfer == xfer;
+ sitd = next) {
+ next = sitd->nextitd;
+ ohci_free_sitd(sc, sitd);
+ }
crit_enter();
usb_transfer_complete(xfer);
@@ -1487,9 +1534,8 @@
{
struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
- ohci_soft_ed_t *sed = opipe->sed;
- ohci_soft_td_t *data, *tail;
+ usbd_status err;
DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
@@ -1497,32 +1543,11 @@
xfer->hcpriv = NULL;
if (xfer->pipe->repeat) {
- data = opipe->tail.td;
- tail = ohci_alloc_std(sc); /* XXX should reuse TD */
- if (tail == NULL) {
- xfer->status = USBD_NOMEM;
+ err = ohci_device_intr_insert(sc, xfer);
+ if (err) {
+ xfer->status = err;
return;
}
- tail->xfer = NULL;
-
- data->td.td_flags = htole32(
- OHCI_TD_IN | OHCI_TD_NOCC |
- OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
- if (xfer->flags & USBD_SHORT_XFER_OK)
- data->td.td_flags |= htole32(OHCI_TD_R);
- data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
- data->nexttd = tail;
- data->td.td_nexttd = htole32(tail->physaddr);
- data->td.td_be = htole32(le32toh(data->td.td_cbp) +
- xfer->length - 1);
- data->len = xfer->length;
- data->xfer = xfer;
- data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
- xfer->hcpriv = data;
- xfer->actlen = 0;
-
- sed->ed.ed_tailp = htole32(tail->physaddr);
- opipe->tail.td = tail;
}
}
@@ -1535,6 +1560,24 @@
xfer->hcpriv = NULL;
}
+/*
+ * XXX write back xfer data for architectures with a write-back
+ * data cache; this is a hack because usb is mis-architected
+ * in blindly mixing bus_dma w/ PIO.
+ */
+static __inline void
+hacksync(usbd_xfer_handle xfer)
+{
+ bus_dma_tag_t tag;
+ struct usb_dma_mapping *dmap;
+
+ if (xfer->length == 0)
+ return;
+ tag = xfer->pipe->device->bus->buffer_dmatag;
+ dmap = &xfer->dmamap;
+ bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE);
+}
+
void
ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer)
{
@@ -1554,7 +1597,7 @@
pipe = xfer->pipe;
- p = KERNADDR(&xfer->dmabuf, 0);
+ p = xfer->buffer;
m = min(sc->sc_noport, xfer->length * 8 - 1);
memset(p, 0, xfer->length);
for (i = 1; i <= m; i++) {
@@ -1566,6 +1609,7 @@
xfer->actlen = xfer->length;
xfer->status = USBD_NORMAL_COMPLETION;
+ hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
}
@@ -1643,7 +1687,6 @@
usb_device_request_t *req = &xfer->request;
usbd_device_handle dev = opipe->pipe.device;
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
- int addr = dev->address;
ohci_soft_td_t *setup, *stat, *next, *tail;
ohci_soft_ed_t *sed;
int isread;
@@ -1656,7 +1699,7 @@
DPRINTFN(3,("ohci_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), len, addr,
+ UGETW(req->wIndex), len, dev->address,
opipe->pipe.endpoint->edesc->bEndpointAddress));
setup = opipe->tail.td;
@@ -1675,15 +1718,6 @@
sed = opipe->sed;
opipe->u.ctl.length = len;
- /* Update device address and length since they may have changed
- during the setup of the control pipe in usbd_new_device(). */
- /* XXX This only needs to be done once, but it's too early in open. */
- /* XXXX Should not touch ED here! */
- sed->ed.ed_flags = htole32(
- (le32toh(sed->ed.ed_flags) & ~(OHCI_ED_ADDRMASK | OHCI_ED_MAXPMASK)) |
- OHCI_ED_SET_FA(addr) |
- OHCI_ED_SET_MAXP(UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize)));
-
next = stat;
/* Set up data transaction */
@@ -1793,22 +1827,10 @@
/* XXX */
for (p = head; p != NULL && p->next != sed; p = p->next)
;
-#if 0
if (p == NULL)
panic("ohci_rem_ed: ED not found");
-#else
- /*
- * XXX
- * p == NULL if ohci is detaching and there are still devices
- * using ohci (e.g. usb sticks are still plugged in). But
- * the real solution should be correcting ohci_free_sed() or
- * correctly use it.
- */
- if (p != NULL) {
- p->next = sed->next;
- p->ed.ed_nexted = sed->ed.ed_nexted;
- }
-#endif
+ p->next = sed->next;
+ p->ed.ed_nexted = sed->ed.ed_nexted;
}
/*
@@ -2441,7 +2463,7 @@
index = UGETW(req->wIndex);
if (len != 0)
- buf = KERNADDR(&xfer->dmabuf, 0);
+ buf = xfer->buffer;
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
@@ -2712,6 +2734,7 @@
ret:
xfer->status = err;
crit_enter();
+ hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
crit_exit();
return (USBD_IN_PROGRESS);
@@ -3019,25 +3042,43 @@
ohci_device_intr_start(usbd_xfer_handle xfer)
{
struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
- usbd_device_handle dev = opipe->pipe.device;
- ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed = opipe->sed;
- ohci_soft_td_t *data, *tail;
- int len;
+ usbd_status err;
if (sc->sc_dying)
return (USBD_IOERROR);
- DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d "
+ DPRINTFN(3, ("ohci_device_intr_start: xfer=%p len=%d "
"flags=%d priv=%p\n",
xfer, xfer->length, xfer->flags, xfer->priv));
#ifdef DIAGNOSTIC
if (xfer->rqflags & URQ_REQUEST)
- panic("ohci_device_intr_transfer: a request");
+ panic("ohci_device_intr_start: a request");
#endif
- len = xfer->length;
+ err = ohci_device_intr_insert(sc, xfer);
+ if (err)
+ return (err);
+
+ sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
+
+ return (USBD_IN_PROGRESS);
+}
+
+/*
+ * Insert an interrupt transfer into an endpoint descriptor list
+ */
+static usbd_status
+ohci_device_intr_insert(ohci_softc_t *sc, usbd_xfer_handle xfer)
+{
+ struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
+ ohci_soft_ed_t *sed = opipe->sed;
+ ohci_soft_td_t *data, *tail;
+ ohci_physaddr_t dataphys, physend;
+
+ DPRINTFN(4, ("ohci_device_intr_insert: xfer=%p", xfer));
data = opipe->tail.td;
tail = ohci_alloc_std(sc);
@@ -3050,18 +3091,43 @@
OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
if (xfer->flags & USBD_SHORT_XFER_OK)
data->td.td_flags |= htole32(OHCI_TD_R);
- data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0));
+ /*
+ * Assume a short mapping with no complications, which
+ * should always be true for <= 4k buffers in contiguous
+ * virtual memory. The data can take the following forms:
+ * 1 segment in 1 OHCI page
+ * 1 segment in 2 OHCI pages
+ * 2 segments in 2 OHCI pages
+ * (see comment in ohci_alloc_std_chain() for details)
+ */
+ KASSERT(xfer->length > 0 && xfer->length <= OHCI_PAGE_SIZE,
+ ("ohci_device_intr_insert: bad length %d", xfer->length));
+ dataphys = xfer->dmamap.segs[0].ds_addr;
+ physend = dataphys + xfer->length - 1;
+ if (xfer->dmamap.nsegs == 2) {
+ KASSERT(OHCI_PAGE_OFFSET(dataphys +
+ xfer->dmamap.segs[0].ds_len) == 0,
+ ("ohci_device_intr_insert: bad seg 0 termination"));
+ physend = xfer->dmamap.segs[1].ds_addr + xfer->length -
+ xfer->dmamap.segs[0].ds_len - 1;
+ } else {
+ KASSERT(xfer->dmamap.nsegs == 1,
+ ("ohci_device_intr_insert: bad seg count %d",
+ (u_int)xfer->dmamap.nsegs));
+ }
+ data->td.td_cbp = htole32(dataphys);
data->nexttd = tail;
data->td.td_nexttd = htole32(tail->physaddr);
- data->td.td_be = htole32(le32toh(data->td.td_cbp) + len - 1);
- data->len = len;
+ data->td.td_be = htole32(physend);
+ data->len = xfer->length;
data->xfer = xfer;
data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
xfer->hcpriv = data;
+ xfer->actlen = 0;
#ifdef USB_DEBUG
if (ohcidebug > 5) {
- DPRINTF(("ohci_device_intr_transfer:\n"));
+ DPRINTF(("ohci_device_intr_insert:\n"));
ohci_dump_ed(sed);
ohci_dump_tds(data);
}
@@ -3071,25 +3137,9 @@
crit_enter();
sed->ed.ed_tailp = htole32(tail->physaddr);
opipe->tail.td = tail;
- sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
-
-#if 0
-/*
- * This goes horribly wrong, printing thousands of descriptors,
- * because false references are followed due to the fact that the
- * TD is gone.
- */
- if (ohcidebug > 5) {
- usb_delay_ms(&sc->sc_bus, 5);
- DPRINTF(("ohci_device_intr_transfer: status=%x\n",
- OREAD4(sc, OHCI_COMMAND_STATUS)));
- ohci_dump_ed(sed);
- ohci_dump_tds(data);
- }
-#endif
crit_exit();
- return (USBD_IN_PROGRESS);
+ return (USBD_NORMAL_COMPLETION);
}
/* Abort a device control request. */
@@ -3243,10 +3293,10 @@
ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
ohci_soft_ed_t *sed = opipe->sed;
struct iso *iso = &opipe->u.iso;
- struct ohci_xfer *oxfer = (struct ohci_xfer *)xfer;
+ struct usb_dma_mapping *dma = &xfer->dmamap;
ohci_soft_itd_t *sitd, *nsitd;
- ohci_physaddr_t buf, offs, noffs, bp0, tdphys;
- int i, ncur, nframes;
+ ohci_physaddr_t dataphys, bp0, physend, prevpage;
+ int curlen, i, len, ncur, nframes, npages, seg, segoff;
DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
"nframes=%d\n",
@@ -3262,96 +3312,116 @@
iso->next));
}
- if (xfer->hcpriv) {
- crit_enter();
- for (sitd = xfer->hcpriv; sitd != NULL && sitd->xfer == xfer;
- sitd = sitd->nextitd)
- ohci_free_sitd(sc, sitd); /* Free ITDs in prev xfer*/
- crit_exit();
-
- if (sitd == NULL) {
- sitd = ohci_alloc_sitd(sc);
- if (sitd == NULL)
- panic("can't alloc isoc");
- opipe->tail.itd = sitd;
- tdphys = sitd->physaddr;
- sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* Stop*/
- sed->ed.ed_headp =
- sed->ed.ed_tailp = htole32(tdphys);
- sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* Start.*/
- }
- }
-
sitd = opipe->tail.itd;
- buf = DMAADDR(&xfer->dmabuf, 0);
- bp0 = OHCI_PAGE(buf);
- offs = OHCI_PAGE_OFFSET(buf);
nframes = xfer->nframes;
xfer->hcpriv = sitd;
- for (i = ncur = 0; i < nframes; i++, ncur++) {
- noffs = offs + xfer->frlengths[i];
- if (ncur == OHCI_ITD_NOFFSET || /* all offsets used */
- OHCI_PAGE(buf + noffs) > bp0 + OHCI_PAGE_SIZE) { /* too many page crossings */
-
- /* Allocate next ITD */
- nsitd = ohci_alloc_sitd(sc);
- if (nsitd == NULL) {
- /* XXX what now? */
- kprintf("%s: isoc TD alloc failed\n",
- device_get_nameunit(sc->sc_bus.bdev));
- return;
+ seg = 0;
+ segoff = 0;
+ i = 0;
+ while (i < nframes) {
+ /*
+ * Fill in as many ITD frames as possible.
+ */
+ KASSERT(seg < dma->nsegs, ("ohci_device_isoc_enter: overrun"));
+ bp0 = dma->segs[seg].ds_addr + segoff;
+ sitd->itd.itd_bp0 = htole32(bp0);
+ prevpage = OHCI_PAGE(bp0);
+ npages = 1;
+
+ ncur = 0;
+ while (ncur < OHCI_ITD_NOFFSET && i < nframes) {
+ /* Find the frame start and end physical addresses. */
+ len = xfer->frlengths[i];
+ dataphys = dma->segs[seg].ds_addr + segoff;
+ curlen = dma->segs[seg].ds_len - segoff;
+ if (len > curlen) {
+ KASSERT(seg + 1 < dma->nsegs,
+ ("ohci_device_isoc_enter: overrun2"));
+ seg++;
+ segoff = len - curlen;
+ } else {
+ segoff += len;
+ }
+ KASSERT(segoff <= dma->segs[seg].ds_len,
+ ("ohci_device_isoc_enter: overrun3"));
+ physend = dma->segs[seg].ds_addr + segoff - 1;
+
+ /* Check if there would be more than 2 pages . */
+ if (OHCI_PAGE(dataphys) != prevpage) {
+ prevpage = OHCI_PAGE(dataphys);
+ npages++;
+ }
+ if (OHCI_PAGE(physend) != prevpage) {
+ prevpage = OHCI_PAGE(physend);
+ npages++;
+ }
+ if (npages > 2) {
+ /* We cannot fit this frame now. */
+ segoff -= len;
+ if (segoff < 0) {
+ seg--;
+ segoff += dma->segs[seg].ds_len;
+ }
+ break;
}
- /* Fill current ITD */
+ sitd->itd.itd_be = htole32(physend);
+ sitd->itd.itd_offset[ncur] =
+ htole16(OHCI_ITD_MK_OFFS(OHCI_PAGE(dataphys) ==
+ OHCI_PAGE(bp0) ? 0 : 1, dataphys));
+ i++;
+ ncur++;
+ }
+ if (segoff >= dma->segs[seg].ds_len) {
+ KASSERT(segoff == dma->segs[seg].ds_len,
+ ("ohci_device_isoc_enter: overlap"));
+ seg++;
+ segoff = 0;
+ }
+
+ /* Allocate next ITD */
+ nsitd = ohci_alloc_sitd(sc);
+ if (nsitd == NULL) {
+ /* XXX what now? */
+ kprintf("%s: isoc TD alloc failed\n",
+ device_get_nameunit(sc->sc_bus.bdev));
+ return;
+ }
+
+ /* Fill out remaining fields of current ITD */
+ sitd->nextitd = nsitd;
+ sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
+ sitd->xfer = xfer;
+ if (i < nframes) {
sitd->itd.itd_flags = htole32(
OHCI_ITD_NOCC |
OHCI_ITD_SET_SF(iso->next) |
OHCI_ITD_SET_DI(6) | /* delay intr a little */
OHCI_ITD_SET_FC(ncur));
- sitd->itd.itd_bp0 = htole32(bp0);
- sitd->nextitd = nsitd;
- sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
- sitd->itd.itd_be = htole32(bp0 + offs - 1);
- sitd->xfer = xfer;
sitd->flags = OHCI_ITD_ACTIVE;
- sitd = nsitd;
- iso->next = iso->next + ncur;
- bp0 = OHCI_PAGE(buf + offs);
- ncur = 0;
- }
- sitd->itd.itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS(offs));
- offs = noffs;
- }
- nsitd = ohci_alloc_sitd(sc);
- if (nsitd == NULL) {
- /* XXX what now? */
- kprintf("%s: isoc TD alloc failed\n",
- device_get_nameunit(sc->sc_bus.bdev));
- return;
+ } else {
+ sitd->itd.itd_flags = htole32(
+ OHCI_ITD_NOCC |
+ OHCI_ITD_SET_SF(iso->next) |
+ OHCI_ITD_SET_DI(0) |
+ OHCI_ITD_SET_FC(ncur));
+ sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE;
+ }
+ iso->next += ncur;
+
+ sitd = nsitd;
}
- /* Fixup last used ITD */
- sitd->itd.itd_flags = htole32(
- OHCI_ITD_NOCC |
- OHCI_ITD_SET_SF(iso->next) |
- OHCI_ITD_SET_DI(0) |
- OHCI_ITD_SET_FC(ncur));
- sitd->itd.itd_bp0 = htole32(bp0);
- sitd->nextitd = nsitd;
- sitd->itd.itd_nextitd = htole32(nsitd->physaddr);
- sitd->itd.itd_be = htole32(bp0 + offs - 1);
- sitd->xfer = xfer;
- sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE;
- iso->next = iso->next + ncur;
iso->inuse += nframes;
- xfer->actlen = offs; /* XXX pretend we did it all */
+ /* XXX pretend we did it all */
+ xfer->actlen = 0;
+ for (i = 0; i < nframes; i++)
+ xfer->actlen += xfer->frlengths[i];
xfer->status = USBD_IN_PROGRESS;
- oxfer->ohci_xfer_flags |= OHCI_ISOC_DIRTY;
-
#ifdef USB_DEBUG
if (ohcidebug > 5) {
DPRINTF(("ohci_device_isoc_enter: frame=%d\n",
@@ -3362,9 +3432,9 @@
#endif
crit_enter();
- sed->ed.ed_tailp = htole32(nsitd->physaddr);
- opipe->tail.itd = nsitd;
+ opipe->tail.itd = sitd;
sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
+ sed->ed.ed_tailp = htole32(sitd->physaddr);
crit_exit();
#ifdef USB_DEBUG
@@ -3411,7 +3481,7 @@
struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed;
- ohci_soft_itd_t *sitd, *tmp_sitd;
+ ohci_soft_itd_t *sitd, *sitdnext, *tmp_sitd;
int undone, num_sitds;
crit_enter();
@@ -3474,19 +3544,20 @@
}
} while( undone != 0 );
+ /* Free the sitds */
+ for (sitd = xfer->hcpriv; sitd->xfer == xfer;
+ sitd = sitdnext) {
+ sitdnext = sitd->nextitd;
+ ohci_free_sitd(sc, sitd);
+ }
+
crit_enter();
/* Run callback. */
usb_transfer_complete(xfer);
- if (sitd != NULL)
- /*
- * Only if there is a `next' sitd in next xfer...
- * unlink this xfer's sitds.
- */
- sed->ed.ed_headp = htole32(sitd->physaddr);
- else
- sed->ed.ed_headp = 0;
+ /* There is always a `next' sitd so link it up. */
+ sed->ed.ed_headp = htole32(sitd->physaddr);
sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */
Index: ohci_pci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ohci_pci.c,v
retrieving revision 1.9
diff -u -r1.9 ohci_pci.c
--- ohci_pci.c 24 Aug 2007 16:02:47 -0000 1.9
+++ ohci_pci.c 19 May 2008 00:26:21 -0000
@@ -126,11 +126,10 @@
#define PCI_OHCI_BASE_REG 0x10
-
-static int ohci_pci_attach(device_t self);
-static int ohci_pci_detach(device_t self);
-static int ohci_pci_suspend(device_t self);
-static int ohci_pci_resume(device_t self);
+static device_attach_t ohci_pci_attach;
+static device_detach_t ohci_pci_detach;
+static device_suspend_t ohci_pci_suspend;
+static device_resume_t ohci_pci_resume;
static int
ohci_pci_suspend(device_t self)
@@ -151,20 +150,6 @@
{
ohci_softc_t *sc = device_get_softc(self);
-#ifndef BURN_BRIDGES
- uint32_t reg, int_line;
-
- if (pci_get_powerstate(self) != PCI_POWERSTATE_D0) {
- device_printf(self, "chip is in D%d mode "
- "-- setting to D0\n", pci_get_powerstate(self));
- reg = pci_read_config(self, PCI_CBMEM, 4);
- int_line = pci_read_config(self, PCIR_INTLINE, 4);
- pci_set_powerstate(self, PCI_POWERSTATE_D0);
- pci_write_config(self, PCI_CBMEM, reg, 4);
- pci_write_config(self, PCIR_INTLINE, int_line, 4);
- }
-#endif /* !BURN_BRIDGES */
-
ohci_power(PWR_RESUME, sc);
bus_generic_resume(self);
@@ -222,8 +207,7 @@
if (desc) {
device_set_desc(self, desc);
- device_set_async_attach(self, TRUE);
- return 0;
+ return BUS_PROBE_DEFAULT;
} else {
return ENXIO;
}
@@ -321,6 +305,30 @@
ohci_pci_detach(self);
return ENXIO;
}
+
+ /* Allocate a parent dma tag for DMA maps */
+ err = bus_dma_tag_create(/*XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.parent_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate parent DMA tag (%d)\n",
+ err);
+ ohci_pci_detach(self);
+ return ENXIO;
+ }
+ /* Allocate a dma tag for transfer buffers */
+ err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.buffer_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate transfer tag (%d)\n",
+ err);
+ ohci_pci_detach(self);
+ return ENXIO;
+ }
+
err = ohci_init(sc);
if (!err) {
sc->sc_flags |= OHCI_SCFLG_DONEINIT;
@@ -345,6 +353,11 @@
sc->sc_flags &= ~OHCI_SCFLG_DONEINIT;
}
+ if (sc->sc_bus.parent_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
+ if (sc->sc_bus.buffer_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
+
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
Index: ohcireg.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ohcireg.h,v
retrieving revision 1.4
diff -u -r1.4 ohcireg.h
--- ohcireg.h 10 Dec 2006 02:03:56 -0000 1.4
+++ ohcireg.h 19 May 2008 00:19:46 -0000
@@ -221,7 +221,8 @@
u_int16_t itd_offset[OHCI_ITD_NOFFSET]; /* Buffer offsets */
#define itd_pswn itd_offset /* Packet Status Word*/
#define OHCI_ITD_PAGE_SELECT 0x00001000
-#define OHCI_ITD_MK_OFFS(len) (0xe000 | ((len) & 0x1fff))
+#define OHCI_ITD_MK_OFFS(page, off) \
+ (0xe000 | ((page) ? OHCI_ITD_PAGE_SELECT : 0) | ((off) & 0xfff))
#define OHCI_ITD_PSW_LENGTH(x) ((x) & 0xfff) /* Transfer length */
#define OHCI_ITD_PSW_GET_CC(x) ((x) >> 12) /* Condition Code */
} ohci_itd_t;
Index: ohcivar.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/ohcivar.h,v
retrieving revision 1.9
diff -u -r1.9 ohcivar.h
--- ohcivar.h 30 Jun 2007 20:39:22 -0000 1.9
+++ ohcivar.h 19 May 2008 00:18:53 -0000
@@ -149,17 +149,16 @@
struct usb_task abort_task;
u_int32_t ohci_xfer_flags;
};
-#define OHCI_ISOC_DIRTY 0x01
-#define OHCI_XFER_ABORTING 0x02 /* xfer is aborting. */
-#define OHCI_XFER_ABORTWAIT 0x04 /* abort completion is being awaited. */
+#define OHCI_XFER_ABORTING 0x01 /* xfer is aborting. */
+#define OHCI_XFER_ABORTWAIT 0x02 /* abort completion is being awaited. */
#define OXFER(xfer) ((struct ohci_xfer *)(xfer))
+#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
usbd_status ohci_init(ohci_softc_t *);
-int ohci_intr(void *);
+void ohci_intr(void *);
int ohci_detach(ohci_softc_t *, int);
-#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
void ohci_shutdown(void *v);
void ohci_power(int state, void *priv);
Index: uhci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/uhci.c,v
retrieving revision 1.25
diff -u -r1.25 uhci.c
--- uhci.c 29 Jun 2007 22:56:31 -0000 1.25
+++ uhci.c 18 May 2008 23:54:10 -0000
@@ -153,6 +153,10 @@
static void uhci_free_std(uhci_softc_t *, uhci_soft_td_t *);
static uhci_soft_qh_t *uhci_alloc_sqh(uhci_softc_t *);
static void uhci_free_sqh(uhci_softc_t *, uhci_soft_qh_t *);
+static usbd_status uhci_aux_dma_alloc(uhci_softc_t *, uhci_soft_td_t *,
+ void *data, int len);
+static uhci_physaddr_t uhci_aux_dma_prepare(uhci_soft_td_t *, int);
+static void uhci_aux_dma_complete(uhci_soft_td_t *, int);
#if 0
static void uhci_enter_ctl_q(uhci_softc_t *, uhci_soft_qh_t *,
uhci_intr_info_t *);
@@ -162,7 +166,8 @@
static void uhci_free_std_chain(uhci_softc_t *,
uhci_soft_td_t *, uhci_soft_td_t *);
static usbd_status uhci_alloc_std_chain(struct uhci_pipe *,
- uhci_softc_t *, int, int, u_int16_t, usb_dma_t *,
+ uhci_softc_t *, int, int, u_int16_t,
+ usbd_xfer_handle xfer,
uhci_soft_td_t **, uhci_soft_td_t **);
static void uhci_poll_hub(void *);
static void uhci_waitintr(uhci_softc_t *, usbd_xfer_handle);
@@ -170,6 +175,7 @@
static void uhci_idone(uhci_intr_info_t *);
static void uhci_abort_xfer(usbd_xfer_handle, usbd_status status);
+static void uhci_transfer_complete(usbd_xfer_handle xfer);
static void uhci_timeout(void *);
static void uhci_timeout_task(void *);
@@ -456,7 +462,7 @@
clsqh = uhci_alloc_sqh(sc);
if (clsqh == NULL)
return (USBD_NOMEM);
- clsqh->hlink = bsqh;
+ clsqh->hlink = chsqh;
clsqh->qh.qh_hlink = htole32(chsqh->physaddr | UHCI_PTR_QH);
clsqh->elink = NULL;
clsqh->qh.qh_elink = htole32(UHCI_PTR_T);
@@ -473,7 +479,6 @@
if (std == NULL || sqh == NULL)
return (USBD_NOMEM);
std->link.sqh = sqh;
-
std->td.td_link = htole32(sqh->physaddr | UHCI_PTR_QH);
std->td.td_status = htole32(UHCI_TD_IOS); /* iso, inactive */
std->td.td_token = htole32(0);
@@ -518,6 +523,8 @@
usbd_xfer_handle xfer;
int rv = 0;
+ sc->sc_dying = 1;
+
UWRITE2(sc, UHCI_INTR, 0); /* disable interrupts */
uhci_run(sc, 0);
@@ -564,7 +571,7 @@
}
#endif
} else {
- xfer = kmalloc(sizeof(struct uhci_xfer), M_USB, M_INTWAIT);
+ xfer = kmalloc(sizeof(struct uhci_xfer), M_USB, M_NOWAIT);
}
if (xfer != NULL) {
memset(xfer, 0, sizeof (struct uhci_xfer));
@@ -640,6 +647,7 @@
callout_stop(&sc->sc_poll_handle);
sc->sc_bus.use_polling++;
uhci_run(sc, 0); /* stop the controller */
+ cmd &= ~UHCI_CMD_RS;
/* save some state if BIOS doesn't */
sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM);
@@ -749,6 +757,7 @@
le32toh(sqh->qh.qh_elink)));
}
+
#if 1
void
uhci_dump(void)
@@ -766,6 +775,7 @@
uhci_dump_qh(sc->sc_lctl_start);
}
+
void
uhci_dump_qhs(uhci_soft_qh_t *sqh)
{
@@ -889,14 +899,15 @@
{
usbd_xfer_handle xfer = addr;
usbd_pipe_handle pipe = xfer->pipe;
- uhci_softc_t *sc = (uhci_softc_t *)pipe->device->bus;
+ usbd_device_handle dev = pipe->device;
+ uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
u_char *p;
DPRINTFN(20, ("uhci_poll_hub\n"));
callout_reset(&sc->sc_poll_handle, sc->sc_ival, uhci_poll_hub, xfer);
- p = KERNADDR(&xfer->dmabuf, 0);
+ p = xfer->buffer;
p[0] = 0;
if (UREAD2(sc, UHCI_PORTSC1) & (UHCI_PORTSC_CSC|UHCI_PORTSC_OCIC))
p[0] |= 1<<1;
@@ -909,9 +920,9 @@
xfer->actlen = 1;
xfer->status = USBD_NORMAL_COMPLETION;
crit_enter();
- xfer->device->bus->intr_context++;
- usb_transfer_complete(xfer);
- xfer->device->bus->intr_context--;
+ dev->bus->intr_context++;
+ uhci_transfer_complete(xfer);
+ dev->bus->intr_context--;
crit_exit();
}
@@ -1085,13 +1096,13 @@
{
uhci_softc_t *sc = arg;
- if (sc->sc_dying || (sc->sc_flags & UHCI_SCFLG_DONEINIT) == 0)
+ if (sc->sc_dying)
return (0);
DPRINTFN(15,("uhci_intr: real interrupt\n"));
if (sc->sc_bus.use_polling) {
#ifdef DIAGNOSTIC
- DPRINTFN(16, ("uhci_intr: ignored interrupt while polling\n"));
+ kprintf("uhci_intr: ignored interrupt while polling\n");
#endif
return (0);
}
@@ -1265,7 +1276,7 @@
/* We want short packets, and it is short: it's done */
if ((status & UHCI_TD_SPD) &&
UHCI_TD_GET_ACTLEN(status) <
- UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) {
+ UHCI_TD_GET_MAXLEN(le32toh(std->td.td_token))) {
goto done;
}
}
@@ -1358,7 +1369,8 @@
if (UHCI_TD_GET_PID(le32toh(std->td.td_token)) !=
UHCI_TD_PID_SETUP) {
actlen += UHCI_TD_GET_ACTLEN(status);
- } else {
+ }
+ else {
/*
* UHCI will report CRCTO in addition to a STALL or NAK
* for a SETUP transaction. See section 3.2.2, "TD
@@ -1402,7 +1414,7 @@
}
end:
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
DPRINTFN(12, ("uhci_idone: ii=%p done\n", ii));
}
@@ -1563,6 +1575,9 @@
std = KERNADDR(&dma, offs);
std->physaddr = DMAADDR(&dma, offs);
std->link.std = sc->sc_freetds;
+ std->aux_dma.block = NULL;
+ std->aux_data = NULL;
+ std->aux_len = 0;
sc->sc_freetds = std;
}
}
@@ -1583,6 +1598,12 @@
}
std->td.td_token = htole32(TD_IS_FREE);
#endif
+ if (std->aux_dma.block != NULL) {
+ usb_freemem(&sc->sc_bus, &std->aux_dma);
+ std->aux_dma.block = NULL;
+ std->aux_data = NULL;
+ std->aux_len = 0;
+ }
std->link.std = sc->sc_freetds;
sc->sc_freetds = std;
}
@@ -1636,12 +1657,12 @@
usbd_status
uhci_alloc_std_chain(struct uhci_pipe *upipe, uhci_softc_t *sc, int len,
- int rd, u_int16_t flags, usb_dma_t *dma,
+ int rd, u_int16_t flags, usbd_xfer_handle xfer,
uhci_soft_td_t **sp, uhci_soft_td_t **ep)
{
- uhci_soft_td_t *p, *lastp;
- uhci_physaddr_t lastlink;
- int i, ntd, l, tog, maxp;
+ struct usb_dma_mapping *dma = &xfer->dmamap;
+ uhci_soft_td_t *p, *prevp, *startp;
+ int err, i, ntd, l, tog, maxp, seg, segoff;
u_int32_t status;
int addr = upipe->pipe.device->address;
int endpt = upipe->pipe.endpoint->edesc->bEndpointAddress;
@@ -1655,38 +1676,38 @@
return (USBD_INVAL);
}
ntd = (len + maxp - 1) / maxp;
+ if (len == 0)
+ flags |= USBD_FORCE_SHORT_XFER;
if ((flags & USBD_FORCE_SHORT_XFER) && len % maxp == 0)
ntd++;
DPRINTFN(10, ("uhci_alloc_std_chain: maxp=%d ntd=%d\n", maxp, ntd));
- if (ntd == 0) {
- *sp = *ep = 0;
- DPRINTFN(-1,("uhci_alloc_std_chain: ntd=0\n"));
- return (USBD_NORMAL_COMPLETION);
- }
+ KASSERT(ntd > 0, ("uhci_alloc_std_chain: ntd=0"));
tog = upipe->nexttoggle;
- if (ntd % 2 == 0)
- tog ^= 1;
- upipe->nexttoggle = tog ^ 1;
- lastp = NULL;
- lastlink = UHCI_PTR_T;
- ntd--;
+ prevp = NULL;
+ startp = NULL;
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(3) | UHCI_TD_ACTIVE);
if (upipe->pipe.device->speed == USB_SPEED_LOW)
status |= UHCI_TD_LS;
if (flags & USBD_SHORT_XFER_OK)
status |= UHCI_TD_SPD;
- for (i = ntd; i >= 0; i--) {
+ seg = 0;
+ segoff = 0;
+ for (i = 0; i < ntd; i++) {
p = uhci_alloc_std(sc);
if (p == NULL) {
- uhci_free_std_chain(sc, lastp, NULL);
+ uhci_free_std_chain(sc, startp, NULL);
return (USBD_NOMEM);
}
- p->link.std = lastp;
- p->td.td_link = htole32(lastlink | UHCI_PTR_VF | UHCI_PTR_TD);
- lastp = p;
- lastlink = p->physaddr;
+ p->link.std = NULL;
+ if (prevp != NULL) {
+ prevp->link.std = p;
+ prevp->td.td_link = htole32(p->physaddr | UHCI_PTR_VF |
+ UHCI_PTR_TD);
+ } else {
+ startp = p;
+ }
p->td.td_status = htole32(status);
- if (i == ntd) {
+ if (i == ntd - 1) {
/* last TD */
l = len % maxp;
if (l == 0 && !(flags & USBD_FORCE_SHORT_XFER))
@@ -1697,15 +1718,102 @@
p->td.td_token =
htole32(rd ? UHCI_TD_IN (l, endpt, addr, tog) :
UHCI_TD_OUT(l, endpt, addr, tog));
- p->td.td_buffer = htole32(DMAADDR(dma, i * maxp));
+
+ KASSERT(seg < dma->nsegs || l == 0,
+ ("uhci_alloc_std_chain: too few segments"));
+ if (l == 0) {
+ p->td.td_buffer = 0;
+ } else if (l > dma->segs[seg].ds_len - segoff) {
+ /* UHCI can't handle non-contiguous data. */
+ err = uhci_aux_dma_alloc(sc, p, (char *)xfer->buffer +
+ i * maxp, l);
+ if (err) {
+ uhci_free_std_chain(sc, startp, NULL);
+ return (err);
+ }
+ p->td.td_buffer = htole32(uhci_aux_dma_prepare(p, rd));
+ l -= dma->segs[seg].ds_len - segoff;
+ seg++;
+ KASSERT(seg < dma->nsegs,
+ ("uhci_alloc_std_chain: too few segments 2"));
+ segoff = 0;
+ } else {
+ p->td.td_buffer = htole32(dma->segs[seg].ds_addr +
+ segoff);
+ }
+ segoff += l;
+ if (l > 0 && segoff >= dma->segs[seg].ds_len) {
+ KASSERT(segoff == dma->segs[seg].ds_len,
+ ("uhci_alloc_std_chain: overlap"));
+ if (i * maxp + l != len) {
+ seg++;
+ segoff = 0;
+ }
+ }
+ prevp = p;
tog ^= 1;
}
- *sp = lastp;
+ prevp->td.td_link = htole32(UHCI_PTR_T | UHCI_PTR_VF | UHCI_PTR_TD);
+ upipe->nexttoggle = tog;
+ *sp = startp;
DPRINTFN(10, ("uhci_alloc_std_chain: nexttog=%d\n",
upipe->nexttoggle));
return (USBD_NORMAL_COMPLETION);
}
+/*
+ * Allocate a physically contiguous buffer to handle cases where UHCI
+ * cannot handle a packet because it is not physically contiguous.
+ * If the usb_dma_t was already allocated this just ensures it is
+ * large enough for the specified size.
+ */
+static usbd_status
+uhci_aux_dma_alloc(uhci_softc_t *sc, uhci_soft_td_t *std, void *data, int len)
+{
+ int err, align;
+
+ if (std->aux_dma.block == NULL || std->aux_dma.block->size < len) {
+ /* Align to avoid crossing a page boundary. */
+ if (powerof2(len))
+ align = len;
+ else
+ align = 1 << fls(len);
+
+ if (std->aux_dma.block != NULL)
+ usb_freemem(&sc->sc_bus, &std->aux_dma);
+ std->aux_dma.block = NULL;
+ err = usb_allocmem(&sc->sc_bus, len, align, &std->aux_dma);
+ if (err)
+ return (err);
+ }
+ std->aux_data = data;
+ std->aux_len = len;
+
+ return (USBD_NORMAL_COMPLETION);
+}
+
+static uhci_physaddr_t
+uhci_aux_dma_prepare(uhci_soft_td_t *std, int isread)
+{
+ if (!isread) {
+ bcopy(std->aux_data, KERNADDR(&std->aux_dma, 0), std->aux_len);
+ bus_dmamap_sync(std->aux_dma.block->tag,
+ std->aux_dma.block->map, BUS_DMASYNC_PREWRITE);
+ }
+
+ return (DMAADDR(&std->aux_dma, 0));
+}
+
+static void
+uhci_aux_dma_complete(uhci_soft_td_t *std, int isread)
+{
+ if (isread) {
+ bus_dmamap_sync(std->aux_dma.block->tag,
+ std->aux_dma.block->map, BUS_DMASYNC_POSTREAD);
+ bcopy(KERNADDR(&std->aux_dma, 0), std->aux_data, std->aux_len);
+ }
+}
+
void
uhci_device_clear_toggle(usbd_pipe_handle pipe)
{
@@ -1766,8 +1874,8 @@
upipe->u.bulk.isread = isread;
upipe->u.bulk.length = len;
- err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
- &xfer->dmabuf, &data, &dataend);
+ err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags, xfer,
+ &data, &dataend);
if (err)
return (err);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
@@ -1827,7 +1935,7 @@
/*
* Abort a device request.
- * If this routine is called from a critical section. It guarantees that
+ * If this routine is called from a critical section it guarantees that
* the request will be removed from the hardware scheduling and that
* the callback for it will be called with USBD_CANCELLED status.
* It's impossible to guarantee that the requested transfer will not
@@ -1852,7 +1960,7 @@
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task);
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
crit_exit();
return;
}
@@ -1920,10 +2028,50 @@
uxfer->uhci_xfer_flags &= ~UHCI_XFER_ABORTWAIT;
wakeup(&uxfer->uhci_xfer_flags);
}
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
crit_exit();
}
+/*
+ * Perform any UHCI-specific transfer completion operations, then
+ * call usb_transfer_complete().
+ */
+static void
+uhci_transfer_complete(usbd_xfer_handle xfer)
+{
+ uhci_intr_info_t *ii = &UXFER(xfer)->iinfo;
+ struct uhci_pipe *upipe = (struct uhci_pipe *)xfer->pipe;
+ uhci_soft_td_t *p;
+ int i, isread, n;
+
+ /* XXX, must be an easier way to detect reads... */
+ isread = ((xfer->rqflags & URQ_REQUEST) &&
+ (xfer->request.bmRequestType & UT_READ)) ||
+ (xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN);
+
+ /* Copy back from any auxillary buffers after a read operation. */
+ if (xfer->nframes == 0) {
+ for (p = ii->stdstart; p != NULL; p = p->link.std) {
+ if (p->aux_data != NULL)
+ uhci_aux_dma_complete(p, isread);
+ }
+ } else {
+ if (xfer->nframes != 0) {
+ /* Isoc transfer, do things differently. */
+ n = UXFER(xfer)->curframe;
+ for (i = 0; i < xfer->nframes; i++) {
+ p = upipe->u.iso.stds[n];
+ if (p->aux_data != NULL)
+ uhci_aux_dma_complete(p, isread);
+ if (++n >= UHCI_VFRAMELIST_COUNT)
+ n = 0;
+ }
+ }
+ }
+
+ usb_transfer_complete(xfer);
+}
+
/* Close a device bulk pipe. */
void
uhci_device_bulk_close(usbd_pipe_handle pipe)
@@ -2023,9 +2171,8 @@
upipe->u.intr.isread = isread;
- err = uhci_alloc_std_chain(upipe, sc, xfer->length, isread,
- xfer->flags, &xfer->dmabuf, &data,
- &dataend);
+ err = uhci_alloc_std_chain(upipe, sc, xfer->length, isread, xfer->flags,
+ xfer, &data, &dataend);
if (err)
return (err);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
@@ -2161,7 +2308,7 @@
if (len != 0) {
upipe->nexttoggle = 1;
err = uhci_alloc_std_chain(upipe, sc, len, isread, xfer->flags,
- &xfer->dmabuf, &data, &dataend);
+ xfer, &data, &dataend);
if (err)
return (err);
next = data;
@@ -2288,8 +2435,9 @@
uhci_softc_t *sc = (uhci_softc_t *)dev->bus;
struct iso *iso = &upipe->u.iso;
uhci_soft_td_t *std;
- u_int32_t buf, len, status;
- int i, next, nframes;
+ void *dataptr;
+ u_int32_t len, status;
+ int err, i, isread, next, nframes, seg, segoff;
DPRINTFN(5,("uhci_device_isoc_enter: used=%d next=%d xfer=%p "
"nframes=%d\n",
@@ -2319,7 +2467,10 @@
xfer->status = USBD_IN_PROGRESS;
UXFER(xfer)->curframe = next;
- buf = DMAADDR(&xfer->dmabuf, 0);
+ seg = 0;
+ segoff = 0;
+ dataptr = xfer->allocbuf; /* Normal buffers not possible for isoc? */
+ isread = xfer->pipe->endpoint->edesc->bEndpointAddress & UE_DIR_IN;
status = UHCI_TD_ZERO_ACTLEN(UHCI_TD_SET_ERRCNT(0) |
UHCI_TD_ACTIVE |
UHCI_TD_IOS);
@@ -2330,7 +2481,35 @@
if (++next >= UHCI_VFRAMELIST_COUNT)
next = 0;
len = xfer->frlengths[i];
- std->td.td_buffer = htole32(buf);
+ KASSERT(seg < xfer->dmamap.nsegs,
+ ("uhci_device_isoc_enter: too few segments"));
+ if (len + segoff > xfer->dmamap.segs[seg].ds_len) {
+ /* UHCI can't handle non-contiguous data. */
+ err = uhci_aux_dma_alloc(sc, std, dataptr, len);
+ /* XXX */
+ if (err)
+ kprintf("uhci_device_isoc_enter: aux alloc\n");
+ std->td.td_buffer = htole32(uhci_aux_dma_prepare(std,
+ isread));
+ segoff += len;
+ while (segoff >= xfer->dmamap.segs[seg].ds_len) {
+ KASSERT(seg < xfer->dmamap.nsegs - 1 ||
+ segoff == xfer->dmamap.segs[seg].ds_len,
+ ("uhci_device_isoc_enter: overlap2"));
+ segoff -= xfer->dmamap.segs[seg].ds_len;
+ seg++;
+ }
+ } else {
+ std->td.td_buffer =
+ htole32(xfer->dmamap.segs[seg].ds_addr + segoff);
+ segoff += len;
+ if (segoff >= xfer->dmamap.segs[seg].ds_len) {
+ KASSERT(segoff == xfer->dmamap.segs[seg].ds_len,
+ ("uhci_device_isoc_enter: overlap"));
+ segoff = 0;
+ seg++;
+ }
+ }
if (i == nframes - 1)
status |= UHCI_TD_IOC;
std->td.td_status = htole32(status);
@@ -2342,7 +2521,7 @@
uhci_dump_td(std);
}
#endif
- buf += len;
+ dataptr = (char *)dataptr + len;
}
iso->next = next;
iso->inuse += xfer->nframes;
@@ -2441,7 +2620,7 @@
UXFER(xfer)->iinfo.isdone = 1;
#endif
/* Run callback and remove from interrupt list. */
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
crit_exit();
}
@@ -2506,7 +2685,7 @@
iso = &upipe->u.iso;
iso->stds = kmalloc(UHCI_VFRAMELIST_COUNT * sizeof (uhci_soft_td_t *),
- M_USBHC, M_INTWAIT);
+ M_USBHC, M_WAITOK);
token = rd ? UHCI_TD_IN (0, endpt, addr, 0) :
UHCI_TD_OUT(0, endpt, addr, 0);
@@ -2589,6 +2768,8 @@
return;
}
#endif
+ ii->stdstart = NULL;
+ ii->stdend = NULL;
}
void
@@ -2618,8 +2799,8 @@
/* This alloc cannot fail since we freed the chain above. */
uhci_alloc_std_chain(upipe, sc, xfer->length,
- upipe->u.intr.isread, xfer->flags,
- &xfer->dmabuf, &data, &dataend);
+ upipe->u.intr.isread, xfer->flags, xfer,
+ &data, &dataend);
dataend->td.td_status |= htole32(UHCI_TD_IOC);
#ifdef USB_DEBUG
@@ -2647,8 +2828,11 @@
/* The ii is already on the examined list, just leave it. */
} else {
DPRINTFN(5,("uhci_device_intr_done: removing\n"));
- if (uhci_active_intr_info(ii))
+ if (uhci_active_intr_info(ii)) {
uhci_del_intr_info(ii);
+ ii->stdstart = NULL;
+ ii->stdend = NULL;
+ }
}
}
@@ -2677,7 +2861,9 @@
if (upipe->u.ctl.length != 0)
uhci_free_std_chain(sc, ii->stdstart->link.std, ii->stdend);
-
+ ii->stdstart = NULL;
+ ii->stdend = NULL;
+
DPRINTFN(5, ("uhci_device_ctrl_done: length=%d\n", xfer->actlen));
}
@@ -2700,7 +2886,9 @@
uhci_remove_bulk(sc, upipe->u.bulk.sqh);
uhci_free_std_chain(sc, ii->stdstart, NULL);
-
+ ii->stdstart = NULL;
+ ii->stdend = NULL;
+
DPRINTFN(5, ("uhci_device_bulk_done: length=%d\n", xfer->actlen));
}
@@ -2766,7 +2954,7 @@
upipe->u.intr.npoll = npoll;
upipe->u.intr.qhs =
- kmalloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_INTWAIT);
+ kmalloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_WAITOK);
/*
* Figure out which offset in the schedule that has most
@@ -3100,7 +3288,7 @@
index = UGETW(req->wIndex);
if (len != 0)
- buf = KERNADDR(&xfer->dmabuf, 0);
+ buf = xfer->buffer;
#define C(x,y) ((x) | ((y) << 8))
switch(C(req->bRequest, req->bmRequestType)) {
@@ -3390,7 +3578,7 @@
ret:
xfer->status = err;
crit_enter();
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
crit_exit();
return (USBD_IN_PROGRESS);
}
@@ -3426,7 +3614,7 @@
#ifdef DIAGNOSTIC
UXFER(xfer)->iinfo.isdone = 1;
#endif
- usb_transfer_complete(xfer);
+ uhci_transfer_complete(xfer);
}
usbd_status
Index: uhci_pci.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/uhci_pci.c,v
retrieving revision 1.11
diff -u -r1.11 uhci_pci.c
--- uhci_pci.c 27 Jun 2007 12:27:59 -0000 1.11
+++ uhci_pci.c 19 May 2008 00:15:48 -0000
@@ -56,7 +56,6 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/queue.h>
-#include <sys/bus.h>
#include <sys/rman.h>
#include <bus/pci/pcivar.h>
@@ -134,6 +133,41 @@
#define PCI_UHCI_DEVICEID_ICH6_D 0x265b8086
static const char *uhci_device_ich6_d = "Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D";
+#define PCI_UHCI_DEVICEID_63XXESB_1 0x26888086
+static const char *uhci_device_esb_1 = "Intel 631XESB/632XESB/3100 USB controller USB-1";
+
+#define PCI_UHCI_DEVICEID_63XXESB_2 0x26898086
+static const char *uhci_device_esb_2 = "Intel 631XESB/632XESB/3100 USB controller USB-2";
+
+#define PCI_UHCI_DEVICEID_63XXESB_3 0x268a8086
+static const char *uhci_device_esb_3 = "Intel 631XESB/632XESB/3100 USB controller USB-3";
+
+#define PCI_UHCI_DEVICEID_63XXESB_4 0x268b8086
+static const char *uhci_device_esb_4 = "Intel 631XESB/632XESB/3100 USB controller USB-4";
+
+#define PCI_UHCI_DEVICEID_ICH8_A 0x28308086
+static const char *uhci_device_ich8_a = "Intel 82801H (ICH8) USB controller USB-A";
+
+#define PCI_UHCI_DEVICEID_ICH8_B 0x28318086
+static const char *uhci_device_ich8_b = "Intel 82801H (ICH8) USB controller USB-B";
+
+#define PCI_UHCI_DEVICEID_ICH8_C 0x28328086
+static const char *uhci_device_ich8_c = "Intel 82801H (ICH8) USB controller USB-C";
+
+#define PCI_UHCI_DEVICEID_ICH8_D 0x28348086
+static const char *uhci_device_ich8_d = "Intel 82801H (ICH8) USB controller USB-D";
+
+#define PCI_UHCI_DEVICEID_ICH8_E 0x28358086
+static const char *uhci_device_ich8_e = "Intel 82801H (ICH8) USB controller USB-E";
+
+#define PCI_UHCI_DEVICEID_ICH9_A 0x29348086
+#define PCI_UHCI_DEVICEID_ICH9_B 0x29358086
+#define PCI_UHCI_DEVICEID_ICH9_C 0x29368086
+#define PCI_UHCI_DEVICEID_ICH9_D 0x29378086
+#define PCI_UHCI_DEVICEID_ICH9_E 0x29388086
+#define PCI_UHCI_DEVICEID_ICH9_F 0x29398086
+static const char *uhci_device_ich9 = "Intel 82801I (ICH9) USB controller";
+
#define PCI_UHCI_DEVICEID_440MX 0x719a8086
static const char *uhci_device_440mx = "Intel 82443MX USB controller";
@@ -148,12 +182,11 @@
#define PCI_UHCI_BASE_REG 0x20
-static int uhci_pci_attach(device_t self);
-static int uhci_pci_detach(device_t self);
-static int uhci_pci_suspend(device_t self);
-static int uhci_pci_resume(device_t self);
-
-
+static device_attach_t uhci_pci_attach;
+static device_detach_t uhci_pci_detach;
+static device_suspend_t uhci_pci_suspend;
+static device_resume_t uhci_pci_resume;
+
static int
uhci_pci_suspend(device_t self)
{
@@ -226,6 +259,36 @@
return (uhci_device_ich6_c);
} else if (device_id == PCI_UHCI_DEVICEID_ICH6_D) {
return (uhci_device_ich6_d);
+ } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_1) {
+ return (uhci_device_esb_1);
+ } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_2) {
+ return (uhci_device_esb_2);
+ } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_3) {
+ return (uhci_device_esb_3);
+ } else if (device_id == PCI_UHCI_DEVICEID_63XXESB_4) {
+ return (uhci_device_esb_4);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH8_A) {
+ return (uhci_device_ich8_a);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH8_B) {
+ return (uhci_device_ich8_b);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH8_C) {
+ return (uhci_device_ich8_c);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH8_D) {
+ return (uhci_device_ich8_d);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH8_E) {
+ return (uhci_device_ich8_e);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_A) {
+ return (uhci_device_ich9);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_B) {
+ return (uhci_device_ich9);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_C) {
+ return (uhci_device_ich9);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_D) {
+ return (uhci_device_ich9);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_E) {
+ return (uhci_device_ich9);
+ } else if (device_id == PCI_UHCI_DEVICEID_ICH9_F) {
+ return (uhci_device_ich9);
} else if (device_id == PCI_UHCI_DEVICEID_440MX) {
return (uhci_device_440mx);
} else if (device_id == PCI_UHCI_DEVICEID_460GX) {
@@ -250,7 +313,7 @@
if (desc) {
device_set_desc(self, desc);
- return 0;
+ return BUS_PROBE_DEFAULT;
} else {
return ENXIO;
}
@@ -343,6 +406,29 @@
#endif
pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
+ /* Allocate a parent dma tag for DMA maps */
+ err = bus_dma_tag_create(/* XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.parent_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate parent DMA tag (%d)\n",
+ err);
+ uhci_pci_detach(self);
+ return ENXIO;
+ }
+ /* Allocate a dma tag for transfer buffers */
+ err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->sc_bus.buffer_dmatag);
+ if (err) {
+ device_printf(self, "Could not allocate transfer tag (%d)\n",
+ err);
+ uhci_pci_detach(self);
+ return ENXIO;
+ }
+
err = uhci_init(sc);
if (!err) {
sc->sc_flags |= UHCI_SCFLG_DONEINIT;
@@ -367,6 +453,10 @@
sc->sc_flags &= ~UHCI_SCFLG_DONEINIT;
}
+ if (sc->sc_bus.parent_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
+ if (sc->sc_bus.buffer_dmatag != NULL)
+ bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
Index: uhcivar.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/uhcivar.h,v
retrieving revision 1.9
diff -u -r1.9 uhcivar.h
--- uhcivar.h 30 Jun 2007 20:39:22 -0000 1.9
+++ uhcivar.h 18 May 2008 22:39:16 -0000
@@ -101,6 +101,9 @@
uhci_td_t td; /* The real TD, must be first */
uhci_soft_td_qh_t link; /* soft version of the td_link field */
uhci_physaddr_t physaddr; /* TD's physical address. */
+ usb_dma_t aux_dma; /* Auxillary storage if needed. */
+ void *aux_data; /* Original aux data virtual address. */
+ int aux_len; /* Auxillary storage size. */
};
/*
* Make the size such that it is a multiple of UHCI_TD_ALIGN. This way
Index: uhub.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/uhub.c,v
retrieving revision 1.20
diff -u -r1.20 uhub.c
--- uhub.c 25 Jan 2008 08:49:47 -0000 1.20
+++ uhub.c 18 May 2008 22:38:02 -0000
@@ -62,7 +62,10 @@
#ifdef USB_DEBUG
#define DPRINTF(x) if (uhubdebug) kprintf x
-#define DPRINTFN(n,x) if (uhubdebug>(n)) kprintf x
+#define DPRINTFN(n,x) if (uhubdebug > (n)) kprintf x
+#define DEVPRINTF(x) if (uhubdebug) device_printf x
+#define DEVPRINTFN(n, x)if (uhubdebug > (n)) device_printf x
+
int uhubdebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB uhub");
SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW,
@@ -70,13 +73,15 @@
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
+#define DEVPRINTF(x)
+#define DEVPRINTFN(n,x)
#endif
struct uhub_softc {
device_t 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_int8_t sc_status[32]; /* max 255 ports */
u_char sc_running;
};
#define UHUB_PROTO(sc) ((sc)->sc_hub->ddesc.bDeviceProtocol)
@@ -86,10 +91,6 @@
static usbd_status uhub_explore(usbd_device_handle hub);
static void uhub_intr(usbd_xfer_handle, usbd_private_handle,usbd_status);
-static bus_child_detached_t uhub_child_detached;
-static bus_child_location_str_t uhub_child_location_str;
-static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str;
-
/*
* We need two attachment points:
* hub to usb and hub to hub
@@ -99,21 +100,23 @@
static device_probe_t uhub_match;
static device_attach_t uhub_attach;
static device_detach_t uhub_detach;
+static bus_child_location_str_t uhub_child_location_str;
+static bus_child_pnpinfo_str_t uhub_child_pnpinfo_str;
-static devclass_t uhub_devclass;
+static device_method_t uhub_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uhub_match),
+ DEVMETHOD(device_attach, uhub_attach),
+ DEVMETHOD(device_detach, uhub_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
-static kobj_method_t uhub_methods[] = {
- DEVMETHOD(device_probe, uhub_match),
- DEVMETHOD(device_attach, uhub_attach),
- DEVMETHOD(device_detach, uhub_detach),
- DEVMETHOD(bus_child_detached, uhub_child_detached),
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0,0}
+ /* XXX driver_added needs special care */
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ { 0, 0 }
};
static driver_t uhub_driver = {
@@ -122,23 +125,24 @@
sizeof(struct uhub_softc)
};
-MODULE_DEPEND(uhub, usb, 1, 1, 1);
+static devclass_t uhub_devclass;
/* Create the driver instance for the hub connected to usb case. */
devclass_t uhubroot_devclass;
static device_method_t uhubroot_methods[] = {
- DEVMETHOD(bus_child_detached, uhub_child_detached),
+ DEVMETHOD(device_probe, uhub_match),
+ DEVMETHOD(device_attach, uhub_attach),
+ DEVMETHOD(device_detach, uhub_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
DEVMETHOD(bus_child_location_str, uhub_child_location_str),
DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_str),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ /* XXX driver_added needs special care */
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(device_probe, uhub_match),
- DEVMETHOD(device_attach, uhub_attach),
- DEVMETHOD(device_detach, uhub_detach),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
{0,0}
};
@@ -184,22 +188,21 @@
sc->sc_dev = self;
if (dev->depth > 0 && UHUB_IS_HIGH_SPEED(sc)) {
- kprintf("%s: %s transaction translator%s\n",
- device_get_nameunit(sc->sc_dev),
+ device_printf(sc->sc_dev, "%s transaction translator%s\n",
UHUB_IS_SINGLE_TT(sc) ? "single" : "multiple",
UHUB_IS_SINGLE_TT(sc) ? "" : "s");
}
err = usbd_set_config_index(dev, 0, 1);
if (err) {
- DPRINTF(("%s: configuration failed, error=%s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- return ENXIO;
+ DEVPRINTF((sc->sc_dev, "configuration failed, error=%s\n",
+ usbd_errstr(err)));
+ return (ENXIO);
}
if (dev->depth > USB_HUB_MAX_DEPTH) {
- kprintf("%s: hub depth (%d) exceeded, hub ignored\n",
- device_get_nameunit(sc->sc_dev), USB_HUB_MAX_DEPTH);
- return ENXIO;
+ device_printf(sc->sc_dev, "hub depth (%d) exceeded, hub ignored\n",
+ USB_HUB_MAX_DEPTH);
+ return (ENXIO);
}
/* Get hub descriptor. */
@@ -216,25 +219,28 @@
err = usbd_do_request(dev, &req, &hubdesc);
}
if (err) {
- DPRINTF(("%s: getting hub descriptor failed, error=%s\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
- return ENXIO;
+ DEVPRINTF((sc->sc_dev, "getting hub descriptor failed: %s\n",
+ usbd_errstr(err)));
+ return (ENXIO);
}
for (nremov = 0, port = 1; port <= nports; port++)
if (!UHD_NOT_REMOV(&hubdesc, port))
nremov++;
- kprintf("%s: %d port%s with %d removable, %s powered\n",
- device_get_nameunit(sc->sc_dev), nports, nports != 1 ? "s" : "",
- nremov, dev->self_powered ? "self" : "bus");
+ device_printf(sc->sc_dev, "%d port%s with %d removable, %s powered\n",
+ nports, nports != 1 ? "s" : "", nremov,
+ dev->self_powered ? "self" : "bus");
if (nports == 0) {
- kprintf("%s: no ports, hub ignored\n", device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "no ports, hub ignored\n");
goto bad;
}
hub = kmalloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
- M_USBDEV, M_WAITOK);
+ M_USBDEV, M_NOWAIT);
+ if (hub == NULL) {
+ return (ENXIO);
+ }
dev->hub = hub;
dev->hub->hubsoftc = sc;
hub->explore = uhub_explore;
@@ -248,33 +254,32 @@
if (!dev->self_powered && dev->powersrc->parent != NULL &&
!dev->powersrc->parent->self_powered) {
- kprintf("%s: bus powered hub connected to bus powered hub, "
- "ignored\n", device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "bus powered hub connected to bus "
+ "powered hub, ignored\n");
goto bad;
}
/* Set up interrupt pipe. */
err = usbd_device2interface_handle(dev, 0, &iface);
if (err) {
- kprintf("%s: no interface handle\n", device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "no interface handle\n");
goto bad;
}
ed = usbd_interface2endpoint_descriptor(iface, 0);
if (ed == NULL) {
- kprintf("%s: no endpoint descriptor\n", device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "no endpoint descriptor\n");
goto bad;
}
if ((ed->bmAttributes & UE_XFERTYPE) != UE_INTERRUPT) {
- kprintf("%s: bad interrupt endpoint\n", device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "bad interrupt endpoint\n");
goto bad;
}
err = usbd_open_pipe_intr(iface, ed->bEndpointAddress,
USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_status,
- sizeof(sc->sc_status), uhub_intr, UHUB_INTR_INTERVAL);
+ (nports + 1 + 7) / 8, uhub_intr, UHUB_INTR_INTERVAL);
if (err) {
- kprintf("%s: cannot open interrupt pipe\n",
- device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev, "cannot open interrupt pipe\n");
goto bad;
}
@@ -310,7 +315,9 @@
if (UHUB_IS_HIGH_SPEED(sc)) {
tts = kmalloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) *
- sizeof(struct usbd_tt), M_USBDEV, M_WAITOK);
+ sizeof(struct usbd_tt), M_USBDEV, M_NOWAIT);
+ if (!tts)
+ goto bad;
}
/* Set up data structures */
@@ -341,27 +348,23 @@
/* Turn the power on. */
err = usbd_set_port_feature(dev, port, UHF_PORT_POWER);
if (err)
- kprintf("%s: port %d power on failed, %s\n",
- device_get_nameunit(sc->sc_dev), port,
- usbd_errstr(err));
+ device_printf(sc->sc_dev,
+ "port %d power on failed, %s\n", port,
+ usbd_errstr(err));
DPRINTF(("usb_init_port: turn on port %d power\n", port));
- }
-
- /* Wait for stable power if we are not a root hub */
- if (dev->powersrc->parent != NULL)
+ /* Wait for stable power. */
usbd_delay_ms(dev, pwrdly);
+ }
/* The usual exploration will finish the setup. */
sc->sc_running = 1;
-
- return 0;
-
+ return (0);
bad:
if (hub)
kfree(hub, M_USBDEV);
dev->hub = NULL;
- return ENXIO;
+ return (ENXIO);
}
usbd_status
@@ -394,8 +397,9 @@
}
status = UGETW(up->status.wPortStatus);
change = UGETW(up->status.wPortChange);
- DPRINTFN(3,("uhub_explore: %s port %d status 0x%04x 0x%04x\n",
- device_get_nameunit(sc->sc_dev), port, status, change));
+ DEVPRINTFN(3,(sc->sc_dev,
+ "uhub_explore: port %d status 0x%04x 0x%04x\n", port,
+ status, change));
if (change & UPS_C_PORT_ENABLED) {
DPRINTF(("uhub_explore: C_PORT_ENABLED 0x%x\n", change));
usbd_clear_port_feature(dev, port, UHF_C_PORT_ENABLE);
@@ -403,21 +407,21 @@
/* Ignore the port error if the device
vanished. */
} else if (status & UPS_PORT_ENABLED) {
- kprintf("%s: illegal enable change, port %d\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "illegal enable change, port %d\n", port);
} else {
/* Port error condition. */
if (up->restartcnt) /* no message first time */
- kprintf("%s: port error, restarting "
- "port %d\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "port error, restarting port %d\n",
+ port);
if (up->restartcnt++ < USBD_RESTART_MAX)
goto disco;
else
- kprintf("%s: port error, giving up "
- "port %d\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "port error, giving up port %d\n",
+ port);
}
}
if (!(change & UPS_C_CONNECT_STATUS)) {
@@ -429,8 +433,8 @@
#if 0 && defined(DIAGNOSTIC)
if (up->device == NULL &&
(status & UPS_CURRENT_CONNECT_STATUS))
- kprintf("%s: connected, no device\n",
- device_get_nameunit(sc->sc_dev));
+ device_printf(sc->sc_dev,
+ "connected, no device\n");
#endif
continue;
}
@@ -467,16 +471,16 @@
/* Connected */
if (!(status & UPS_PORT_POWER))
- kprintf("%s: strange, connected port %d has no power\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "strange, connected port %d has no power\n", port);
/* Wait for maximum device power up time. */
usbd_delay_ms(dev, USB_PORT_POWERUP_DELAY);
/* Reset port, which implies enabling it. */
if (usbd_reset_port(dev, port, &up->status)) {
- kprintf("%s: port %d reset failed\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev, "port %d reset failed\n",
+ port);
continue;
}
/* Get port status again, it might have changed during reset */
@@ -491,17 +495,17 @@
if (!(status & UPS_CURRENT_CONNECT_STATUS)) {
/* Nothing connected, just ignore it. */
#ifdef DIAGNOSTIC
- kprintf("%s: port %d, device disappeared after reset\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "port %d, device disappeared after reset\n", port);
#endif
continue;
}
#if 0
if (UHUB_IS_HIGH_SPEED(sc) && !(status & UPS_HIGH_SPEED)) {
- kprintf("%s: port %d, transaction translation not "
- "implemented, low/full speed device ignored\n",
- device_get_nameunit(sc->sc_dev), port);
+ device_printf(sc->sc_dev,
+ "port %d, transaction translation not implemented,"
+ " low/full speed device ignored\n", port);
continue;
}
#endif
@@ -528,8 +532,9 @@
* some other serious problem. Since we cannot leave
* at 0 we have to disable the port instead.
*/
- kprintf("%s: device problem (%s), disabling port %d\n",
- device_get_nameunit(sc->sc_dev), usbd_errstr(err), port);
+ device_printf(sc->sc_dev,
+ "device problem (%s), disabling port %d\n",
+ usbd_errstr(err), port);
usbd_clear_port_feature(dev, port, UHF_PORT_ENABLE);
} else {
/* The port set up succeeded, reset error count. */
@@ -556,10 +561,7 @@
DPRINTF(("uhub_detach: sc=%port\n", sc));
- crit_enter();
-
if (hub == NULL) { /* Must be partially working */
- crit_exit();
return (0);
}
@@ -573,16 +575,13 @@
usb_disconnect_port(rup, self);
}
- usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub,
- sc->sc_dev);
+ usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, sc->sc_dev);
if (hub->ports[0].tt)
kfree(hub->ports[0].tt, M_USBDEV);
kfree(hub, M_USBDEV);
sc->sc_hub->hub = NULL;
- crit_exit();
-
return (0);
}
@@ -597,7 +596,7 @@
int port;
int i;
- crit_enter();
+ get_mplock();
nports = devhub->hub->hubdesc.bNbrPorts;
for (port = 0; port < nports; port++) {
dev = devhub->hub->ports[port].device;
@@ -620,7 +619,7 @@
DPRINTFN(0,("uhub_child_location_str: device not on hub\n"));
buf[0] = '\0';
found_dev:
- crit_exit();
+ rel_mplock();
return (0);
}
@@ -637,7 +636,7 @@
int port;
int i;
- crit_enter();
+ get_mplock();
nports = devhub->hub->hubdesc.bNbrPorts;
for (port = 0; port < nports; port++) {
dev = devhub->hub->ports[port].device;
@@ -651,12 +650,13 @@
}
DPRINTFN(0,("uhub_child_pnpinfo_str: device not on hub\n"));
buf[0] = '\0';
- crit_exit();
+ rel_mplock();
return (0);
found_dev:
/* XXX can sleep */
- (void)usbd_get_string(dev, dev->ddesc.iSerialNumber, &serial[0]);
+ (void)usbd_get_string(dev, dev->ddesc.iSerialNumber, serial,
+ sizeof(serial));
if (dev->ifacenums == NULL) {
ksnprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
"devclass=0x%02x devsubclass=0x%02x "
@@ -676,45 +676,10 @@
iface->idesc->bInterfaceClass,
iface->idesc->bInterfaceSubClass);
}
- crit_exit();
+ rel_mplock();
return (0);
}
-static void
-uhub_child_detached(device_t self, device_t child)
-{
- struct uhub_softc *sc = device_get_softc(self);
- usbd_device_handle devhub = sc->sc_hub;
- usbd_device_handle dev = NULL;
- int nports, port, i = 0;
-
- crit_enter();
- nports = devhub->hub->hubdesc.bNbrPorts;
- for (port = 0; port < nports; port++) {
- dev = devhub->hub->ports[port].device;
- if (dev && dev->subdevs) {
- for (i = 0; dev->subdevs[i]; ++i) {
- if (dev->subdevs[i] == child)
- goto found_dev;
- }
- }
- }
- crit_exit();
- return;
-
-found_dev:
-#if 0
- kprintf("%s: at %s", device_get_nameunit(dev->subdevs[i]),
- device_get_nameunit(self));
- if (port != 0)
- kprintf(" port %d", port);
- kprintf(" (addr %d) disconnected\n", dev->address);
-#endif
- kfree(device_get_ivars(dev->subdevs[i]), M_USB);
- dev->subdevs[i] = NULL;
- crit_exit();
-}
-
/*
* Hub interrupt.
* This an indication that some port has changed status.
@@ -733,5 +698,6 @@
usb_needs_explore(sc->sc_hub);
}
+MODULE_DEPEND(uhub, usb, 1, 1, 1);
DRIVER_MODULE(uhub, usb, uhubroot_driver, uhubroot_devclass, 0, 0);
DRIVER_MODULE(uhub, uhub, uhub_driver, uhub_devclass, usbd_driver_load, 0);
Index: usb.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usb.c,v
retrieving revision 1.41
diff -u -r1.41 usb.c
--- usb.c 26 Apr 2008 23:09:40 -0000 1.41
+++ usb.c 19 May 2008 11:40:20 -0000
@@ -117,6 +117,7 @@
struct usb_softc {
device_t sc_dev; /* base device */
cdev_t sc_usbdev;
+ TAILQ_ENTRY(usb_softc) sc_coldexplist; /* cold needs-explore list */
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
@@ -149,13 +150,15 @@
};
static void usb_discover(void *);
-static bus_child_detached_t usb_child_detached;
static void usb_create_event_thread(void *);
static void usb_event_thread(void *);
static void usb_task_thread(void *);
-static cdev_t usb_dev; /* The /dev/usb device. */
+static cdev_t usb_dev; /* The /dev/usb device. */
static int usb_ndevs; /* Number of /dev/usbN devices. */
+/* Busses to explore at the end of boot-time device configuration. */
+static TAILQ_HEAD(, usb_softc) usb_coldexplist =
+ TAILQ_HEAD_INITIALIZER(usb_coldexplist);
#define USB_MAX_EVENTS 100
struct usb_event_q {
@@ -177,18 +180,21 @@
static device_probe_t usb_match;
static device_attach_t usb_attach;
static device_detach_t usb_detach;
+static bus_child_detached_t usb_child_detached;
-static devclass_t usb_devclass;
+static device_method_t usb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, usb_match),
+ DEVMETHOD(device_attach, usb_attach),
+ DEVMETHOD(device_detach, usb_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, usb_child_detached),
-static kobj_method_t usb_methods[] = {
- DEVMETHOD(device_probe, usb_match),
- DEVMETHOD(device_attach, usb_attach),
- DEVMETHOD(device_detach, usb_detach),
- DEVMETHOD(bus_child_detached, usb_child_detached),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- {0,0}
+ { 0, 0 }
};
static driver_t usb_driver = {
@@ -197,7 +203,12 @@
sizeof(struct usb_softc)
};
-MODULE_DEPEND(usb, usb, 1, 1, 1);
+static devclass_t usb_devclass;
+
+DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0);
+DRIVER_MODULE(usb, slhci, usb_driver, usb_devclass, 0, 0);
MODULE_VERSION(usb, 1);
static int
@@ -246,11 +257,9 @@
}
kprintf("\n");
-#if 0
/* Make sure not to use tsleep() if we are cold booting. */
if (cold)
sc->sc_bus->use_polling++;
-#endif
ue.u.ue_ctrlr.ue_bus = device_get_unit(sc->sc_dev);
usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
@@ -266,7 +275,7 @@
return ENXIO;
}
#else
- callout_init(&sc->sc_bus->softi);
+ usb_callout_init(sc->sc_bus->softi);
#endif
#endif
@@ -288,12 +297,12 @@
* the keyboard will not work until after cold boot.
*/
if (cold) {
- /*
- * XXX Exploring high speed device here will
- * hang the system.
- */
- if (speed != USB_SPEED_HIGH)
+ /* Explore high-speed busses before others. */
+ if (speed == USB_SPEED_HIGH)
dev->hub->explore(sc->sc_bus->root_hub);
+ else
+ TAILQ_INSERT_TAIL(&usb_coldexplist, sc,
+ sc_coldexplist);
}
#endif
} else {
@@ -301,18 +310,17 @@
device_get_nameunit(sc->sc_dev), err);
sc->sc_dying = 1;
}
-#if 0
if (cold)
sc->sc_bus->use_polling--;
-#endif
+ /* XXX really do right config_pending_incr(); */
usb_create_event_thread(sc);
/* The per controller devices (used for usb_discover) */
/* XXX This is redundant now, but old usbd's will want it */
dev_ops_add(&usb_ops, -1, device_get_unit(self));
tmp_dev = make_dev(&usb_ops, device_get_unit(self),
- UID_ROOT, GID_OPERATOR, 0660,
- "usb%d", device_get_unit(self));
+ UID_ROOT, GID_OPERATOR, 0660,
+ "usb%d", device_get_unit(self));
sc->sc_usbdev = reference_dev(tmp_dev);
if (usb_ndevs++ == 0) {
/* The device spitting out events */
@@ -331,6 +339,7 @@
usb_create_event_thread(void *arg)
{
struct usb_softc *sc = arg;
+ struct usb_taskq *taskq;
int i;
if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
@@ -341,7 +350,7 @@
}
for (i = 0; i < USB_NUM_TASKQS; i++) {
- struct usb_taskq *taskq = &usb_taskq[i];
+ taskq = &usb_taskq[i];
if (taskq->taskcreated == 0) {
taskq->taskcreated = 1;
@@ -382,35 +391,14 @@
}
void
-usb_do_task(usbd_device_handle dev, struct usb_task *task, int queue,
- int time_out)
+usb_rem_task(usbd_device_handle dev, struct usb_task *task)
{
struct usb_taskq *taskq;
crit_enter();
-
- taskq = &usb_taskq[queue];
- if (task->queue == -1) {
- DPRINTFN(2,("usb_add_task: task=%p\n", task));
- TAILQ_INSERT_TAIL(&taskq->tasks, task, next);
- task->queue = queue;
- } else {
- DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
- }
- wakeup(&taskq->tasks);
-
- /* Wait until task is finished */
- tsleep((&taskq->tasks + 1), 0, "usbdotsk", time_out);
-
- crit_exit();
-}
-
-void
-usb_rem_task(usbd_device_handle dev, struct usb_task *task)
-{
- crit_enter();
if (task->queue != -1) {
- TAILQ_REMOVE(&usb_taskq[task->queue].tasks, task, next);
+ taskq = &usb_taskq[task->queue];
+ TAILQ_REMOVE(&taskq->tasks, task, next);
task->queue = -1;
}
crit_exit();
@@ -419,25 +407,35 @@
void
usb_event_thread(void *arg)
{
+ static int newthread_wchan;
struct usb_softc *sc = arg;
+ get_mplock();
+
DPRINTF(("usb_event_thread: start\n"));
/*
* In case this controller is a companion controller to an
* EHCI controller we need to wait until the EHCI controller
- * has grabbed the port.
- * XXX It would be nicer to do this with a tsleep(), but I don't
- * know how to synchronize the creation of the threads so it
- * will work.
+ * has grabbed the port. What we do here is wait until no new
+ * USB threads have been created in a while. XXX we actually
+ * just want to wait for the PCI slot to be fully scanned.
+ *
+ * Note that when you `kldload usb' it actually attaches the
+ * devices in order that the drivers appear in the kld, not the
+ * normal PCI order, since the addition of each driver within
+ * usb.ko (ohci, ehci etc.) causes a separate PCI bus re-scan.
*/
- usb_delay_ms(sc->sc_bus, 500);
-
- crit_enter();
+ wakeup(&newthread_wchan);
+ for (;;) {
+ if (tsleep(&newthread_wchan , 0, "usbets", hz * 4) != 0)
+ break;
+ }
/* Make sure first discover does something. */
sc->sc_bus->needs_explore = 1;
usb_discover(sc);
+ /* XXX really do right config_pending_decr(); */
while (!sc->sc_dying) {
#ifdef USB_DEBUG
@@ -445,17 +443,16 @@
#endif
usb_discover(sc);
#ifdef USB_DEBUG
- tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
- usb_noexplore ? 0 : hz * 60);
+ (void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
+ usb_noexplore ? 0 : hz * 60);
#else
- tsleep(&sc->sc_bus->needs_explore, 0, "usbevt", hz * 60);
+ (void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
+ hz * 60);
#endif
DPRINTFN(2,("usb_event_thread: woke up\n"));
}
sc->sc_event_thread = NULL;
- crit_exit();
-
/* In case parent is waiting for us to exit. */
wakeup(sc);
@@ -469,11 +466,12 @@
struct usb_task *task;
struct usb_taskq *taskq;
- crit_enter();
+ get_mplock();
taskq = arg;
DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name));
+ crit_enter();
while (usb_ndevs > 0) {
task = TAILQ_FIRST(&taskq->tasks);
if (task == NULL) {
@@ -487,7 +485,6 @@
crit_exit();
task->fun(task->arg);
crit_enter();
- wakeup((&taskq->tasks + 1));
}
}
@@ -497,6 +494,7 @@
wakeup(&taskq->taskcreated);
DPRINTF(("usb_event_thread: exit\n"));
+ kthread_exit();
}
int
@@ -583,6 +581,10 @@
if (unit == USB_DEV_MINOR) {
switch (ap->a_cmd) {
+ case FIONBIO:
+ /* XXX: True for DragonFly? */
+ /* All handled in the upper FS layer. */
+ return (0);
case FIOASYNC:
if (*(int *)ap->a_data)
usb_async_proc = curproc;
@@ -697,12 +699,12 @@
mask = POLLIN | POLLRDNORM;
crit_enter();
- if (ap->a_events & mask && usb_nevents > 0)
+ if ((ap->a_events & mask) && usb_nevents > 0)
revents |= ap->a_events & mask;
if (revents == 0 && ap->a_events & mask)
selrecord(curthread, &usb_selevent);
crit_exit();
- ap->a_events = revents;
+ ap->a_events = revents;
return (0);
} else {
ap->a_events = 0;
@@ -734,7 +736,6 @@
crit_exit();
sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
crit_enter();
-
}
crit_exit();
}
@@ -797,7 +798,7 @@
struct usb_event ue;
struct timeval thetime;
- ueq = kmalloc(sizeof *ueq, M_USBDEV, M_INTWAIT);
+ ueq = kmalloc(sizeof *ueq, M_USBDEV, M_WAITOK);
ueq->ue = *uep;
ueq->ue.ue_type = type;
microtime(&thetime);
@@ -821,7 +822,7 @@
if (usb_nevents >= USB_MAX_EVENTS) {
/* Too many queued events, drop an old one. */
DPRINTF(("usb: event dropped\n"));
- usb_get_next_event(&ue);
+ (void)usb_get_next_event(&ue);
}
TAILQ_INSERT_TAIL(&usb_events, ueq, next);
usb_nevents++;
@@ -859,6 +860,8 @@
{
struct usb_softc *sc = device_get_softc(self);
struct usb_event ue;
+ struct usb_taskq *taskq;
+ int i;
DPRINTF(("usb_detach: start\n"));
@@ -879,13 +882,11 @@
destroy_dev(sc->sc_usbdev);
if (--usb_ndevs == 0) {
- int i;
-
destroy_dev(usb_dev);
usb_dev = NULL;
for (i = 0; i < USB_NUM_TASKQS; i++) {
- struct usb_taskq *taskq = &usb_taskq[i];
+ taskq = &usb_taskq[i];
wakeup(&taskq->tasks);
if (tsleep(&taskq->taskcreated, 0, "usbtdt",
hz * 60)) {
@@ -923,7 +924,23 @@
sc->sc_port.device = NULL;
}
-DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
-DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
-DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0);
+/* Explore USB busses at the end of device configuration. */
+static void
+usb_cold_explore(void *arg)
+{
+ struct usb_softc *sc;
+
+ KASSERT(cold || TAILQ_EMPTY(&usb_coldexplist),
+ ("usb_cold_explore: busses to explore when !cold"));
+ while (!TAILQ_EMPTY(&usb_coldexplist)) {
+ sc = TAILQ_FIRST(&usb_coldexplist);
+ TAILQ_REMOVE(&usb_coldexplist, sc, sc_coldexplist);
+
+ sc->sc_bus->use_polling++;
+ sc->sc_port.device->hub->explore(sc->sc_bus->root_hub);
+ sc->sc_bus->use_polling--;
+ }
+}
+SYSINIT(usb_cold_explore, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE,
+ usb_cold_explore, NULL);
Index: usb.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usb.h,v
retrieving revision 1.8
diff -u -r1.8 usb.h
--- usb.h 4 Jul 2007 06:06:48 -0000 1.8
+++ usb.h 18 May 2008 17:52:24 -0000
@@ -62,7 +62,11 @@
#define PWR_RESUME 0
#define PWR_SUSPEND 1
-
+#define PWR_STANDBY 2
+#define PWR_SOFTSUSPEND 3
+#define PWR_SOFTSTANDBY 4
+#define PWR_SOFTRESUME 5
+
/* These two defines are used by usbd to autoload the usb kld */
#define USB_KLD "usb" /* name of usb module */
#define USB_UHUB "usb/uhub" /* root hub */
@@ -432,6 +436,7 @@
#define UICLASS_HID 0x03
#define UISUBCLASS_BOOT 1
#define UIPROTO_BOOT_KEYBOARD 1
+#define UIPROTO_MOUSE 2
#define UICLASS_PHYSICAL 0x05
Index: usb_mem.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usb_mem.c,v
retrieving revision 1.12
diff -u -r1.12 usb_mem.c
--- usb_mem.c 28 Jun 2007 13:55:12 -0000 1.12
+++ usb_mem.c 19 May 2008 01:22:20 -0000
@@ -147,7 +147,8 @@
crit_enter();
/* First check the free list. */
for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) {
- if (p->tag == tag && p->size >= size && p->align >= align) {
+ if (p->tag == tag && p->size >= size && p->size < size * 2 &&
+ align >= align) {
LIST_REMOVE(p, next);
usb_blk_nfree--;
crit_exit();
@@ -161,8 +162,10 @@
crit_exit();
DPRINTFN(6, ("usb_block_allocmem: no free\n"));
- p = kmalloc(sizeof *p, M_USB, M_INTWAIT);
+ p = kmalloc(sizeof *p, M_USB, M_NOWAIT);
logmemory(blkalloc, p, NULL, size, align);
+ if (p == NULL)
+ return (USBD_NOMEM);
if (bus_dma_tag_create(tag, align, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
@@ -219,7 +222,7 @@
usbd_status
usb_allocmem(usbd_bus_handle bus, size_t size, size_t align, usb_dma_t *p)
{
- bus_dma_tag_t tag = bus->dmatag;
+ bus_dma_tag_t tag = bus->parent_dmatag;
usbd_status err;
struct usb_frag_dma *f;
usb_dma_block_t *b;
Index: usb_quirks.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usb_quirks.h,v
retrieving revision 1.4
diff -u -r1.4 usb_quirks.h
--- usb_quirks.h 10 Dec 2006 02:03:56 -0000 1.4
+++ usb_quirks.h 18 May 2008 21:02:46 -0000
@@ -41,22 +41,25 @@
struct usbd_quirks {
u_int32_t uq_flags; /* Device problems: */
-#define UQ_NO_SET_PROTO 0x0001 /* cannot handle SET PROTOCOL. */
-#define UQ_SWAP_UNICODE 0x0002 /* has some Unicode strings swapped. */
-#define UQ_MS_REVZ 0x0004 /* mouse has Z-axis reversed */
-#define UQ_NO_STRINGS 0x0008 /* string descriptors are broken. */
-#define UQ_BAD_ADC 0x0010 /* bad audio spec version number. */
-#define UQ_BUS_POWERED 0x0020 /* device is bus powered, despite claim */
-#define UQ_BAD_AUDIO 0x0040 /* device claims audio class, but isn't */
-#define UQ_SPUR_BUT_UP 0x0080 /* spurious mouse button up events */
-#define UQ_AU_NO_XU 0x0100 /* audio device has broken extension unit */
-#define UQ_POWER_CLAIM 0x0200 /* hub lies about power status */
-#define UQ_AU_NO_FRAC 0x0400 /* don't adjust for fractional samples */
-#define UQ_AU_INP_ASYNC 0x0800 /* input is async despite claim of adaptive */
+#define UQ_NO_SET_PROTO 0x00000001 /* cannot handle SET PROTOCOL. */
+#define UQ_SWAP_UNICODE 0x00000002 /* has some Unicode strings swapped. */
+#define UQ_MS_REVZ 0x00000004 /* mouse has Z-axis reversed */
+#define UQ_NO_STRINGS 0x00000008 /* string descriptors are broken. */
+#define UQ_BAD_ADC 0x00000010 /* bad audio spec version number. */
+#define UQ_BUS_POWERED 0x00000020 /* device is bus powered, despite claim */
+#define UQ_BAD_AUDIO 0x00000040 /* device claims audio class, but isn't */
+#define UQ_SPUR_BUT_UP 0x00000080 /* spurious mouse button up events */
+#define UQ_AU_NO_XU 0x00000100 /* audio device has broken extension unit */
+#define UQ_POWER_CLAIM 0x00000200 /* hub lies about power status */
+#define UQ_AU_NO_FRAC 0x00000400 /* don't adjust for fractional samples */
+#define UQ_AU_INP_ASYNC 0x00000800 /* input is async despite claim of adaptive */
#define UQ_ASSUME_CM_OVER_DATA 0x1000 /* modem device breaks on cm over data */
-#define UQ_BROKEN_BIDIR 0x2000 /* printer has broken bidir mode */
-#define UQ_HID_IGNORE 0x8000 /* device should be ignored by hid class */
-
+#define UQ_BROKEN_BIDIR 0x00002000 /* printer has broken bidir mode */
+#define UQ_OPEN_CLEARSTALL 0x04000 /* device needs clear endpoint stall */
+#define UQ_HID_IGNORE 0x00008000 /* device should be ignored by hid class */
+#define UQ_KBD_IGNORE 0x00018000 /* device should be ignored by both kbd and hid class */
+#define UQ_MS_BAD_CLASS 0x00020000 /* doesn't identify properly */
+#define UQ_MS_LEADING_BYTE 0x40000 /* mouse sends an unknown leading byte. */
};
extern const struct usbd_quirks usbd_no_quirk;
Index: usb_subr.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usb_subr.c,v
retrieving revision 1.27
diff -u -r1.27 usb_subr.c
--- usb_subr.c 11 Jan 2008 11:41:50 -0000 1.27
+++ usb_subr.c 18 May 2008 21:34:04 -0000
@@ -187,12 +187,14 @@
}
if (usedev) {
- if (usbd_get_string(dev, udd->iManufacturer, v))
+ if (usbd_get_string(dev, udd->iManufacturer, v,
+ USB_MAX_STRING_LEN))
vendor = NULL;
else
vendor = v;
usbd_trim_spaces(vendor);
- if (usbd_get_string(dev, udd->iProduct, p))
+ if (usbd_get_string(dev, udd->iProduct, p,
+ USB_MAX_STRING_LEN))
product = NULL;
else
product = p;
@@ -260,10 +262,10 @@
usb_delay_ms(usbd_bus_handle bus, u_int ms)
{
/* Wait at least two clock ticks so we know the time has passed. */
- if (bus->use_polling)
+ if (bus->use_polling || cold)
delay((ms+1) * 1000);
else
- tsleep(&ms, 0, "usbdly", (ms*hz+999)/1000 + 1);
+ tsleep(usb_delay_ms, 0, "usbdly", (ms*hz+999)/1000 + 1); /* XXX: port pause */
}
/* Delay given a device handle. */
@@ -403,7 +405,9 @@
DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
if (nendpt != 0) {
ifc->endpoints = kmalloc(nendpt * sizeof(struct usbd_endpoint),
- M_USB, M_INTWAIT);
+ M_USB, M_NOWAIT);
+ if (ifc->endpoints == NULL)
+ return (USBD_NOMEM);
} else {
ifc->endpoints = NULL;
}
@@ -560,7 +564,9 @@
if (err)
return (err);
len = UGETW(cd.wTotalLength);
- cdp = kmalloc(len, M_USB, M_INTWAIT);
+ cdp = kmalloc(len, M_USB, M_NOWAIT);
+ if (cdp == NULL)
+ return (USBD_NOMEM);
/* Get the full descriptor. Try a few times for slow devices. */
for (i = 0; i < 3; i++) {
err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
@@ -660,7 +666,11 @@
/* Allocate and fill interface data. */
nifc = cdp->bNumInterface;
dev->ifaces = kmalloc(nifc * sizeof(struct usbd_interface),
- M_USB, M_INTWAIT);
+ M_USB, M_NOWAIT);
+ if (dev->ifaces == NULL) {
+ err = USBD_NOMEM;
+ goto bad;
+ }
DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
dev->cdesc = cdp;
dev->config = cdp->bConfigurationValue;
@@ -691,7 +701,9 @@
DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
dev, iface, ep, pipe));
- p = kmalloc(dev->bus->pipe_size, M_USB, M_INTWAIT);
+ p = kmalloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
+ if (p == NULL)
+ return (USBD_NOMEM);
p->device = dev;
p->iface = iface;
p->endpoint = ep;
@@ -712,6 +724,18 @@
return (err);
}
+ if (dev->quirks->uq_flags & UQ_OPEN_CLEARSTALL) {
+ /* Clear any stall and make sure DATA0 toggle will be used next. */
+ if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT) {
+ err = usbd_clear_endpoint_stall(p);
+ if (err && err != USBD_STALLED && err != USBD_TIMEOUT) {
+ kprintf("usbd_setup_pipe: failed to start "
+ "endpoint, %s\n", usbd_errstr(err));
+ return (err);
+ }
+ }
+ }
+
*pipe = p;
return (USBD_NORMAL_COMPLETION);
}
@@ -756,8 +780,7 @@
devinfo = kmalloc(1024, M_USB, M_NOWAIT);
if (devinfo == NULL) {
- device_printf(parent,
- "Can't allocate memory for probe string\n");
+ device_printf(parent, "Can't allocate memory for probe string\n");
return (USBD_NOMEM);
}
bdev = device_add_child(parent, NULL, -1);
@@ -766,7 +789,11 @@
device_printf(parent, "Device creation failed\n");
return (USBD_INVAL);
}
- uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK);
+ uaap = kmalloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_INVAL);
+ }
device_set_ivars(bdev, uaap);
uaa.device = dev;
uaa.iface = NULL;
@@ -779,12 +806,17 @@
uaa.vendor = UGETW(dd->idVendor);
uaa.product = UGETW(dd->idProduct);
uaa.release = UGETW(dd->bcdDevice);
+ uaa.matchlvl = 0;
/* First try with device specific drivers. */
DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
dev->ifacenums = NULL;
- dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_WAITOK);
+ dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
+ if (dev->subdevs == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_NOMEM);
+ }
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
*uaap = uaa;
@@ -829,10 +861,18 @@
ifaces[i] = &dev->ifaces[i];
uaa.ifaces = ifaces;
uaa.nifaces = nifaces;
- dev->subdevs = kmalloc((nifaces+1) * sizeof(device_t), M_USB,
- M_WAITOK);
+ dev->subdevs = kmalloc((nifaces+1) * sizeof(device_t),
+ M_USB, M_NOWAIT);
+ if (dev->subdevs == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_NOMEM);
+ }
dev->ifacenums = kmalloc((nifaces) * sizeof(*dev->ifacenums),
- M_USB, M_WAITOK);
+ M_USB, M_NOWAIT);
+ if (dev->ifacenums == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_NOMEM);
+ }
found = 0;
for (i = 0; i < nifaces; i++) {
@@ -858,7 +898,11 @@
kfree(devinfo, M_USB);
return (USBD_NORMAL_COMPLETION);
}
- uaap = kmalloc(sizeof(uaa), M_USB, M_WAITOK);
+ uaap = kmalloc(sizeof(uaa), M_USB, M_NOWAIT);
+ if (uaap == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_NOMEM);
+ }
device_set_ivars(bdev, uaap);
} else {
dev->subdevs[found] = 0;
@@ -890,7 +934,11 @@
uaa.usegeneric = 1;
uaa.configno = UHUB_UNK_CONFIGURATION;
uaa.ifaceno = UHUB_UNK_INTERFACE;
- dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_WAITOK);
+ dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
+ if (dev->subdevs == NULL) {
+ kfree(devinfo, M_USB);
+ return (USBD_NOMEM);
+ }
dev->subdevs[0] = bdev;
dev->subdevs[1] = 0;
*uaap = uaa;
@@ -938,7 +986,10 @@
return (USBD_NO_ADDR);
}
- dev = kmalloc(sizeof *dev, M_USB, M_INTWAIT | M_ZERO);
+ dev = kmalloc(sizeof *dev, M_USB, M_NOWAIT | M_ZERO);
+ if (dev == NULL)
+ return (USBD_NOMEM);
+
dev->bus = bus;
/* Set up default endpoint handle. */
@@ -961,6 +1012,20 @@
up->device = dev;
+ if (up->parent && speed > up->parent->speed) {
+#ifdef USB_DEBUG
+ kprintf("%s: maxium speed of attached "
+ "device, %d, is higher than speed "
+ "of parent HUB, %d.\n",
+ __FUNCTION__, speed, up->parent->speed);
+#endif
+ /*
+ * Reduce the speed, otherwise we won't setup the
+ * proper transfer methods.
+ */
+ speed = up->parent->speed;
+ }
+
/* Locate port on upstream high speed hub */
for (adev = dev, hub = up->parent;
hub != NULL && hub->speed != USB_SPEED_HIGH;
@@ -991,11 +1056,12 @@
return (err);
}
- /* Set the address. Do this early; some devices need that. */
+ dd = &dev->ddesc;
/* Try a few times in case the device is slow (i.e. outside specs.) */
DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
for (i = 0; i < 15; i++) {
- err = usbd_set_address(dev, addr);
+ /* Get the first 8 bytes of the device descriptor. */
+ err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (!err)
break;
usbd_delay_ms(dev, 200);
@@ -1005,20 +1071,7 @@
usbd_reset_port(up->parent, port, &ps);
}
}
- if (err) {
- DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
- err = USBD_SET_ADDR_FAILED;
- usbd_remove_device(dev, up);
- return (err);
- }
- /* Allow device time to set new address */
- usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
- dev->address = addr; /* New device address now */
- bus->devices[addr] = dev;
- dd = &dev->ddesc;
- /* Get the first 8 bytes of the device descriptor. */
- err = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd);
if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
"failed\n", addr));
@@ -1059,6 +1112,15 @@
USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize);
+ /* Re-establish the default pipe with the new max packet size. */
+ usbd_kill_pipe(dev->default_pipe);
+ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+ &dev->default_pipe);
+ if (err) {
+ usbd_remove_device(dev, up);
+ return (err);
+ }
+
err = usbd_reload_device_desc(dev);
if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc "
@@ -1067,6 +1129,30 @@
return (err);
}
+ /* Set the address */
+ DPRINTFN(5,("usbd_new_device: setting device address=%d\n", addr));
+ err = usbd_set_address(dev, addr);
+ if (err) {
+ DPRINTFN(-1,("usb_new_device: set address %d failed\n", addr));
+ err = USBD_SET_ADDR_FAILED;
+ usbd_remove_device(dev, up);
+ return (err);
+ }
+
+ /* Allow device time to set new address */
+ usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE);
+ dev->address = addr; /* New device address now */
+ bus->devices[addr] = dev;
+
+ /* Re-establish the default pipe with the new address. */
+ usbd_kill_pipe(dev->default_pipe);
+ err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
+ &dev->default_pipe);
+ if (err) {
+ usbd_remove_device(dev, up);
+ return (err);
+ }
+
/* Assume 100mA bus powered for now. Changed when configured. */
dev->power = USB_MIN_POWER;
dev->self_powered = 0;
@@ -1247,7 +1333,12 @@
if (up->portno != 0)
kprintf(" port %d", up->portno);
kprintf(" (addr %d) disconnected\n", dev->address);
- device_delete_child(device_get_parent(dev->subdevs[i]), dev->subdevs[i]);
+ struct usb_attach_arg *uaap =
+ device_get_ivars(dev->subdevs[i]);
+ device_detach(dev->subdevs[i]);
+ kfree(uaap, M_USB);
+ device_delete_child(device_get_parent(dev->subdevs[i]),
+ dev->subdevs[i]);
dev->subdevs[i] = NULL;
}
}
Index: usbcdc.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbcdc.h,v
retrieving revision 1.3
diff -u -r1.3 usbcdc.h
--- usbcdc.h 30 Dec 2003 01:01:44 -0000 1.3
+++ usbcdc.h 18 May 2008 21:31:07 -0000
@@ -54,13 +54,20 @@
#define UDESCSUB_CDC_CS 7 /* Country Selection */
#define UDESCSUB_CDC_TOM 8 /* Telephone Operational Modes */
#define UDESCSUB_CDC_USBT 9 /* USB Terminal */
+#define UDESCSUB_CDC_NCT 10
+#define UDESCSUB_CDC_PUF 11
+#define UDESCSUB_CDC_EUF 12
+#define UDESCSUB_CDC_MCMF 13
+#define UDESCSUB_CDC_CCMF 14
+#define UDESCSUB_CDC_ENF 15
+#define UDESCSUB_CDC_ANF 16
typedef struct {
uByte bLength;
uByte bDescriptorType;
uByte bDescriptorSubtype;
uWord bcdCDC;
-} usb_cdc_header_descriptor_t;
+} UPACKED usb_cdc_header_descriptor_t;
typedef struct {
uByte bLength;
@@ -70,7 +77,7 @@
#define USB_CDC_CM_DOES_CM 0x01
#define USB_CDC_CM_OVER_DATA 0x02
uByte bDataInterface;
-} usb_cdc_cm_descriptor_t;
+} UPACKED usb_cdc_cm_descriptor_t;
typedef struct {
uByte bLength;
@@ -81,7 +88,7 @@
#define USB_CDC_ACM_HAS_LINE 0x02
#define USB_CDC_ACM_HAS_BREAK 0x04
#define USB_CDC_ACM_HAS_NETWORK_CONN 0x08
-} usb_cdc_acm_descriptor_t;
+} UPACKED usb_cdc_acm_descriptor_t;
typedef struct {
uByte bLength;
@@ -89,8 +96,19 @@
uByte bDescriptorSubtype;
uByte bMasterInterface;
uByte bSlaveInterface[1];
-} usb_cdc_union_descriptor_t;
+} UPACKED usb_cdc_union_descriptor_t;
+typedef struct {
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bDescriptorSubtype;
+ uByte iMacAddress;
+ uDWord bmEthernetStatistics;
+ uWord wMaxSegmentSize;
+ uWord wNumberMCFikters;
+ uByte bNumberPowerFilters;
+} UPACKED usb_cdc_ethernet_descriptor_t;
+
#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
#define UCDC_GET_ENCAPSULATED_RESPONSE 0x01
#define UCDC_SET_COMM_FEATURE 0x02
@@ -111,7 +129,7 @@
uWord wState;
#define UCDC_IDLE_SETTING 0x0001
#define UCDC_DATA_MULTIPLEXED 0x0002
-} usb_cdc_abstract_state_t;
+} UPACKED usb_cdc_abstract_state_t;
#define UCDC_ABSTRACT_STATE_LENGTH 2
typedef struct {
@@ -127,7 +145,7 @@
#define UCDC_PARITY_MARK 3
#define UCDC_PARITY_SPACE 4
uByte bDataBits;
-} usb_cdc_line_state_t;
+} UPACKED usb_cdc_line_state_t;
#define UCDC_LINE_STATE_LENGTH 7
typedef struct {
@@ -146,7 +164,7 @@
uWord wIndex;
uWord wLength;
uByte data[16];
-} usb_cdc_notification_t;
+} UPACKED usb_cdc_notification_t;
#define UCDC_NOTIFICATION_LENGTH 8
/*
Index: usbdi.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbdi.c,v
retrieving revision 1.18
diff -u -r1.18 usbdi.c
--- usbdi.c 29 Jun 2007 22:56:31 -0000 1.18
+++ usbdi.c 18 May 2008 22:22:00 -0000
@@ -76,7 +76,11 @@
static usbd_status usbd_open_pipe_ival
(usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int);
static int usbd_xfer_isread(usbd_xfer_handle xfer);
-
+static void usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg,
+ int error);
+static void usbd_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg,
+ int error);
+
static int usbd_nbuses = 0;
void
@@ -272,12 +276,15 @@
usbd_transfer(usbd_xfer_handle xfer)
{
usbd_pipe_handle pipe = xfer->pipe;
- usb_dma_t *dmap = &xfer->dmabuf;
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
usbd_status err;
u_int size;
- DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
- xfer, xfer->flags, pipe, pipe->running));
+ DPRINTFN(5,("%s: xfer=%p, flags=0x%b, rqflags=0x%b, "
+ "length=%d, buffer=%p, allocbuf=%p, pipe=%p, running=%d\n",
+ __func__, xfer, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS,
+ xfer->length, xfer->buffer, xfer->allocbuf, pipe, pipe->running));
+
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
@@ -290,43 +297,36 @@
size = xfer->length;
/* If there is no buffer, allocate one. */
if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) {
- struct usbd_bus *bus = pipe->device->bus;
+ bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag;
#ifdef DIAGNOSTIC
if (xfer->rqflags & URQ_AUTO_DMABUF)
kprintf("usbd_transfer: has old buffer!\n");
#endif
- err = bus->methods->allocm(bus, dmap, size);
+ err = bus_dmamap_create(tag, 0, &dmap->map);
if (err)
- return (err);
- xfer->rqflags |= URQ_AUTO_DMABUF;
- }
-
- /* Copy data if going out. */
- if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
- !usbd_xfer_isread(xfer))
- memcpy(KERNADDR(dmap, 0), xfer->buffer, size);
-
- err = pipe->methods->transfer(xfer);
-
- if (err != USBD_IN_PROGRESS && err) {
- /* The transfer has not been queued, so free buffer. */
- if (xfer->rqflags & URQ_AUTO_DMABUF) {
- struct usbd_bus *bus = pipe->device->bus;
+ return (USBD_NOMEM);
- bus->methods->freem(bus, &xfer->dmabuf);
+ xfer->rqflags |= URQ_AUTO_DMABUF;
+ err = bus_dmamap_load(tag, dmap->map, xfer->buffer, size,
+ usbd_start_transfer, xfer, 0);
+ if (err != 0 && err != EINPROGRESS) {
xfer->rqflags &= ~URQ_AUTO_DMABUF;
+ bus_dmamap_destroy(tag, dmap->map);
+ return (USBD_INVAL);
}
+ } else if (size != 0) {
+ usbd_start_transfer(xfer, dmap->segs, dmap->nsegs, 0);
+ } else {
+ usbd_start_transfer(xfer, NULL, 0, 0);
}
if (!(xfer->flags & USBD_SYNCHRONOUS))
- return (err);
+ return (xfer->done ? 0 : USBD_IN_PROGRESS);
/* Sync transfer, wait for completion. */
- if (err != USBD_IN_PROGRESS)
- return (err);
crit_enter();
- if (!xfer->done) {
+ while (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done");
tsleep(xfer, 0, "usbsyn", 0);
@@ -335,6 +335,70 @@
return (xfer->status);
}
+static void
+usbd_start_transfer(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ usbd_xfer_handle xfer = arg;
+ usbd_pipe_handle pipe = xfer->pipe;
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
+ bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag;
+ int err, i;
+
+ if (error != 0) {
+ KASSERT(xfer->rqflags & URQ_AUTO_DMABUF,
+ ("usbd_start_transfer: error with non-auto buf"));
+ if (nseg > 0)
+ bus_dmamap_unload(tag, dmap->map);
+ bus_dmamap_destroy(tag, dmap->map);
+ /* XXX */
+ usb_insert_transfer(xfer);
+ xfer->status = USBD_IOERROR;
+ usb_transfer_complete(xfer);
+ return;
+ }
+
+ if (segs != dmap->segs) {
+ for (i = 0; i < nseg; i++)
+ dmap->segs[i] = segs[i];
+ }
+ dmap->nsegs = nseg;
+
+ if (nseg > 0) {
+ if (!usbd_xfer_isread(xfer)) {
+ /*
+ * Copy data if it is not already in the correct
+ * buffer.
+ */
+ if (!(xfer->flags & USBD_NO_COPY) &&
+ xfer->allocbuf != NULL &&
+ xfer->buffer != xfer->allocbuf)
+ memcpy(xfer->allocbuf, xfer->buffer,
+ xfer->length);
+ bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREWRITE);
+ } else if (xfer->rqflags & URQ_REQUEST) {
+ /*
+ * Even if we have no data portion we still need to
+ * sync the dmamap for the request data in the SETUP
+ * packet.
+ */
+ bus_dmamap_sync(tag, dmap->map,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+ } else
+ bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_PREREAD);
+ }
+ err = pipe->methods->transfer(xfer);
+ if (err != USBD_IN_PROGRESS && err) {
+ if (xfer->rqflags & URQ_AUTO_DMABUF) {
+ bus_dmamap_unload(tag, dmap->map);
+ bus_dmamap_destroy(tag, dmap->map);
+ xfer->rqflags &= ~URQ_AUTO_DMABUF;
+ }
+ xfer->status = err;
+ usb_transfer_complete(xfer);
+ return;
+ }
+}
+
/* Like usbd_transfer(), but waits for completion. */
usbd_status
usbd_sync_transfer(usbd_xfer_handle xfer)
@@ -343,44 +407,105 @@
return (usbd_transfer(xfer));
}
+struct usbd_allocstate {
+ usbd_xfer_handle xfer;
+ int done;
+ int error;
+ int waiting;
+};
+
void *
usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
{
- struct usbd_bus *bus = xfer->device->bus;
+ struct usbd_allocstate allocstate;
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
+ bus_dma_tag_t tag = xfer->device->bus->buffer_dmatag;
+ void *buf;
usbd_status err;
+ int error;
-#ifdef DIAGNOSTIC
- if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
- kprintf("usbd_alloc_buffer: xfer already has a buffer\n");
-#endif
- err = bus->methods->allocm(bus, &xfer->dmabuf, size);
+ KASSERT((xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) == 0,
+ ("usbd_alloc_buffer: xfer already has a buffer"));
+ err = bus_dmamap_create(tag, 0, &dmap->map);
if (err)
return (NULL);
+ buf = kmalloc(size, M_USB, M_WAITOK);
+
+ allocstate.xfer = xfer;
+ allocstate.done = 0;
+ allocstate.error = 0;
+ allocstate.waiting = 0;
+ error = bus_dmamap_load(tag, dmap->map, buf, size, usbd_alloc_callback,
+ &allocstate, 0);
+ if (error && error != EINPROGRESS) {
+ bus_dmamap_destroy(tag, dmap->map);
+ kfree(buf, M_USB);
+ return (NULL);
+ }
+ if (error == EINPROGRESS) {
+ /* Wait for completion. */
+ crit_enter();
+ allocstate.waiting = 1;
+ while (!allocstate.done)
+ tsleep(&allocstate, 0, "usbdab", 0);
+ crit_exit();
+ error = allocstate.error;
+ }
+ if (error) {
+ bus_dmamap_unload(tag, dmap->map);
+ bus_dmamap_destroy(tag, dmap->map);
+ kfree(buf, M_USB);
+ return (NULL);
+ }
+
+ xfer->allocbuf = buf;
xfer->rqflags |= URQ_DEV_DMABUF;
- return (KERNADDR(&xfer->dmabuf, 0));
+ return (buf);
}
void
usbd_free_buffer(usbd_xfer_handle xfer)
{
-#ifdef DIAGNOSTIC
- if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) {
- kprintf("usbd_free_buffer: no buffer\n");
- return;
- }
-#endif
- xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF);
- xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
+ bus_dma_tag_t tag = xfer->device->bus->buffer_dmatag;
+
+ KASSERT((xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) ==
+ URQ_DEV_DMABUF, ("usbd_free_buffer: no/auto buffer"));
+
+ xfer->rqflags &= ~URQ_DEV_DMABUF;
+ bus_dmamap_unload(tag, dmap->map);
+ bus_dmamap_destroy(tag, dmap->map);
+ kfree(xfer->allocbuf, M_USB);
+ xfer->allocbuf = NULL;
}
void *
usbd_get_buffer(usbd_xfer_handle xfer)
{
if (!(xfer->rqflags & URQ_DEV_DMABUF))
- return (0);
- return (KERNADDR(&xfer->dmabuf, 0));
+ return (NULL);
+ return (xfer->allocbuf);
}
+static void
+usbd_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ struct usbd_allocstate *allocstate = arg;
+ usbd_xfer_handle xfer = allocstate->xfer;
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
+ int i;
+
+ allocstate->error = error;
+ if (error == 0) {
+ for (i = 0; i < nseg; i++)
+ dmap->segs[i] = segs[i];
+ dmap->nsegs = nseg;
+ }
+ allocstate->done = 1;
+ if (allocstate->waiting)
+ wakeup(&allocstate);
+}
+
usbd_xfer_handle
usbd_alloc_xfer(usbd_device_handle dev)
{
@@ -399,8 +524,15 @@
usbd_free_xfer(usbd_xfer_handle xfer)
{
DPRINTFN(5,("usbd_free_xfer: %p\n", xfer));
- if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
+ if (xfer->rqflags & URQ_DEV_DMABUF)
usbd_free_buffer(xfer);
+/* XXX Does FreeBSD need to do something similar? */
+#if defined(__NetBSD__) && defined(DIAGNOSTIC)
+ if (callout_pending(&xfer->timeout_handle)) {
+ callout_stop(&xfer->timeout_handle);
+ kprintf("usbd_free_xfer: timout_handle pending");
+ }
+#endif
xfer->device->bus->methods->freex(xfer->device->bus, xfer);
return (USBD_NORMAL_COMPLETION);
}
@@ -450,10 +582,14 @@
usbd_private_handle priv, u_int16_t *frlengths,
u_int32_t nframes, u_int16_t flags, usbd_callback callback)
{
+ int i;
+
xfer->pipe = pipe;
xfer->priv = priv;
xfer->buffer = 0;
xfer->length = 0;
+ for (i = 0; i < nframes; i++)
+ xfer->length += frlengths[i];
xfer->actlen = 0;
xfer->flags = flags;
xfer->timeout = USBD_NO_TIMEOUT;
@@ -478,12 +614,6 @@
*status = xfer->status;
}
-int
-usbd_get_speed(usbd_device_handle dev)
-{
- return(dev->speed);
-}
-
usb_config_descriptor_t *
usbd_get_config_descriptor(usbd_device_handle dev)
{
@@ -496,6 +626,11 @@
return (dev->cdesc);
}
+usbd_get_speed(usbd_device_handle dev)
+{
+ return (dev->speed);
+}
+
usb_interface_descriptor_t *
usbd_get_interface_descriptor(usbd_interface_handle iface)
{
@@ -739,6 +874,7 @@
pipe, xfer, pipe->methods));
/* Make the HC abort it (and invoke the callback). */
pipe->methods->abort(xfer);
+ KASSERT(STAILQ_FIRST(&pipe->queue) != xfer, ("usbd_ar_pipe"));
/* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
}
pipe->aborting = 0;
@@ -750,15 +886,20 @@
usb_transfer_complete(usbd_xfer_handle xfer)
{
usbd_pipe_handle pipe = xfer->pipe;
- usb_dma_t *dmap = &xfer->dmabuf;
+ struct usb_dma_mapping *dmap = &xfer->dmamap;
+ bus_dma_tag_t tag = pipe->device->bus->buffer_dmatag;
int sync = xfer->flags & USBD_SYNCHRONOUS;
int erred = xfer->status == USBD_CANCELLED ||
xfer->status == USBD_TIMEOUT;
int repeat = pipe->repeat;
int polling;
- DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
- "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
+ DPRINTFN(5, ("%s: pipe=%p xfer=%p status=%d actlen=%d\n",
+ __func__, pipe, xfer, xfer->status, xfer->actlen));
+ DPRINTFN(5,("%s: flags=0x%b, rqflags=0x%b, length=%d, buffer=%p\n",
+ __func__, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS,
+ xfer->length, xfer->buffer));
+
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_ONQU) {
kprintf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
@@ -778,23 +919,19 @@
if (polling)
pipe->running = 0;
- if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
- usbd_xfer_isread(xfer)) {
-#ifdef DIAGNOSTIC
- if (xfer->actlen > xfer->length) {
- kprintf("usb_transfer_complete: actlen > len %d > %d\n",
- xfer->actlen, xfer->length);
- xfer->actlen = xfer->length;
- }
-#endif
- memcpy(xfer->buffer, KERNADDR(dmap, 0), xfer->actlen);
+ if (xfer->actlen != 0 && usbd_xfer_isread(xfer)) {
+ bus_dmamap_sync(tag, dmap->map, BUS_DMASYNC_POSTREAD);
+ /* Copy data if it is not already in the correct buffer. */
+ if (!(xfer->flags & USBD_NO_COPY) && xfer->allocbuf != NULL &&
+ xfer->buffer != xfer->allocbuf)
+ memcpy(xfer->buffer, xfer->allocbuf, xfer->actlen);
}
- /* if we allocated the buffer in usbd_transfer() we free it here. */
+ /* if we mapped the buffer in usbd_transfer() we unmap it here. */
if (xfer->rqflags & URQ_AUTO_DMABUF) {
if (!repeat) {
- struct usbd_bus *bus = pipe->device->bus;
- bus->methods->freem(bus, dmap);
+ bus_dmamap_unload(tag, dmap->map);
+ bus_dmamap_destroy(tag, dmap->map);
xfer->rqflags &= ~URQ_AUTO_DMABUF;
}
}
@@ -802,11 +939,10 @@
if (!repeat) {
/* Remove request from queue. */
#ifdef DIAGNOSTIC
- if (xfer != STAILQ_FIRST(&pipe->queue))
- kprintf("usb_transfer_complete: bad dequeue %p != %p\n",
- xfer, STAILQ_FIRST(&pipe->queue));
xfer->busy_free = XFER_BUSY;
#endif
+ KASSERT(STAILQ_FIRST(&pipe->queue) == xfer,
+ ("usb_transfer_complete: bad dequeue"));
STAILQ_REMOVE_HEAD(&pipe->queue, next);
}
DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
@@ -869,6 +1005,7 @@
xfer->busy_free = XFER_ONQU;
#endif
crit_enter();
+ KASSERT(STAILQ_FIRST(&pipe->queue) != xfer, ("usb_insert_transfer"));
STAILQ_INSERT_TAIL(&pipe->queue, xfer, next);
if (pipe->running)
err = USBD_IN_PROGRESS;
@@ -1166,7 +1303,7 @@
}
usbd_status
-usbd_get_string(usbd_device_handle dev, int si, char *buf)
+usbd_get_string(usbd_device_handle dev, int si, char *buf, size_t len)
{
int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
usb_string_descriptor_t us;
@@ -1177,6 +1314,8 @@
int size;
buf[0] = '\0';
+ if (len == 0)
+ return (USBD_NORMAL_COMPLETION);
if (si == 0)
return (USBD_INVAL);
if (dev->quirks->uq_flags & UQ_NO_STRINGS)
@@ -1198,7 +1337,7 @@
return (err);
s = buf;
n = size / 2 - 1;
- for (i = 0; i < n; i++) {
+ for (i = 0; i < n && i < len - 1; i++) {
c = UGETW(us.bString[i]);
/* Convert from Unicode, handle buggy strings. */
if ((c & 0xff00) == 0)
Index: usbdi.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbdi.h,v
retrieving revision 1.10
diff -u -r1.10 usbdi.h
--- usbdi.h 5 Nov 2007 13:32:27 -0000 1.10
+++ usbdi.h 18 May 2008 21:55:33 -0000
@@ -89,6 +89,8 @@
/* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */
#define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */
+#define USBD_BITS "\20\1NO_COPY\2SYNCHRONOUS\4FORCE_SHORT_XFER"
+
#define USBD_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
@@ -176,7 +178,8 @@
int usbd_ratecheck(struct timeval *last);
-usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf);
+usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf,
+ size_t len);
/* An iterator for descriptors. */
typedef struct {
@@ -203,8 +206,7 @@
#define USB_NUM_TASKQS 2
#define USB_TASKQ_NAMES {"usbtask-hc", "usbtask-dr"}
-void usb_do_task(usbd_device_handle, struct usb_task *, int, int);
-void usb_add_task(usbd_device_handle, struct usb_task *, int);
+void usb_add_task(usbd_device_handle, struct usb_task *, int queue);
void usb_rem_task(usbd_device_handle, struct usb_task *);
#define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->queue = -1)
Index: usbdi_util.c
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbdi_util.c,v
retrieving revision 1.16
diff -u -r1.16 usbdi_util.c
--- usbdi_util.c 2 Aug 2007 16:19:17 -0000 1.16
+++ usbdi_util.c 18 May 2008 21:53:59 -0000
@@ -394,7 +394,9 @@
if (hid == NULL)
return (USBD_IOERROR);
*sizep = UGETW(hid->descrs[0].wDescriptorLength);
- *descp = kmalloc(*sizep, mem, M_INTWAIT);
+ *descp = kmalloc(*sizep, mem, M_NOWAIT);
+ if (*descp == NULL)
+ return (USBD_NOMEM);
err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
*sizep, *descp);
if (err) {
Index: usbdi_util.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbdi_util.h,v
retrieving revision 1.7
diff -u -r1.7 usbdi_util.h
--- usbdi_util.h 2 Aug 2007 16:19:17 -0000 1.7
+++ usbdi_util.h 18 May 2008 21:51:12 -0000
@@ -39,6 +39,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef _USBI_UTIL_H_
+#define _USBI_UTIL_H_
+
usbd_status usbd_get_desc(usbd_device_handle dev, int type,
int index, int len, void *desc);
usbd_status usbd_get_config_desc(usbd_device_handle, int,
@@ -97,3 +100,4 @@
usb_interface_descriptor_t *id);
#define USBD_SUBTYPE_ANY (~0)
+#endif /* _USBI_UTIL_H_ */
Index: usbdivar.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbdivar.h,v
retrieving revision 1.11
diff -u -r1.11 usbdivar.h
--- usbdivar.h 3 Jul 2007 19:28:16 -0000 1.11
+++ usbdivar.h 18 May 2008 21:49:04 -0000
@@ -39,7 +39,6 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
-
/* From usb_mem.h */
struct usb_dma_block;
typedef struct {
@@ -133,7 +132,8 @@
#endif
#endif
- bus_dma_tag_t dmatag; /* DMA tag */
+ bus_dma_tag_t parent_dmatag; /* Base DMA tag */
+ bus_dma_tag_t buffer_dmatag; /* Tag for transfer buffers */
};
struct usbd_device {
@@ -190,6 +190,15 @@
struct usbd_pipe_methods *methods;
};
+#define USB_DMA_NSEG (btoc(MAXPHYS) + 1)
+
+/* DMA-capable memory buffer. */
+struct usb_dma_mapping {
+ bus_dma_segment_t segs[USB_DMA_NSEG]; /* The physical segments. */
+ int nsegs; /* Number of segments. */
+ bus_dmamap_t map; /* DMA mapping. */
+};
+
struct usbd_xfer {
struct usbd_pipe *pipe;
void *priv;
@@ -217,8 +226,9 @@
/* For memory allocation */
struct usbd_device *device;
- usb_dma_t dmabuf;
-
+ struct usb_dma_mapping dmamap;
+ void *allocbuf;
+
int rqflags;
#define URQ_REQUEST 0x01
#define URQ_AUTO_DMABUF 0x10
@@ -231,6 +241,8 @@
struct callout timeout_handle;
};
+#define URQ_BITS "\20\1REQUEST\5AUTO_DMABUF\6DEV_DMABUF"
+
void usbd_init(void);
void usbd_finish(void);
Index: usbhid.h
===================================================================
RCS file: /home/dcvs/src/sys/bus/usb/usbhid.h,v
retrieving revision 1.4
diff -u -r1.4 usbhid.h
--- usbhid.h 30 Dec 2007 20:02:56 -0000 1.4
+++ usbhid.h 18 May 2008 21:44:11 -0000
@@ -126,6 +126,7 @@
#define HUG_VBRY 0x0044
#define HUG_VBRZ 0x0045
#define HUG_VNO 0x0046
+#define HUG_TWHEEL 0x0048 // M$ Wireless Intellimouse Wheel
#define HUG_SYSTEM_CONTROL 0x0080
#define HUG_SYSTEM_POWER_DOWN 0x0081
#define HUG_SYSTEM_SLEEP 0x0082
@@ -167,9 +168,6 @@
#define HUD_ERASER 0x0045
#define HUD_TABLET_PICK 0x0046
-/* Usages, Consumer */
-#define HUC_AC_PAN 0x0238
-
#define HID_USAGE2(p,u) (((p) << 16) | u)
#define UHID_INPUT_REPORT 0x01
--- ehci.c 2008-05-19 11:21:42 +0000
+++ /root/src/sys/dev/usb/ehci.c 2008-05-13 20:58:08 +0000
@@ -1,8 +1,6 @@
/* $NetBSD: ehci.c,v 1.91 2005/02/27 00:27:51 perry Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ehci.c,v 1.36.2.3 2006/09/24 13:39:04 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/ehci.c,v 1.32 2007/06/29 22:56:31 hasso Exp $ */
-/*
+/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -60,6 +58,9 @@
* 3) Command failures are not recovered correctly.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/ehci.c,v 1.63 2008/05/13 20:58:08 marius Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -68,34 +69,37 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/lock.h>
+#include <sys/lockmgr.h>
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
+#include <machine/cpu.h>
+#endif
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
-#include <sys/thread2.h>
-#include <machine/cpu.h>
+#include <machine/bus.h>
#include <machine/endian.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
-#include <bus/usb/usb_quirks.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usb_quirks.h>
-#include <bus/usb/ehcireg.h>
-#include <bus/usb/ehcivar.h>
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
#define delay(d) DELAY(d)
#ifdef USB_DEBUG
#define EHCI_DEBUG USB_DEBUG
-#define DPRINTF(x) do { if (ehcidebug) kprintf x; } while (0)
-#define DPRINTFN(n,x) do { if (ehcidebug>(n)) kprintf x; } while (0)
+#define DPRINTF(x) do { if (ehcidebug) printf x; } while (0)
+#define DPRINTFN(n,x) do { if (ehcidebug>(n)) printf x; } while (0)
int ehcidebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW,
&ehcidebug, 0, "ehci debug level");
-#define bitmask_snprintf(q,f,b,l) ksnprintf((b), (l), "%b", (q), (f))
+#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -327,7 +331,7 @@
* Table 2-9 in the EHCI spec says this will result
* in undefined behavior.
*/
- kprintf("%s: stop timeout\n",
+ printf("%s: stop timeout\n",
device_get_nameunit(sc->sc_bus.bdev));
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
@@ -337,7 +341,7 @@
if (!hcr)
return (USBD_NORMAL_COMPLETION);
}
- kprintf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
return (USBD_IOERROR);
}
@@ -359,7 +363,7 @@
sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH);
version = EREAD2(sc, EHCI_HCIVERSION);
- kprintf("%s: EHCI version %x.%x\n", device_get_nameunit(sc->sc_bus.bdev),
+ printf("%s: EHCI version %x.%x\n", device_get_nameunit(sc->sc_bus.bdev),
version >> 8, version & 0xff);
sparams = EREAD4(sc, EHCI_HCSPARAMS);
@@ -367,20 +371,20 @@
sc->sc_npcomp = EHCI_HCS_N_PCC(sparams);
ncomp = EHCI_HCS_N_CC(sparams);
if (ncomp != sc->sc_ncomp) {
- kprintf("%s: wrong number of companions (%d != %d)\n",
+ printf("%s: wrong number of companions (%d != %d)\n",
device_get_nameunit(sc->sc_bus.bdev),
ncomp, sc->sc_ncomp);
if (ncomp < sc->sc_ncomp)
sc->sc_ncomp = ncomp;
}
if (sc->sc_ncomp > 0) {
- kprintf("%s: companion controller%s, %d port%s each:",
+ printf("%s: companion controller%s, %d port%s each:",
device_get_nameunit(sc->sc_bus.bdev), sc->sc_ncomp!=1 ? "s" : "",
EHCI_HCS_N_PCC(sparams),
EHCI_HCS_N_PCC(sparams)!=1 ? "s" : "");
for (i = 0; i < sc->sc_ncomp; i++)
- kprintf(" %s", device_get_nameunit(sc->sc_comps[i]->bdev));
- kprintf("\n");
+ printf(" %s", device_get_nameunit(sc->sc_comps[i]->bdev));
+ printf("\n");
}
sc->sc_noport = EHCI_HCS_N_PORTS(sparams);
cparams = EREAD4(sc, EHCI_HCCPARAMS);
@@ -407,7 +411,7 @@
case 3: return (USBD_IOERROR);
}
err = usb_allocmem(&sc->sc_bus, sc->sc_flsize * sizeof(ehci_link_t),
- EHCI_FLALIGN_ALIGN, &sc->sc_fldma);
+ EHCI_FLALIGN_ALIGN, &sc->sc_fldma);
if (err)
return (err);
DPRINTF(("%s: flsize=%d\n", device_get_nameunit(sc->sc_bus.bdev),sc->sc_flsize));
@@ -418,6 +422,11 @@
sc->sc_bus.methods = &ehci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct ehci_pipe);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sc->sc_powerhook = powerhook_establish(ehci_power, sc);
+ sc->sc_shutdownhook = shutdownhook_establish(ehci_shutdown, sc);
+#endif
+
sc->sc_eintrs = EHCI_NORMAL_INTRS;
/*
@@ -490,10 +499,10 @@
sc->sc_async_head = sqh;
EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH);
- callout_init(&sc->sc_tmo_pcd);
- callout_init(&sc->sc_tmo_intrlist);
+ callout_init(&sc->sc_tmo_pcd, 0);
+ callout_init(&sc->sc_tmo_intrlist, 0);
- lockinit(&sc->sc_doorbell_lock, "ehcidb", 0, 0);
+ lockinit(&sc->sc_doorbell_lock, PZERO, "ehcidb", 0, 0);
/* Enable interrupts */
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
@@ -516,7 +525,7 @@
break;
}
if (hcr) {
- kprintf("%s: run timeout\n", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s: run timeout\n", device_get_nameunit(sc->sc_bus.bdev));
return (USBD_IOERROR);
}
@@ -564,7 +573,7 @@
/* In case the interrupt occurs before initialization has completed. */
if (sc == NULL) {
#ifdef DIAGNOSTIC
- kprintf("ehci_intr1: sc == NULL\n");
+ printf("ehci_intr1: sc == NULL\n");
#endif
return (0);
}
@@ -596,7 +605,7 @@
eintrs &= ~(EHCI_STS_INT | EHCI_STS_ERRINT);
}
if (eintrs & EHCI_STS_HSE) {
- kprintf("%s: unrecoverable error, controller halted\n",
+ printf("%s: unrecoverable error, controller halted\n",
device_get_nameunit(sc->sc_bus.bdev));
/* XXX what else */
}
@@ -618,7 +627,7 @@
/* Block unprocessed interrupts. */
sc->sc_eintrs &= ~eintrs;
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
- kprintf("%s: blocking intrs 0x%x\n",
+ printf("%s: blocking intrs 0x%x\n",
device_get_nameunit(sc->sc_bus.bdev), eintrs);
}
@@ -740,13 +749,13 @@
DPRINTFN(/*15*/2, ("ehci_check_intr: ex=%p\n", ex));
if (ex->sqtdstart == NULL) {
- kprintf("ehci_check_intr: sqtdstart=NULL\n");
+ printf("ehci_check_intr: sqtdstart=NULL\n");
return;
}
lsqtd = ex->sqtdend;
#ifdef DIAGNOSTIC
if (lsqtd == NULL) {
- kprintf("ehci_check_intr: lsqtd==0\n");
+ printf("ehci_check_intr: lsqtd==0\n");
return;
}
#endif
@@ -793,19 +802,19 @@
DPRINTFN(/*12*/2, ("ehci_idone: ex=%p\n", ex));
#ifdef DIAGNOSTIC
{
- crit_enter();
+ int s = splhigh();
if (ex->isdone) {
- crit_exit();
+ splx(s);
#ifdef EHCI_DEBUG
- kprintf("ehci_idone: ex is done!\n ");
+ printf("ehci_idone: ex is done!\n ");
ehci_dump_exfer(ex);
#else
- kprintf("ehci_idone: ex=%p is done!\n", ex);
+ printf("ehci_idone: ex=%p is done!\n", ex);
#endif
return;
}
ex->isdone = 1;
- crit_exit();
+ splx(s);
}
#endif
@@ -964,6 +973,12 @@
callout_stop(&sc->sc_tmo_intrlist);
callout_stop(&sc->sc_tmo_pcd);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ if (sc->sc_powerhook != NULL)
+ powerhook_disestablish(sc->sc_powerhook);
+ if (sc->sc_shutdownhook != NULL)
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+#endif
usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
usb_freemem(&sc->sc_bus, &sc->sc_fldma);
@@ -984,7 +999,7 @@
{
ehci_softc_t *sc = v;
u_int32_t cmd, hcr;
- int i;
+ int s, i;
#ifdef EHCI_DEBUG
DPRINTF(("ehci_power: sc=%p, why=%d\n", sc, why));
@@ -992,8 +1007,7 @@
ehci_dump_regs(sc);
#endif
- crit_enter();
-
+ s = splhardusb();
switch (why) {
case PWR_SUSPEND:
case PWR_STANDBY:
@@ -1021,7 +1035,7 @@
usb_delay_ms(&sc->sc_bus, 1);
}
if (hcr != 0) {
- kprintf("%s: reset timeout\n",
+ printf("%s: reset timeout\n",
device_get_nameunit(sc->sc_bus.bdev));
}
@@ -1036,7 +1050,7 @@
usb_delay_ms(&sc->sc_bus, 1);
}
if (hcr != EHCI_STS_HCH) {
- kprintf("%s: config timeout\n",
+ printf("%s: config timeout\n",
device_get_nameunit(sc->sc_bus.bdev));
}
@@ -1086,7 +1100,7 @@
usb_delay_ms(&sc->sc_bus, 1);
}
if (hcr == EHCI_STS_HCH) {
- kprintf("%s: config timeout\n",
+ printf("%s: config timeout\n",
device_get_nameunit(sc->sc_bus.bdev));
}
@@ -1099,7 +1113,7 @@
case PWR_SOFTRESUME:
break;
}
- crit_exit();
+ splx(s);
#ifdef EHCI_DEBUG
DPRINTF(("ehci_power: sc=%p\n", sc));
@@ -1128,7 +1142,7 @@
err = usb_allocmem(bus, size, 0, dma);
#ifdef EHCI_DEBUG
if (err)
- kprintf("ehci_allocm: usb_allocmem()=%d\n", err);
+ printf("ehci_allocm: usb_allocmem()=%d\n", err);
#endif
return (err);
}
@@ -1150,12 +1164,12 @@
STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_FREE) {
- kprintf("ehci_allocx: xfer=%p not free, 0x%08x\n", xfer,
+ printf("ehci_allocx: xfer=%p not free, 0x%08x\n", xfer,
xfer->busy_free);
}
#endif
} else {
- xfer = kmalloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT);
+ xfer = malloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT);
}
if (xfer != NULL) {
memset(xfer, 0, sizeof(struct ehci_xfer));
@@ -1177,13 +1191,13 @@
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
- kprintf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer,
+ printf("ehci_freex: xfer=%p not busy, 0x%08x\n", xfer,
xfer->busy_free);
return;
}
xfer->busy_free = XFER_FREE;
if (!EXFER(xfer)->isdone) {
- kprintf("ehci_freex: !isdone\n");
+ printf("ehci_freex: !isdone\n");
return;
}
#endif
@@ -1217,17 +1231,17 @@
ehci_dump_regs(ehci_softc_t *sc)
{
int i;
- kprintf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n",
+ printf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n",
EOREAD4(sc, EHCI_USBCMD),
EOREAD4(sc, EHCI_USBSTS),
EOREAD4(sc, EHCI_USBINTR));
- kprintf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
+ printf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
EOREAD4(sc, EHCI_FRINDEX),
EOREAD4(sc, EHCI_CTRLDSSEGMENT),
EOREAD4(sc, EHCI_PERIODICLISTBASE),
EOREAD4(sc, EHCI_ASYNCLISTADDR));
for (i = 1; i <= sc->sc_noport; i++)
- kprintf("port %d status=0x%08x\n", i,
+ printf("port %d status=0x%08x\n", i,
EOREAD4(sc, EHCI_PORTSC(i)));
}
@@ -1245,20 +1259,20 @@
ehci_dump_link(ehci_link_t link, int type)
{
link = le32toh(link);
- kprintf("0x%08x", link);
+ printf("0x%08x", link);
if (link & EHCI_LINK_TERMINATE)
- kprintf("<T>");
+ printf("<T>");
else {
- kprintf("<");
+ printf("<");
if (type) {
switch (EHCI_LINK_TYPE(link)) {
- case EHCI_LINK_ITD: kprintf("ITD"); break;
- case EHCI_LINK_QH: kprintf("QH"); break;
- case EHCI_LINK_SITD: kprintf("SITD"); break;
- case EHCI_LINK_FSTN: kprintf("FSTN"); break;
+ case EHCI_LINK_ITD: printf("ITD"); break;
+ case EHCI_LINK_QH: printf("QH"); break;
+ case EHCI_LINK_SITD: printf("SITD"); break;
+ case EHCI_LINK_FSTN: printf("FSTN"); break;
}
}
- kprintf(">");
+ printf(">");
}
}
@@ -1274,13 +1288,13 @@
stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE);
}
if (sqtd)
- kprintf("dump aborted, too many TDs\n");
+ printf("dump aborted, too many TDs\n");
}
void
ehci_dump_sqtd(ehci_soft_qtd_t *sqtd)
{
- kprintf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
+ printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
ehci_dump_qtd(&sqtd->qtd);
}
@@ -1290,20 +1304,20 @@
u_int32_t s;
char sbuf[128];
- kprintf(" next="); ehci_dump_link(qtd->qtd_next, 0);
- kprintf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0);
- kprintf("\n");
+ printf(" next="); ehci_dump_link(qtd->qtd_next, 0);
+ printf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0);
+ printf("\n");
s = le32toh(qtd->qtd_status);
bitmask_snprintf(EHCI_QTD_GET_STATUS(s),
"\20\10ACTIVE\7HALTED\6BUFERR\5BABBLE\4XACTERR"
"\3MISSED\2SPLIT\1PING", sbuf, sizeof(sbuf));
- kprintf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
+ printf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
s, EHCI_QTD_GET_TOGGLE(s), EHCI_QTD_GET_BYTES(s),
EHCI_QTD_GET_IOC(s), EHCI_QTD_GET_C_PAGE(s));
- kprintf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s),
+ printf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s),
EHCI_QTD_GET_PID(s), sbuf);
for (s = 0; s < 5; s++)
- kprintf(" buffer[%d]=0x%08x\n", s, le32toh(qtd->qtd_buffer[s]));
+ printf(" buffer[%d]=0x%08x\n", s, le32toh(qtd->qtd_buffer[s]));
}
void
@@ -1312,26 +1326,26 @@
ehci_qh_t *qh = &sqh->qh;
u_int32_t endp, endphub;
- kprintf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
- kprintf(" sqtd=%p inactivesqtd=%p\n", sqh->sqtd, sqh->inactivesqtd);
- kprintf(" link="); ehci_dump_link(qh->qh_link, 1); kprintf("\n");
+ printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
+ printf(" sqtd=%p inactivesqtd=%p\n", sqh->sqtd, sqh->inactivesqtd);
+ printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
endp = le32toh(qh->qh_endp);
- kprintf(" endp=0x%08x\n", endp);
- kprintf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n",
+ printf(" endp=0x%08x\n", endp);
+ printf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n",
EHCI_QH_GET_ADDR(endp), EHCI_QH_GET_INACT(endp),
EHCI_QH_GET_ENDPT(endp), EHCI_QH_GET_EPS(endp),
EHCI_QH_GET_DTC(endp), EHCI_QH_GET_HRECL(endp));
- kprintf(" mpl=0x%x ctl=%d nrl=%d\n",
+ printf(" mpl=0x%x ctl=%d nrl=%d\n",
EHCI_QH_GET_MPL(endp), EHCI_QH_GET_CTL(endp),
EHCI_QH_GET_NRL(endp));
endphub = le32toh(qh->qh_endphub);
- kprintf(" endphub=0x%08x\n", endphub);
- kprintf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n",
+ printf(" endphub=0x%08x\n", endphub);
+ printf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n",
EHCI_QH_GET_SMASK(endphub), EHCI_QH_GET_CMASK(endphub),
EHCI_QH_GET_HUBA(endphub), EHCI_QH_GET_PORT(endphub),
EHCI_QH_GET_MULT(endphub));
- kprintf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); kprintf("\n");
- kprintf("Overlay qTD:\n");
+ printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
+ printf("Overlay qTD:\n");
ehci_dump_qtd(&qh->qh_qtd);
}
@@ -1339,7 +1353,7 @@
static void
ehci_dump_exfer(struct ehci_xfer *ex)
{
- kprintf("ehci_dump_exfer: ex=%p\n", ex);
+ printf("ehci_dump_exfer: ex=%p\n", ex);
}
#endif
#endif
@@ -1355,6 +1369,7 @@
struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
ehci_soft_qh_t *sqh;
usbd_status err;
+ int s;
int ival, speed, naks;
int hshubaddr, hshubport;
@@ -1394,7 +1409,7 @@
default: panic("ehci_open: bad device speed %d", dev->speed);
}
if (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_ISOCHRONOUS) {
- kprintf("%s: *** WARNING: opening low/full speed device, this "
+ printf("%s: *** WARNING: opening low/full speed device, this "
"does not work yet.\n",
device_get_nameunit(sc->sc_bus.bdev));
DPRINTFN(1,("ehci_open: hshubaddr=%d hshubport=%d\n",
@@ -1437,20 +1452,20 @@
0, &epipe->u.ctl.reqdma);
#ifdef EHCI_DEBUG
if (err)
- kprintf("ehci_open: usb_allocmem()=%d\n", err);
+ printf("ehci_open: usb_allocmem()=%d\n", err);
#endif
if (err)
goto bad1;
pipe->methods = &ehci_device_ctrl_methods;
- crit_enter();
+ s = splusb();
ehci_add_qh(sqh, sc->sc_async_head);
- crit_exit();
+ splx(s);
break;
case UE_BULK:
pipe->methods = &ehci_device_bulk_methods;
- crit_enter();
+ s = splusb();
ehci_add_qh(sqh, sc->sc_async_head);
- crit_exit();
+ splx(s);
break;
case UE_INTERRUPT:
pipe->methods = &ehci_device_intr_methods;
@@ -1473,13 +1488,15 @@
}
/*
- * Add an ED to the schedule. Called while in a critical section.
+ * Add an ED to the schedule. Called at splusb().
* If in the async schedule, it will always have a next.
* If in the intr schedule it may not.
*/
void
ehci_add_qh(ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
{
+ SPLUSBCHECK;
+
sqh->next = head->next;
sqh->prev = head;
sqh->qh.qh_link = head->qh.qh_link;
@@ -1490,19 +1507,20 @@
#ifdef EHCI_DEBUG
if (ehcidebug > 5) {
- kprintf("ehci_add_qh:\n");
+ printf("ehci_add_qh:\n");
ehci_dump_sqh(sqh);
}
#endif
}
/*
- * Remove an ED from the schedule. Called while in a critical section.
+ * Remove an ED from the schedule. Called at splusb().
* Will always have a 'next' if it's in the async list as it's circular.
*/
void
ehci_rem_qh(ehci_softc_t *sc, ehci_soft_qh_t *sqh, ehci_soft_qh_t *head)
{
+ SPLUSBCHECK;
/* XXX */
sqh->prev->qh.qh_link = sqh->qh.qh_link;
sqh->prev->next = sqh->next;
@@ -1529,7 +1547,7 @@
if (EHCI_LINK_ADDR(le32toh(sqh->qh.qh_qtd.qtd_next)) !=
sqtd->physaddr) {
#ifdef EHCI_DEBUG
- kprintf("ehci_activate_qh: unexpected next ptr\n");
+ printf("ehci_activate_qh: unexpected next ptr\n");
ehci_dump_sqh(sqh);
ehci_dump_sqtds(sqh->sqtd);
#endif
@@ -1554,7 +1572,7 @@
void
ehci_sync_hc(ehci_softc_t *sc)
{
- int error;
+ int s, error;
if (sc->sc_dying) {
DPRINTFN(2,("ehci_sync_hc: dying\n"));
@@ -1562,21 +1580,21 @@
}
DPRINTFN(2,("ehci_sync_hc: enter\n"));
/* get doorbell */
- lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE);
- crit_enter();
+ lockmgr(&sc->sc_doorbell_lock, LK_EXCLUSIVE, NULL);
+ s = splhardusb();
/* ask for doorbell */
EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) | EHCI_CMD_IAAD);
DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n",
EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS)));
- error = tsleep(&sc->sc_async_head, 0, "ehcidi", hz); /* bell wait */
+ error = tsleep(&sc->sc_async_head, PZERO, "ehcidi", hz); /* bell wait */
DPRINTFN(1,("ehci_sync_hc: cmd=0x%08x sts=0x%08x\n",
EOREAD4(sc, EHCI_USBCMD), EOREAD4(sc, EHCI_USBSTS)));
- crit_exit();
+ splx(s);
/* release doorbell */
- lockmgr(&sc->sc_doorbell_lock, LK_RELEASE);
+ lockmgr(&sc->sc_doorbell_lock, LK_RELEASE, NULL);
#ifdef DIAGNOSTIC
if (error)
- kprintf("ehci_sync_hc: tsleep() = %d\n", error);
+ printf("ehci_sync_hc: tsleep() = %d\n", error);
#endif
DPRINTFN(2,("ehci_sync_hc: exit\n"));
}
@@ -1696,7 +1714,7 @@
usb_device_request_t *req;
void *buf = NULL;
int port, i;
- int len, value, index, l, totlen = 0;
+ int s, len, value, index, l, totlen = 0;
usb_port_status_t ps;
usb_hub_descriptor_t hubd;
usbd_status err;
@@ -1960,7 +1978,8 @@
goto ret;
}
v = EOREAD4(sc, EHCI_PORTSC(index));
- DPRINTFN(8,("ehci_root_ctrl_start: port status=0x%04x\n", v));
+ DPRINTFN(8,("ehci_root_ctrl_start: port status=0x%04x\n",
+ v));
i = UPS_HIGH_SPEED;
if (v & EHCI_PS_CS) i |= UPS_CURRENT_CONNECT_STATUS;
if (v & EHCI_PS_PE) i |= UPS_PORT_ENABLED;
@@ -2026,7 +2045,7 @@
v = EOREAD4(sc, port);
DPRINTF(("ehci after reset, status=0x%08x\n", v));
if (v & EHCI_PS_PR) {
- kprintf("%s: port reset timeout\n",
+ printf("%s: port reset timeout\n",
device_get_nameunit(sc->sc_bus.bdev));
return (USBD_TIMEOUT);
}
@@ -2071,10 +2090,10 @@
err = USBD_NORMAL_COMPLETION;
ret:
xfer->status = err;
- crit_enter();
+ s = splusb();
hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -2089,16 +2108,16 @@
if (sc->sc_npcomp != 0) {
int i = (index-1) / sc->sc_npcomp;
if (i >= sc->sc_ncomp)
- kprintf("%s: strange port\n",
+ printf("%s: strange port\n",
device_get_nameunit(sc->sc_bus.bdev));
else
- kprintf("%s: handing over %s speed device on "
+ printf("%s: handing over %s speed device on "
"port %d to %s\n",
device_get_nameunit(sc->sc_bus.bdev),
lowspeed ? "low" : "full",
index, device_get_nameunit(sc->sc_comps[i]->bdev));
} else {
- kprintf("%s: npcomp == 0\n", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s: npcomp == 0\n", device_get_nameunit(sc->sc_bus.bdev));
}
#endif
port = EHCI_PORTSC(index);
@@ -2158,14 +2177,16 @@
static void
ehci_root_intr_abort(usbd_xfer_handle xfer)
{
+ int s;
+
if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("ehci_root_intr_abort: remove\n"));
xfer->pipe->intrxfer = NULL;
}
xfer->status = USBD_CANCELLED;
- crit_enter();
+ s = splusb();
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
}
/* Close the root pipe. */
@@ -2201,7 +2222,7 @@
EHCI_PAGE_SIZE, &dma);
#ifdef EHCI_DEBUG
if (err)
- kprintf("ehci_alloc_sqh: usb_allocmem()=%d\n", err);
+ printf("ehci_alloc_sqh: usb_allocmem()=%d\n", err);
#endif
if (err)
return (NULL);
@@ -2254,6 +2275,7 @@
usbd_status err;
int i, offs;
usb_dma_t dma;
+ int s;
if (sc->sc_freeqtds == NULL) {
DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n"));
@@ -2261,11 +2283,11 @@
EHCI_PAGE_SIZE, &dma);
#ifdef EHCI_DEBUG
if (err)
- kprintf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err);
+ printf("ehci_alloc_sqtd: usb_allocmem()=%d\n", err);
#endif
if (err)
return (NULL);
- crit_enter();
+ s = splusb();
for(i = 0; i < EHCI_SQTD_CHUNK; i++) {
offs = i * EHCI_SQTD_SIZE;
sqtd = KERNADDR(&dma, offs);
@@ -2273,10 +2295,10 @@
sqtd->nextqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd;
}
- crit_exit();
+ splx(s);
}
- crit_enter();
+ s = splusb();
sqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd->nextqtd;
sqtd->qtd.qtd_next = EHCI_NULL;
@@ -2288,7 +2310,7 @@
}
sqtd->nextqtd = NULL;
sqtd->xfer = NULL;
- crit_exit();
+ splx(s);
return (sqtd);
}
@@ -2296,10 +2318,12 @@
void
ehci_free_sqtd(ehci_softc_t *sc, ehci_soft_qtd_t *sqtd)
{
- crit_enter();
+ int s;
+
+ s = splusb();
sqtd->nextqtd = sc->sc_freeqtds;
sc->sc_freeqtds = sqtd;
- crit_exit();
+ splx(s);
}
usbd_status
@@ -2382,7 +2406,7 @@
/*
* Must stop if there is any gap before or after
* the page boundary.
- */
+ */
if (EHCI_PAGE_OFFSET(dataphys + pagelen) != 0)
break;
if (seg < dma->nsegs && EHCI_PAGE_OFFSET(segoff +
@@ -2496,10 +2520,11 @@
struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
ehci_softc_t *sc = (ehci_softc_t *)pipe->device->bus;
ehci_soft_qh_t *sqh = epipe->sqh;
+ int s;
- crit_enter();
+ s = splusb();
ehci_rem_qh(sc, sqh, head);
- crit_exit();
+ splx(s);
pipe->endpoint->savedtoggle =
EHCI_QTD_GET_TOGGLE(le32toh(sqh->qh.qh_qtd.qtd_status));
ehci_free_sqh(sc, epipe->sqh);
@@ -2507,8 +2532,8 @@
/*
* Abort a device request.
- * If this routine is called from a critical section it guarantees that the
- * request will be removed from the hardware scheduling and that the callback
+ * If this routine is called at splusb() it guarantees that the request
+ * will be removed from the hardware scheduling and that the callback
* for it will be called with USBD_CANCELLED status.
* It's impossible to guarantee that the requested transfer will not
* have happened since the hardware runs concurrently.
@@ -2524,6 +2549,7 @@
ehci_soft_qh_t *sqh = epipe->sqh;
ehci_soft_qtd_t *sqtd, *snext;
ehci_physaddr_t cur, us, next;
+ int s;
int hit, i;
/* int count = 0; */
ehci_soft_qh_t *psqh;
@@ -2532,16 +2558,16 @@
if (sc->sc_dying) {
/* If we're dying, just do the software part. */
- crit_enter();
+ s = splusb();
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
usb_rem_task(epipe->pipe.device, &exfer->abort_task);
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
return;
}
- if (xfer->device->bus->intr_context /* || !curproc REMOVED DFly */)
+ if (xfer->device->bus->intr_context || !curproc)
panic("ehci_abort_xfer: not in process context");
/*
@@ -2558,19 +2584,19 @@
DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n"));
exfer->ehci_xfer_flags |= EHCI_XFER_ABORTWAIT;
while (exfer->ehci_xfer_flags & EHCI_XFER_ABORTING)
- tsleep(&exfer->ehci_xfer_flags, 0, "ehciaw", 0);
+ tsleep(&exfer->ehci_xfer_flags, PZERO, "ehciaw", 0);
return;
}
/*
* Step 1: Make interrupt routine and timeouts ignore xfer.
*/
- crit_enter();
+ s = splusb();
exfer->ehci_xfer_flags |= EHCI_XFER_ABORTING;
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
usb_rem_task(epipe->pipe.device, &exfer->abort_task);
- crit_exit();
+ splx(s);
/*
* Step 2: Wait until we know hardware has finished any possible
@@ -2587,13 +2613,13 @@
* The hardware has no reference to completed items (TDs).
* It's safe to remove them at any time.
*/
- crit_enter();
+ s = splusb();
#ifdef USB_USE_SOFTINTR
sc->sc_softwake = 1;
#endif /* USB_USE_SOFTINTR */
usb_schedsoftintr(&sc->sc_bus);
#ifdef USB_USE_SOFTINTR
- tsleep(&sc->sc_softwake, 0, "ehciab", 0);
+ tsleep(&sc->sc_softwake, PZERO, "ehciab", 0);
#endif /* USB_USE_SOFTINTR */
/*
@@ -2682,8 +2708,8 @@
}
usb_transfer_complete(xfer);
- /* kprintf("%s: %d TDs aborted\n", __func__, count); */
- crit_exit();
+ /* printf("%s: %d TDs aborted\n", __func__, count); */
+ splx(s);
#undef exfer
}
@@ -2707,18 +2733,20 @@
/* Execute the abort in a process context. */
usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task,
- USB_TASKQ_HC);
+ USB_TASKQ_HC);
}
void
ehci_timeout_task(void *addr)
{
usbd_xfer_handle xfer = addr;
+ int s;
DPRINTF(("ehci_timeout_task: xfer=%p\n", xfer));
- crit_enter();
+
+ s = splusb();
ehci_abort_xfer(xfer, USBD_TIMEOUT);
- crit_exit();
+ splx(s);
}
/*
@@ -2736,9 +2764,12 @@
ehci_intrlist_timeout(void *arg)
{
ehci_softc_t *sc = arg;
+ int s = splusb();
DPRINTFN(3, ("ehci_intrlist_timeout\n"));
usb_schedsoftintr(&sc->sc_bus);
+
+ splx(s);
}
/************************/
@@ -2769,7 +2800,7 @@
#ifdef DIAGNOSTIC
if (!(xfer->rqflags & URQ_REQUEST)) {
/* XXX panic */
- kprintf("ehci_device_ctrl_transfer: not a request\n");
+ printf("ehci_device_ctrl_transfer: not a request\n");
return (USBD_INVAL);
}
#endif
@@ -2839,6 +2870,7 @@
int isread;
int len;
usbd_status err;
+ int s;
isread = req->bmRequestType & UT_READ;
len = UGETW(req->wLength);
@@ -2928,21 +2960,21 @@
exfer->sqtdend = stat;
#ifdef DIAGNOSTIC
if (!exfer->isdone) {
- kprintf("ehci_device_request: not done, exfer=%p\n", exfer);
+ printf("ehci_device_request: not done, exfer=%p\n", exfer);
}
exfer->isdone = 0;
#endif
/* Activate the new qTD in the QH list. */
- crit_enter();
+ s = splusb();
ehci_activate_qh(sqh, setup);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
- ehci_timeout, xfer);
+ ehci_timeout, xfer);
}
ehci_add_intr_list(sc, exfer);
xfer->status = USBD_IN_PROGRESS;
- crit_exit();
+ splx(s);
#ifdef EHCI_DEBUG
if (ehcidebug > 10) {
@@ -2998,6 +3030,7 @@
ehci_soft_qh_t *sqh;
usbd_status err;
int len, isread, endpt;
+ int s;
DPRINTFN(2, ("ehci_device_bulk_start: xfer=%p len=%d flags=%d\n",
xfer, xfer->length, xfer->flags));
@@ -3055,20 +3088,20 @@
exfer->sqtdend = dataend;
#ifdef DIAGNOSTIC
if (!exfer->isdone) {
- kprintf("ehci_device_bulk_start: not done, ex=%p\n", exfer);
+ printf("ehci_device_bulk_start: not done, ex=%p\n", exfer);
}
exfer->isdone = 0;
#endif
- crit_enter();
+ s = splusb();
ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
- ehci_timeout, xfer);
+ ehci_timeout, xfer);
}
ehci_add_intr_list(sc, exfer);
xfer->status = USBD_IN_PROGRESS;
- crit_exit();
+ splx(s);
#ifdef EHCI_DEBUG
if (ehcidebug > 10) {
@@ -3077,10 +3110,10 @@
DPRINTF(("ehci_device_bulk_start: data(3)\n"));
ehci_dump_regs(sc);
#if 0
- kprintf("async_head:\n");
+ printf("async_head:\n");
ehci_dump_sqh(sc->sc_async_head);
#endif
- kprintf("sqh:\n");
+ printf("sqh:\n");
ehci_dump_sqh(sqh);
ehci_dump_sqtds(data);
}
@@ -3146,7 +3179,7 @@
/* Pick an interrupt slot at the right level. */
/* XXX could do better than picking at random. */
- islot = EHCI_IQHIDX(lev, karc4random());
+ islot = EHCI_IQHIDX(lev, arc4random());
sqh->islot = islot;
isp = &sc->sc_islots[islot];
@@ -3183,6 +3216,7 @@
ehci_soft_qh_t *sqh;
usbd_status err;
int len, isread, endpt;
+ int s;
DPRINTFN(2, ("ehci_device_intr_start: xfer=%p len=%d flags=%d\n",
xfer, xfer->length, xfer->flags));
@@ -3239,12 +3273,12 @@
exfer->sqtdend = dataend;
#ifdef DIAGNOSTIC
if (!exfer->isdone) {
- kprintf("ehci_device_intr_start: not done, ex=%p\n", exfer);
+ printf("ehci_device_intr_start: not done, ex=%p\n", exfer);
}
exfer->isdone = 0;
#endif
- crit_enter();
+ s = splusb();
ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
@@ -3252,7 +3286,7 @@
}
ehci_add_intr_list(sc, exfer);
xfer->status = USBD_IN_PROGRESS;
- crit_exit();
+ splx(s);
#ifdef EHCI_DEBUG
if (ehcidebug > 10) {
@@ -3260,7 +3294,7 @@
delay(10000);
DPRINTF(("ehci_device_intr_start: data(3)\n"));
ehci_dump_regs(sc);
- kprintf("sqh:\n");
+ printf("sqh:\n");
ehci_dump_sqh(sqh);
ehci_dump_sqtds(data);
}
@@ -3305,7 +3339,7 @@
ehci_soft_qtd_t *data, *dataend, *newinactive;
ehci_soft_qh_t *sqh;
usbd_status err;
- int len, isread, endpt;
+ int len, isread, endpt, s;
DPRINTFN(10, ("ehci_device_intr_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
@@ -3314,7 +3348,7 @@
if (xfer->pipe->repeat) {
ehci_free_sqtd_chain(sc, sqh, ex->sqtdstart,
ex->sqtdend->nextqtd);
-
+
len = epipe->u.intr.length;
xfer->length = len;
endpt = epipe->pipe.endpoint->edesc->bEndpointAddress;
@@ -3348,19 +3382,19 @@
exfer->sqtdend = dataend;
#ifdef DIAGNOSTIC
if (!exfer->isdone) {
- kprintf("ehci_device_intr_done: not done, ex=%p\n",
+ printf("ehci_device_intr_done: not done, ex=%p\n",
exfer);
}
exfer->isdone = 0;
#endif
- crit_enter();
+ s = splusb();
ehci_activate_qh(sqh, data);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle,
MS_TO_TICKS(xfer->timeout), ehci_timeout, xfer);
}
- crit_exit();
+ splx(s);
xfer->status = USBD_IN_PROGRESS;
} else if (xfer->status != USBD_NOMEM && ehci_active_intr_list(ex)) {
--- ehci_pci.c 2008-05-19 10:32:14 +0000
+++ /root/src/sys/dev/usb/ehci_pci.c 2008-04-11 05:50:53 +0000
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -33,11 +33,11 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/dev/usb/ehci_pci.c,v 1.18.2.1 2006/01/26 01:43:13 iedowse Exp $
- * $DragonFly: src/sys/bus/usb/ehci_pci.c,v 1.18 2007/08/14 20:06:13 dillon Exp $
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/ehci_pci.c,v 1.32 2008/04/11 05:50:53 benno Exp $");
+
/*
* USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
*
@@ -58,21 +58,25 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <sys/queue.h>
-#include <sys/lock.h>
+#include <sys/lockmgr.h>
+#include <machine/bus.h>
#include <sys/rman.h>
+#include <machine/resource.h>
-#include <bus/pci/pcivar.h>
-#include <bus/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
-#include <bus/usb/ehcireg.h>
-#include <bus/usb/ehcivar.h>
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
#define PCI_EHCI_VENDORID_ACERLABS 0x10b9
#define PCI_EHCI_VENDORID_AMD 0x1022
@@ -94,9 +98,7 @@
/* AMD */
#define PCI_EHCI_DEVICEID_8111 0x10227463
-#define PCI_EHCI_DEVICEID_CS5536 0x20951022
static const char *ehci_device_8111 = "AMD 8111 USB 2.0 controller";
-static const char *ehci_device_CS5536 = "AMD CS5536 USB 2.0 controller";
/* ATI */
#define PCI_EHCI_DEVICEID_SB200 0x43451002
@@ -145,18 +147,16 @@
#define PCI_EHCI_DEVICEID_ISP156X 0x15621131
static const char *ehci_device_isp156x = "Philips ISP156x USB 2.0 controller";
-/* VIA */
#define PCI_EHCI_DEVICEID_VIA 0x31041106
static const char *ehci_device_via = "VIA VT6202 USB 2.0 controller";
-/* Generic */
static const char *ehci_device_generic = "EHCI (generic) USB 2.0 controller";
#define PCI_EHCI_BASE_REG 0x10
#ifdef USB_DEBUG
#define EHCI_DEBUG USB_DEBUG
-#define DPRINTF(x) do { if (ehcidebug) kprintf x; } while (0)
+#define DPRINTF(x) do { if (ehcidebug) printf x; } while (0)
extern int ehcidebug;
#else
#define DPRINTF(x)
@@ -221,8 +221,6 @@
return (ehci_device_m5239);
case PCI_EHCI_DEVICEID_8111:
return (ehci_device_8111);
- case PCI_EHCI_DEVICEID_CS5536:
- return (ehci_device_CS5536);
case PCI_EHCI_DEVICEID_SB200:
return (ehci_device_sb200);
case PCI_EHCI_DEVICEID_SB400:
@@ -350,48 +348,48 @@
device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self));
switch (pci_get_vendor(self)) {
case PCI_EHCI_VENDORID_ACERLABS:
- ksprintf(sc->sc_vendor, "AcerLabs");
+ sprintf(sc->sc_vendor, "AcerLabs");
break;
case PCI_EHCI_VENDORID_AMD:
- ksprintf(sc->sc_vendor, "AMD");
+ sprintf(sc->sc_vendor, "AMD");
break;
case PCI_EHCI_VENDORID_APPLE:
- ksprintf(sc->sc_vendor, "Apple");
+ sprintf(sc->sc_vendor, "Apple");
break;
case PCI_EHCI_VENDORID_ATI:
- ksprintf(sc->sc_vendor, "ATI");
+ sprintf(sc->sc_vendor, "ATI");
break;
case PCI_EHCI_VENDORID_CMDTECH:
- ksprintf(sc->sc_vendor, "CMDTECH");
+ sprintf(sc->sc_vendor, "CMDTECH");
break;
case PCI_EHCI_VENDORID_INTEL:
- ksprintf(sc->sc_vendor, "Intel");
+ sprintf(sc->sc_vendor, "Intel");
break;
case PCI_EHCI_VENDORID_NEC:
- ksprintf(sc->sc_vendor, "NEC");
+ sprintf(sc->sc_vendor, "NEC");
break;
case PCI_EHCI_VENDORID_OPTI:
- ksprintf(sc->sc_vendor, "OPTi");
+ sprintf(sc->sc_vendor, "OPTi");
break;
case PCI_EHCI_VENDORID_SIS:
- ksprintf(sc->sc_vendor, "SiS");
+ sprintf(sc->sc_vendor, "SiS");
break;
case PCI_EHCI_VENDORID_NVIDIA:
case PCI_EHCI_VENDORID_NVIDIA2:
- ksprintf(sc->sc_vendor, "nVidia");
+ sprintf(sc->sc_vendor, "nVidia");
break;
case PCI_EHCI_VENDORID_VIA:
- ksprintf(sc->sc_vendor, "VIA");
+ sprintf(sc->sc_vendor, "VIA");
break;
default:
if (bootverbose)
device_printf(self, "(New EHCI DeviceId=0x%08x)\n",
pci_get_devid(self));
- ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
+ sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
}
- err = bus_setup_intr(self, sc->irq_res, 0,
- (driver_intr_t *) ehci_intr, sc, &sc->ih, NULL);
+ err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
+ NULL, (driver_intr_t *)ehci_intr, sc, &sc->ih);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->ih = NULL;
@@ -435,15 +433,15 @@
if (res != 0)
continue;
if (buscount != 1) {
- kfree(nbus, M_TEMP);
+ free(nbus, M_TEMP);
continue;
}
if (device_get_devclass(nbus[0]) != dc) {
- kfree(nbus, M_TEMP);
+ free(nbus, M_TEMP);
continue;
}
bsc = device_get_softc(nbus[0]);
- kfree(nbus, M_TEMP);
+ free(nbus, M_TEMP);
DPRINTF(("ehci_pci_attach: companion %s\n",
device_get_nameunit(bsc->bdev)));
sc->sc_comps[ncomp++] = bsc;
@@ -454,10 +452,10 @@
sc->sc_ncomp = ncomp;
/* Allocate a parent dma tag for DMA maps */
- err = bus_dma_tag_create(/*XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.parent_dmatag);
+ NULL, NULL, &sc->sc_bus.parent_dmatag);
if (err) {
device_printf(self, "Could not allocate parent DMA tag (%d)\n",
err);
@@ -469,7 +467,7 @@
err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.buffer_dmatag);
+ busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag);
if (err) {
device_printf(self, "Could not allocate buffer DMA tag (%d)\n",
err);
@@ -511,7 +509,7 @@
bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
if (sc->sc_bus.buffer_dmatag != NULL)
bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
-
+
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
@@ -549,7 +547,7 @@
/* Synchronise with the BIOS if it owns the controller. */
for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
- eecp = EHCI_EECP_NEXT(eec)) {
+ eecp = EHCI_EECP_NEXT(eec)) {
eec = pci_read_config(self, eecp, 4);
if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP)
continue;
@@ -557,7 +555,7 @@
if (legsup & EHCI_LEGSUP_BIOSOWNED) {
pci_write_config(self, eecp,
legsup | EHCI_LEGSUP_OSOWNED, 4);
- kprintf("%s: waiting for BIOS to give up control\n",
+ printf("%s: waiting for BIOS to give up control\n",
device_get_nameunit(sc->sc_bus.bdev));
for (i = 0; i < 5000; i++) {
legsup = pci_read_config(self, eecp, 4);
@@ -566,7 +564,7 @@
DELAY(1000);
}
if (legsup & EHCI_LEGSUP_BIOSOWNED)
- kprintf("%s: timed out waiting for BIOS\n",
+ printf("%s: timed out waiting for BIOS\n",
device_get_nameunit(sc->sc_bus.bdev));
}
}
@@ -582,7 +580,7 @@
cparams = EREAD4(sc, EHCI_HCCPARAMS);
for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
- eecp = EHCI_EECP_NEXT(eec)) {
+ eecp = EHCI_EECP_NEXT(eec)) {
eec = pci_read_config(self, eecp, 4);
if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP)
continue;
--- ehcireg.h 2007-06-27 12:27:59 +0000
+++ /root/src/sys/dev/usb/ehcireg.h 2005-09-18 11:45:39 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: ehcireg.h,v 1.18 2004/10/22 10:38:17 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ehcireg.h,v 1.7.2.1 2006/01/26 01:43:13 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/ehcireg.h,v 1.7 2007/06/27 12:27:59 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/ehcireg.h,v 1.8 2005/09/18 11:45:39 netchild Exp $ */
-/*
+/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -183,7 +182,9 @@
#define EHCI_PAGE_SIZE 0x1000
#define EHCI_PAGE(x) ((x) &~ 0xfff)
#define EHCI_PAGE_OFFSET(x) ((x) & 0xfff)
+#if defined(__FreeBSD__)
#define EHCI_PAGE_MASK(x) ((x) & 0xfff)
+#endif
typedef u_int32_t ehci_link_t;
#define EHCI_LINK_TERMINATE 0x00000001
@@ -244,7 +245,7 @@
#define EHCI_QTD_SET_TOGGLE(x) ((x) << 31)
#define EHCI_QTD_TOGGLE_MASK 0x80000000
ehci_physaddr_t qtd_buffer[EHCI_QTD_NBUFFERS];
- ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
+ ehci_physaddr_t qtd_buffer_hi[EHCI_QTD_NBUFFERS];
} ehci_qtd_t;
#define EHCI_QTD_ALIGN 32
--- ehcivar.h 2008-05-19 10:17:44 +0000
+++ /root/src/sys/dev/usb/ehcivar.h 2007-06-14 16:23:31 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ehcivar.h,v 1.9.2.1 2006/01/26 01:43:13 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/ehcivar.h,v 1.11 2007/06/30 20:39:22 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/ehcivar.h,v 1.17 2007/06/14 16:23:31 imp Exp $ */
-/*
+/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -81,18 +80,17 @@
* Information about an entry in the interrupt list.
*/
struct ehci_soft_islot {
- ehci_soft_qh_t *sqh; /* Queue Head. */
+ ehci_soft_qh_t *sqh; /* Queue Head. */
};
#define EHCI_FRAMELIST_MAXCOUNT 1024
#define EHCI_IPOLLRATES 8 /* Poll rates (1ms, 2, 4, 8 ... 128) */
#define EHCI_INTRQHS ((1 << EHCI_IPOLLRATES) - 1)
#define EHCI_MAX_POLLRATE (1 << (EHCI_IPOLLRATES - 1))
-#define EHCI_IQHIDX(lev, pos) \
- ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1)
+#define EHCI_IQHIDX(lev, pos) \
+ ((((pos) & ((1 << (lev)) - 1)) | (1 << (lev))) - 1)
#define EHCI_ILEV_IVAL(lev) (1 << (lev))
-
#define EHCI_HASH_SIZE 128
#define EHCI_COMPANION_MAX 8
@@ -101,20 +99,26 @@
typedef struct ehci_softc {
struct usbd_bus sc_bus; /* base device */
+ int sc_flags;
bus_space_tag_t iot;
bus_space_handle_t ioh;
bus_size_t sc_size;
+#if defined(__FreeBSD__)
void *ih;
struct resource *io_res;
struct resource *irq_res;
+#endif
u_int sc_offs; /* offset to operational regs */
- int sc_flags; /* misc flags */
char sc_vendor[32]; /* vendor string for root hub */
int sc_id_vendor; /* vendor ID for root hub */
u_int32_t sc_cmd; /* shadow of cmd reg during suspend */
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+#endif
u_int sc_ncomp;
u_int sc_npcomp;
@@ -123,6 +127,9 @@
usb_dma_t sc_fldma;
ehci_link_t *sc_flist;
u_int sc_flsize;
+#ifndef __FreeBSD__
+ u_int sc_rand; /* XXX need proper intr scheduling */
+#endif
struct ehci_soft_islot sc_islots[EHCI_INTRQHS];
@@ -151,6 +158,9 @@
struct callout sc_tmo_intrlist;
char sc_dying;
+#if defined(__NetBSD__)
+ struct usb_dma_reserve sc_dma_reserve;
+#endif
} ehci_softc_t;
#define EREAD1(sc, a) bus_space_read_1((sc)->iot, (sc)->ioh, (a))
@@ -169,6 +179,9 @@
usbd_status ehci_init(ehci_softc_t *);
int ehci_intr(void *);
int ehci_detach(ehci_softc_t *, int);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+int ehci_activate(device_t, enum devact);
+#endif
void ehci_power(int state, void *priv);
void ehci_shutdown(void *v);
--- hid.c 2008-05-18 17:51:14 +0000
+++ /root/src/sys/dev/usb/hid.c 2008-05-18 21:28:20 +0000
@@ -1,9 +1,9 @@
-/*
- * $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $
- * $FreeBSD: src/sys/dev/usb/hid.c,v 1.23 2003/08/24 17:55:54 obrien Exp $
- * $DragonFly: src/sys/bus/usb/hid.c,v 1.13 2007/06/28 13:55:12 hasso Exp $
- */
-/*
+/* $NetBSD: hid.c,v 1.17 2001/11/13 06:24:53 lukem Exp $ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/hid.c,v 1.29 2007/06/20 05:10:52 imp Exp $");
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -44,14 +44,14 @@
#include <sys/systm.h>
#include <sys/malloc.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbhid.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
-#include <bus/usb/hid.h>
+#include <dev/usb/hid.h>
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
#else
#define DPRINTF(x)
@@ -95,7 +95,7 @@
{
struct hid_data *s;
- s = kmalloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO);
+ s = malloc(sizeof *s, M_TEMP, M_WAITOK|M_ZERO);
s->start = s->p = d;
s->end = (char *)d + len;
s->kindset = kindset;
@@ -108,10 +108,10 @@
while (s->cur.next != NULL) {
struct hid_item *hi = s->cur.next->next;
- kfree(s->cur.next, M_TEMP);
+ free(s->cur.next, M_TEMP);
s->cur.next = hi;
}
- kfree(s, M_TEMP);
+ free(s, M_TEMP);
}
int
@@ -185,7 +185,7 @@
dval |= *data++ << 24;
break;
default:
- kprintf("BAD LENGTH %d\n", bSize);
+ printf("BAD LENGTH %d\n", bSize);
continue;
}
@@ -250,7 +250,7 @@
s->nu = 0;
return (1);
default:
- kprintf("Main bTag=%d\n", bTag);
+ printf("Main bTag=%d\n", bTag);
break;
}
break;
@@ -287,7 +287,7 @@
c->loc.count = dval;
break;
case 10: /* Push */
- hi = kmalloc(sizeof *hi, M_TEMP, M_WAITOK);
+ hi = malloc(sizeof *hi, M_TEMP, M_WAITOK);
*hi = s->cur;
c->next = hi;
break;
@@ -296,10 +296,10 @@
oldpos = c->loc.pos;
s->cur = *hi;
c->loc.pos = oldpos;
- kfree(hi, M_TEMP);
+ free(hi, M_TEMP);
break;
default:
- kprintf("Global bTag=%d\n", bTag);
+ printf("Global bTag=%d\n", bTag);
break;
}
break;
@@ -352,12 +352,12 @@
c->set_delimiter = dval;
break;
default:
- kprintf("Local bTag=%d\n", bTag);
+ printf("Local bTag=%d\n", bTag);
break;
}
break;
default:
- kprintf("default bType=%d\n", bType);
+ printf("default bType=%d\n", bType);
break;
}
}
@@ -372,7 +372,7 @@
id = 0;
hi = lo = -1;
- for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); ) {
+ for (d = hid_start_parse(buf, len, 1<<k); hid_get_item(d, &h); )
if (h.kind == k) {
if (h.report_ID != 0 && !id)
id = h.report_ID;
@@ -382,7 +382,6 @@
hi = h.loc.pos + h.loc.size * h.loc.count;
}
}
- }
hid_end_parse(d);
size = hi - lo;
if (id != 0) {
--- hid.h 2003-12-30 01:01:44 +0000
+++ /root/src/sys/dev/usb/hid.h 2008-05-18 21:28:20 +0000
@@ -1,10 +1,7 @@
-/*
- * $NetBSD: hid.h,v 1.6 2000/06/01 14:28:57 augustss Exp $
- * $FreeBSD: src/sys/dev/usb/hid.h,v 1.12 2003/07/04 01:50:38 jmg Exp $
- * $DragonFly: src/sys/bus/usb/hid.h,v 1.3 2003/12/30 01:01:44 dillon Exp $
- */
+/* $NetBSD: hid.h,v 1.6 2000/06/01 14:28:57 augustss Exp $ */
+/* $FreeBSD: src/sys/dev/usb/hid.h,v 1.13 2005/01/06 01:43:27 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
--- ohci.c 2008-05-19 01:15:42 +0000
+++ /root/src/sys/dev/usb/ohci.c 2008-05-13 20:58:08 +0000
@@ -1,6 +1,4 @@
/* $NetBSD: ohci.c,v 1.138 2003/02/08 03:32:50 ichiro Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.154.2.4 2006/06/26 00:31:25 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/ohci.c,v 1.25 2008/04/20 13:44:25 swildner Exp $ */
/* Also, already ported:
* $NetBSD: ohci.c,v 1.140 2003/05/13 04:42:00 gson Exp $
@@ -14,7 +12,10 @@
* $NetBSD: ohci.c,v 1.148 2004/06/22 18:27:46 mycroft Exp $
*/
-/*
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/ohci.c,v 1.172 2008/05/13 20:58:08 marius Exp $");
+
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -65,35 +66,35 @@
#include <sys/endian.h>
#include <sys/module.h>
#include <sys/bus.h>
-#if defined(DIAGNOSTIC) && defined(__i386__)
+#if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
#include <machine/cpu.h>
#endif
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
-#include <sys/thread2.h>
+#include <machine/bus.h>
#include <machine/endian.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
-#include <bus/usb/usb_quirks.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usb_quirks.h>
-#include <bus/usb/ohcireg.h>
-#include <bus/usb/ohcivar.h>
+#include <dev/usb/ohcireg.h>
+#include <dev/usb/ohcivar.h>
#define delay(d) DELAY(d)
#ifdef USB_DEBUG
-#define DPRINTF(x) if (ohcidebug) kprintf x
-#define DPRINTFN(n,x) if (ohcidebug>(n)) kprintf x
+#define DPRINTF(x) if (ohcidebug) printf x
+#define DPRINTFN(n,x) if (ohcidebug>(n)) printf x
int ohcidebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
&ohcidebug, 0, "ohci debug level");
-#define bitmask_snprintf(q,f,b,l) ksnprintf((b), (l), "%b", (q), (f))
+#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
@@ -118,6 +119,10 @@
ohci_softc_t *, int, int, usbd_xfer_handle,
ohci_soft_td_t *, ohci_soft_td_t **);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+static void ohci_shutdown(void *v);
+static void ohci_power(int, void *);
+#endif
static usbd_status ohci_open(usbd_pipe_handle);
static void ohci_poll(struct usbd_bus *);
static void ohci_softintr(void *);
@@ -333,9 +338,13 @@
int i, rv = 0;
sc->sc_dying = 1;
-
callout_stop(&sc->sc_tmo_rhsc);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ powerhook_disestablish(sc->sc_powerhook);
+ shutdownhook_disestablish(sc->sc_shutdownhook);
+#endif
+
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
@@ -394,6 +403,7 @@
usbd_status err;
int i, offs;
usb_dma_t dma;
+ int s;
if (sc->sc_freetds == NULL) {
DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
@@ -401,7 +411,7 @@
OHCI_TD_ALIGN, &dma);
if (err)
return (NULL);
- crit_enter();
+ s = splusb();
for(i = 0; i < OHCI_STD_CHUNK; i++) {
offs = i * OHCI_STD_SIZE;
std = KERNADDR(&dma, offs);
@@ -409,17 +419,17 @@
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
}
- crit_exit();
+ splx(s);
}
- crit_enter();
+ s = splusb();
std = sc->sc_freetds;
sc->sc_freetds = std->nexttd;
memset(&std->td, 0, sizeof(ohci_td_t));
std->nexttd = NULL;
std->xfer = NULL;
ohci_hash_add_td(sc, std);
- crit_exit();
+ splx(s);
return (std);
}
@@ -427,11 +437,13 @@
void
ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std)
{
- crit_enter();
+ int s;
+
+ s = splusb();
ohci_hash_rem_td(sc, std);
std->nexttd = sc->sc_freetds;
sc->sc_freetds = std;
- crit_exit();
+ splx(s);
}
usbd_status
@@ -476,22 +488,6 @@
* be the 0th byte in the same 4K page that contains the
* last byte of the buffer (the 4K boundary crossing may
* occur within a data packet transfer.)
- *
- * If/when dma has multiple segments, this will need to
- * properly handle fragmenting TD's.
- *
- * Note that if we are gathering data from multiple SMALL
- * segments, e.g. mbufs, we need to do special gymnastics,
- * e.g. bounce buffering or data aggregation,
- * BEFORE WE GET HERE because a bulk USB transfer must
- * consist of maximally sized packets right up to the end.
- * A shorter than maximal packet means that it is the end
- * of the transfer. If the data transfer length is a
- * multiple of the packet size, then a 0 byte
- * packet will be the signal of the end of transfer.
- * Since packets can't cross TDs this means that
- * each TD except the last one must cover an exact multiple
- * of the maximal packet length.
*/
KASSERT(seg < dma->nsegs, ("ohci_alloc_std_chain: overrun"));
dataphys = dma->segs[seg].ds_addr + segoff;
@@ -503,8 +499,8 @@
/* Truncate to two OHCI pages if there are more. */
if (curlen > 2 * OHCI_PAGE_SIZE -
OHCI_PAGE_OFFSET(dataphys))
- curlen = 2 * OHCI_PAGE_SIZE -
- OHCI_PAGE_OFFSET(dataphys);
+ curlen = 2 * OHCI_PAGE_SIZE -
+ OHCI_PAGE_OFFSET(dataphys);
if (curlen < len)
curlen -= curlen % maxp;
physend = dataphys + curlen - 1;
@@ -577,10 +573,9 @@
end = cur;
cur = next;
}
- if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
+ if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
alen % UGETW(opipe->pipe.endpoint->edesc->wMaxPacketSize) == 0) {
/* Force a 0 length transfer at the end. */
-
next = ohci_alloc_std(sc);
if (next == NULL)
goto nomem;
@@ -624,36 +619,34 @@
{
ohci_soft_itd_t *sitd;
usbd_status err;
- int i, offs;
+ int i, s, offs;
usb_dma_t dma;
- /* XXX: crit section? */
if (sc->sc_freeitds == NULL) {
DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
- err = usb_allocmem(&sc->sc_bus,
- OHCI_SITD_SIZE * OHCI_SITD_CHUNK,
- OHCI_ITD_ALIGN, &dma);
+ err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE * OHCI_SITD_CHUNK,
+ OHCI_ITD_ALIGN, &dma);
if (err)
return (NULL);
- crit_enter();
- for (i = 0; i < OHCI_SITD_CHUNK; i++) {
+ s = splusb();
+ for(i = 0; i < OHCI_SITD_CHUNK; i++) {
offs = i * OHCI_SITD_SIZE;
sitd = KERNADDR(&dma, offs);
sitd->physaddr = DMAADDR(&dma, offs);
sitd->nextitd = sc->sc_freeitds;
sc->sc_freeitds = sitd;
}
- crit_exit();
+ splx(s);
}
- crit_enter();
+ s = splusb();
sitd = sc->sc_freeitds;
sc->sc_freeitds = sitd->nextitd;
memset(&sitd->itd, 0, sizeof(ohci_itd_t));
sitd->nextitd = NULL;
sitd->xfer = NULL;
ohci_hash_add_itd(sc, sitd);
- crit_exit();
+ splx(s);
#ifdef DIAGNOSTIC
sitd->isdone = 0;
@@ -665,6 +658,8 @@
void
ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
{
+ int s;
+
DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd));
#ifdef DIAGNOSTIC
@@ -676,11 +671,11 @@
sitd->isdone = 0;
#endif
- crit_enter();
+ s = splusb();
ohci_hash_rem_itd(sc, sitd);
sitd->nextitd = sc->sc_freeitds;
sc->sc_freeitds = sitd;
- crit_exit();
+ splx(s);
}
usbd_status
@@ -692,13 +687,13 @@
u_int32_t rev;
DPRINTF(("ohci_init: start\n"));
- kprintf("%s:", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s:", device_get_nameunit(sc->sc_bus.bdev));
rev = OREAD4(sc, OHCI_REVISION);
- kprintf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
+ printf(" OHCI version %d.%d%s\n", 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) {
- kprintf("%s: unsupported OHCI revision\n",
+ printf("%s: unsupported OHCI revision\n",
device_get_nameunit(sc->sc_bus.bdev));
sc->sc_bus.usbrev = USBREV_UNKNOWN;
return (USBD_INVAL);
@@ -777,10 +772,10 @@
#ifdef USB_DEBUG
if (ohcidebug > 15) {
for (i = 0; i < OHCI_NO_EDS; i++) {
- kprintf("ed#%d ", i);
+ printf("ed#%d ", i);
ohci_dump_ed(sc->sc_eds[i]);
}
- kprintf("iso ");
+ printf("iso ");
ohci_dump_ed(sc->sc_isoc_head);
}
#endif
@@ -793,7 +788,12 @@
sc->sc_bus.methods = &ohci_bus_methods;
sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
- callout_init(&sc->sc_tmo_rhsc);
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sc->sc_powerhook = powerhook_establish(ohci_power, sc);
+ sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
+#endif
+
+ callout_init(&sc->sc_tmo_rhsc, 0);
return (USBD_NORMAL_COMPLETION);
@@ -829,7 +829,7 @@
ctl = OREAD4(sc, OHCI_CONTROL);
}
if ((ctl & OHCI_IR) == 0) {
- kprintf("%s: SMM does not respond, resetting\n",
+ printf("%s: SMM does not respond, resetting\n",
device_get_nameunit(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
goto reset;
@@ -871,7 +871,7 @@
break;
}
if (hcr) {
- kprintf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s: reset timeout\n", device_get_nameunit(sc->sc_bus.bdev));
return (USBD_IOERROR);
}
#ifdef USB_DEBUG
@@ -918,11 +918,11 @@
* The AMD756 requires a delay before re-reading the register,
* otherwise it will occasionally report 0 ports.
*/
- sc->sc_noport = 0;
- for (i = 0; i < 10 && sc->sc_noport == 0; i++) {
- usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY);
- sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
- }
+ sc->sc_noport = 0;
+ for (i = 0; i < 10 && sc->sc_noport == 0; i++) {
+ usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY);
+ sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
+ }
#ifdef USB_DEBUG
if (ohcidebug > 5)
@@ -954,12 +954,12 @@
STAILQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_FREE) {
- kprintf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer,
+ printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer,
xfer->busy_free);
}
#endif
} else {
- xfer = kmalloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT);
+ xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT);
}
if (xfer != NULL) {
memset(xfer, 0, sizeof (struct ohci_xfer));
@@ -980,7 +980,7 @@
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
- kprintf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer,
+ printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer,
xfer->busy_free);
return;
}
@@ -1013,13 +1013,14 @@
{
ohci_softc_t *sc = v;
u_int32_t ctl;
+ int s;
#ifdef USB_DEBUG
DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why));
ohci_dumpregs(sc);
#endif
- crit_enter();
+ s = splhardusb();
if (why != PWR_RESUME) {
sc->sc_bus.use_polling++;
ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
@@ -1057,7 +1058,7 @@
sc->sc_control = sc->sc_intre = 0;
sc->sc_bus.use_polling--;
}
- crit_exit();
+ splx(s);
}
#ifdef USB_DEBUG
@@ -1114,7 +1115,7 @@
/* If we get an interrupt while polling, then just ignore it. */
if (sc->sc_bus.use_polling) {
#ifdef DIAGNOSTIC
- kprintf("ohci_intr: ignored interrupt while polling\n");
+ printf("ohci_intr: ignored interrupt while polling\n");
#endif
return;
}
@@ -1133,7 +1134,7 @@
/* In case the interrupt occurs before initialization has completed. */
if (sc == NULL || sc->sc_hcca == NULL) {
#ifdef DIAGNOSTIC
- kprintf("ohci_intr: sc->sc_hcca == NULL\n");
+ printf("ohci_intr: sc->sc_hcca == NULL\n");
#endif
return (0);
}
@@ -1181,7 +1182,7 @@
if (eintrs & OHCI_SO) {
sc->sc_overrun_cnt++;
if (usbd_ratecheck(&sc->sc_overrun_ntc)) {
- kprintf("%s: %u scheduling overruns\n",
+ printf("%s: %u scheduling overruns\n",
device_get_nameunit(sc->sc_bus.bdev), sc->sc_overrun_cnt);
sc->sc_overrun_cnt = 0;
}
@@ -1194,11 +1195,11 @@
eintrs &= ~OHCI_WDH;
}
if (eintrs & OHCI_RD) {
- kprintf("%s: resume detect\n", device_get_nameunit(sc->sc_bus.bdev));
+ printf("%s: resume detect\n", device_get_nameunit(sc->sc_bus.bdev));
/* XXX process resume detect */
}
if (eintrs & OHCI_UE) {
- kprintf("%s: unrecoverable error, controller halted\n",
+ printf("%s: unrecoverable error, controller halted\n",
device_get_nameunit(sc->sc_bus.bdev));
OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
/* XXX what else */
@@ -1221,7 +1222,7 @@
/* Block unprocessed interrupts. XXX */
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs);
sc->sc_eintrs &= ~eintrs;
- kprintf("%s: blocking intrs 0x%x\n",
+ printf("%s: blocking intrs 0x%x\n",
device_get_nameunit(sc->sc_bus.bdev), eintrs);
}
@@ -1245,10 +1246,11 @@
ohci_rhsc_enable(void *v_sc)
{
ohci_softc_t *sc = v_sc;
+ int s;
- crit_enter();
+ s = splhardusb();
ohci_rhsc_able(sc, 1);
- crit_exit();
+ splx(s);
}
#ifdef USB_DEBUG
@@ -1317,19 +1319,19 @@
ohci_soft_td_t *std, *sdone, *stdnext, *p, *n;
usbd_xfer_handle xfer;
struct ohci_pipe *opipe;
- int len, cc;
+ int len, cc, s;
int i, j, iframes;
DPRINTFN(10,("ohci_softintr: enter\n"));
sc->sc_bus.intr_context++;
- crit_enter();
+ s = splhardusb();
sdone = sc->sc_sdone;
sc->sc_sdone = NULL;
sidone = sc->sc_sidone;
sc->sc_sidone = NULL;
- crit_exit();
+ splx(s);
DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone));
@@ -1409,9 +1411,9 @@
xfer->status = USBD_STALLED;
else
xfer->status = USBD_IOERROR;
- crit_enter();
+ s = splusb();
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
continue;
}
/*
@@ -1430,9 +1432,9 @@
ohci_free_std(sc, p);
}
xfer->status = USBD_NORMAL_COMPLETION;
- crit_enter();
+ s = splusb();
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
}
#ifdef USB_DEBUG
@@ -1462,7 +1464,7 @@
continue; /*Ignore.*/
#ifdef DIAGNOSTIC
if (sitd->isdone)
- kprintf("ohci_softintr: sitd=%p is done\n", sitd);
+ printf("ohci_softintr: sitd=%p is done\n", sitd);
sitd->isdone = 1;
#endif
opipe = (struct ohci_pipe *)xfer->pipe;
@@ -1499,9 +1501,9 @@
ohci_free_sitd(sc, sitd);
}
- crit_enter();
+ s = splusb();
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
}
}
@@ -1534,14 +1536,12 @@
{
struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
-
usbd_status err;
DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n",
xfer, xfer->actlen));
xfer->hcpriv = NULL;
-
if (xfer->pipe->repeat) {
err = ohci_device_intr_insert(sc, xfer);
if (err) {
@@ -1692,6 +1692,7 @@
int isread;
int len;
usbd_status err;
+ int s;
isread = req->bmRequestType & UT_READ;
len = UGETW(req->wLength);
@@ -1717,7 +1718,6 @@
sed = opipe->sed;
opipe->u.ctl.length = len;
-
next = stat;
/* Set up data transaction */
@@ -1767,15 +1767,15 @@
#endif
/* Insert ED in schedule */
- crit_enter();
+ s = splusb();
sed->ed.ed_tailp = htole32(tail->physaddr);
opipe->tail.td = tail;
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
- ohci_timeout, xfer);
+ ohci_timeout, xfer);
}
- crit_exit();
+ splx(s);
#ifdef USB_DEBUG
if (ohcidebug > 20) {
@@ -1783,9 +1783,9 @@
DPRINTF(("ohci_device_request: status=%x\n",
OREAD4(sc, OHCI_COMMAND_STATUS)));
ohci_dumpregs(sc);
- kprintf("ctrl head:\n");
+ printf("ctrl head:\n");
ohci_dump_ed(sc->sc_ctrl_head);
- kprintf("sed:\n");
+ printf("sed:\n");
ohci_dump_ed(sed);
ohci_dump_tds(setup);
}
@@ -1802,13 +1802,14 @@
}
/*
- * Add an ED to the schedule. Called from a critical section.
+ * Add an ED to the schedule. Called at splusb().
*/
void
ohci_add_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
{
DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head));
+ SPLUSBCHECK;
sed->next = head->next;
sed->ed.ed_nexted = head->ed.ed_nexted;
head->next = sed;
@@ -1816,13 +1817,14 @@
}
/*
- * Remove an ED from the schedule. Called from a critical section.
+ * Remove an ED from the schedule. Called at splusb().
*/
void
ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
{
ohci_soft_ed_t *p;
+ SPLUSBCHECK;
/* XXX */
for (p = head; p != NULL && p->next != sed; p = p->next)
@@ -1844,23 +1846,23 @@
*/
#define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE)
-/*
- * Called from a critical section
- */
+/* Called at splusb() */
void
ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std)
{
int h = HASH(std->physaddr);
+ SPLUSBCHECK;
+
LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext);
}
-/*
- * Called from a critical section
- */
+/* Called at splusb() */
void
ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std)
{
+ SPLUSBCHECK;
+
LIST_REMOVE(std, hnext);
}
@@ -1888,26 +1890,26 @@
return (NULL);
}
-/*
- * Called from a critical section
- */
+/* Called at splusb() */
void
ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
{
int h = HASH(sitd->physaddr);
+ SPLUSBCHECK;
+
DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n",
sitd, (u_long)sitd->physaddr));
LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext);
}
-/*
- * Called from a critical section
- */
+/* Called at splusb() */
void
ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
{
+ SPLUSBCHECK;
+
DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n",
sitd, (u_long)sitd->physaddr));
@@ -1944,19 +1946,20 @@
/* Execute the abort in a process context. */
usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task,
- USB_TASKQ_HC);
+ USB_TASKQ_HC);
}
void
ohci_timeout_task(void *addr)
{
usbd_xfer_handle xfer = addr;
+ int s;
DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer));
- crit_enter();
+ s = splusb();
ohci_abort_xfer(xfer, USBD_TIMEOUT);
- crit_exit();
+ splx(s);
}
#ifdef USB_DEBUG
@@ -1976,7 +1979,7 @@
"\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
sbuf, sizeof(sbuf));
- kprintf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
+ printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
"nexttd=0x%08lx be=0x%08lx\n",
std, (u_long)std->physaddr, sbuf,
OHCI_TD_GET_DI(le32toh(std->td.td_flags)),
@@ -1992,7 +1995,7 @@
{
int i;
- kprintf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
+ printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
"bp0=0x%08lx next=0x%08lx be=0x%08lx\n",
sitd, (u_long)sitd->physaddr,
OHCI_ITD_GET_SF(le32toh(sitd->itd.itd_flags)),
@@ -2003,9 +2006,9 @@
(u_long)le32toh(sitd->itd.itd_nextitd),
(u_long)le32toh(sitd->itd.itd_be));
for (i = 0; i < OHCI_ITD_NOFFSET; i++)
- kprintf("offs[%d]=0x%04x ", i,
+ printf("offs[%d]=0x%04x ", i,
(u_int)le16toh(sitd->itd.itd_offset[i]));
- kprintf("\n");
+ printf("\n");
}
void
@@ -2026,7 +2029,7 @@
bitmask_snprintf((u_int32_t)le32toh(sed->ed.ed_headp),
"\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2));
- kprintf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\ntailp=0x%08lx "
+ printf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\ntailp=0x%08lx "
"headflags=%s headp=0x%08lx nexted=0x%08lx\n",
sed, (u_long)sed->physaddr,
OHCI_ED_GET_FA(le32toh(sed->ed.ed_flags)),
@@ -2053,6 +2056,7 @@
ohci_physaddr_t tdphys;
u_int32_t fmt;
usbd_status err;
+ int s;
int ival;
DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
@@ -2118,9 +2122,9 @@
0, &opipe->u.ctl.reqdma);
if (err)
goto bad;
- crit_enter();
+ s = splusb();
ohci_add_ed(sed, sc->sc_ctrl_head);
- crit_exit();
+ splx(s);
break;
case UE_INTERRUPT:
pipe->methods = &ohci_device_intr_methods;
@@ -2133,9 +2137,9 @@
return (ohci_setup_isoc(pipe));
case UE_BULK:
pipe->methods = &ohci_device_bulk_methods;
- crit_enter();
+ s = splusb();
ohci_add_ed(sed, sc->sc_bulk_head);
- crit_exit();
+ splx(s);
break;
}
}
@@ -2162,15 +2166,16 @@
struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
ohci_soft_ed_t *sed = opipe->sed;
+ int s;
- crit_enter();
+ s = splusb();
#ifdef DIAGNOSTIC
sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
(le32toh(sed->ed.ed_headp) & OHCI_HEADMASK)) {
ohci_soft_td_t *std;
std = ohci_hash_find_td(sc, le32toh(sed->ed.ed_headp));
- kprintf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
+ printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
"tl=0x%x pipe=%p, std=%p\n", sed,
(int)le32toh(sed->ed.ed_headp),
(int)le32toh(sed->ed.ed_tailp),
@@ -2186,13 +2191,13 @@
usb_delay_ms(&sc->sc_bus, 2);
if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
(le32toh(sed->ed.ed_headp) & OHCI_HEADMASK))
- kprintf("ohci_close_pipe: pipe still not empty\n");
+ printf("ohci_close_pipe: pipe still not empty\n");
}
#endif
ohci_rem_ed(sed, head);
/* Make sure the host controller is not touching this ED */
usb_delay_ms(&sc->sc_bus, 1);
- crit_exit();
+ splx(s);
pipe->endpoint->savedtoggle =
(le32toh(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0;
ohci_free_sed(sc, opipe->sed);
@@ -2200,9 +2205,9 @@
/*
* Abort a device request.
- * If this routine is called from a critical section it guarantees that
- * the request will be removed from the hardware scheduling and that
- * the callback for it will be called with USBD_CANCELLED status.
+ * If this routine is called at splusb() it guarantees that the request
+ * will be removed from the hardware scheduling and that the callback
+ * for it will be called with USBD_CANCELLED status.
* It's impossible to guarantee that the requested transfer will not
* have happened since the hardware runs concurrently.
* If the transaction has already happened we rely on the ordinary
@@ -2217,22 +2222,22 @@
ohci_soft_ed_t *sed = opipe->sed;
ohci_soft_td_t *p, *n;
ohci_physaddr_t headp;
- int hit;
+ int s, hit;
DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));
if (sc->sc_dying) {
/* If we're dying, just do the software part. */
- crit_enter();
+ s = splusb();
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
return;
}
- if (xfer->device->bus->intr_context /* || !curproc REMOVED DFly */)
+ if (xfer->device->bus->intr_context || !curproc)
panic("ohci_abort_xfer: not in process context");
/*
@@ -2249,19 +2254,19 @@
DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n"));
oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTWAIT;
while (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING)
- tsleep(&oxfer->ohci_xfer_flags, 0, "ohciaw", 0);
+ tsleep(&oxfer->ohci_xfer_flags, PZERO, "ohciaw", 0);
return;
}
/*
* Step 1: Make interrupt routine and hardware ignore xfer.
*/
- crit_enter();
+ s = splusb();
oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTING;
xfer->status = status; /* make software ignore it */
callout_stop(&xfer->timeout_handle);
usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
- crit_exit();
+ splx(s);
DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */
@@ -2271,14 +2276,15 @@
* has run.
*/
usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */
- crit_enter();
+ s = splusb();
#ifdef USB_USE_SOFTINTR
sc->sc_softwake = 1;
#endif /* USB_USE_SOFTINTR */
usb_schedsoftintr(&sc->sc_bus);
#ifdef USB_USE_SOFTINTR
- tsleep(&sc->sc_softwake, 0, "ohciab", 0);
+ tsleep(&sc->sc_softwake, PZERO, "ohciab", 0);
#endif /* USB_USE_SOFTINTR */
+ splx(s);
/*
* Step 3: Remove any vestiges of the xfer from the hardware.
@@ -2287,12 +2293,13 @@
* the TDs of this xfer we check if the hardware points to
* any of them.
*/
+ s = splusb(); /* XXX why? */
p = xfer->hcpriv;
#ifdef DIAGNOSTIC
if (p == NULL) {
oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; /* XXX */
- crit_exit();
- kprintf("ohci_abort_xfer: hcpriv is NULL\n");
+ splx(s);
+ printf("ohci_abort_xfer: hcpriv is NULL\n");
return;
}
#endif
@@ -2335,7 +2342,7 @@
}
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
}
/*
@@ -2439,7 +2446,7 @@
usb_device_request_t *req;
void *buf = NULL;
int port, i;
- int len, value, index, l, totlen = 0;
+ int s, len, value, index, l, totlen = 0;
usb_port_status_t ps;
usb_hub_descriptor_t hubd;
usbd_status err;
@@ -2733,10 +2740,10 @@
err = USBD_NORMAL_COMPLETION;
ret:
xfer->status = err;
- crit_enter();
+ s = splusb();
hacksync(xfer); /* XXX to compensate for usb_transfer_complete */
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -2787,14 +2794,16 @@
static void
ohci_root_intr_abort(usbd_xfer_handle xfer)
{
+ int s;
+
if (xfer->pipe->intrxfer == xfer) {
DPRINTF(("ohci_root_intr_abort: remove\n"));
xfer->pipe->intrxfer = NULL;
}
xfer->status = USBD_CANCELLED;
- crit_enter();
+ s = splusb();
usb_transfer_complete(xfer);
- crit_exit();
+ splx(s);
}
/* Close the root pipe. */
@@ -2836,7 +2845,7 @@
#ifdef DIAGNOSTIC
if (!(xfer->rqflags & URQ_REQUEST)) {
/* XXX panic */
- kprintf("ohci_device_ctrl_transfer: not a request\n");
+ printf("ohci_device_ctrl_transfer: not a request\n");
return (USBD_INVAL);
}
#endif
@@ -2908,7 +2917,7 @@
int addr = dev->address;
ohci_soft_td_t *data, *tail, *tdp;
ohci_soft_ed_t *sed;
- int len, isread, endpt;
+ int s, len, isread, endpt;
usbd_status err;
if (sc->sc_dying)
@@ -2917,7 +2926,7 @@
#ifdef DIAGNOSTIC
if (xfer->rqflags & URQ_REQUEST) {
/* XXX panic */
- kprintf("ohci_device_bulk_start: a request\n");
+ printf("ohci_device_bulk_start: a request\n");
return (USBD_INVAL);
}
#endif
@@ -2969,7 +2978,7 @@
#endif
/* Insert ED in schedule */
- crit_enter();
+ s = splusb();
for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
tdp->xfer = xfer;
}
@@ -2979,7 +2988,7 @@
OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
if (xfer->timeout && !sc->sc_bus.use_polling) {
callout_reset(&xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
- ohci_timeout, xfer);
+ ohci_timeout, xfer);
}
#if 0
@@ -2993,7 +3002,7 @@
}
#endif
- crit_exit();
+ splx(s);
if (sc->sc_bus.use_polling)
ohci_waitintr(sc, xfer);
@@ -3077,6 +3086,7 @@
ohci_soft_ed_t *sed = opipe->sed;
ohci_soft_td_t *data, *tail;
ohci_physaddr_t dataphys, physend;
+ int s;
DPRINTFN(4, ("ohci_device_intr_insert: xfer=%p", xfer));
@@ -3134,10 +3144,10 @@
#endif
/* Insert ED in schedule */
- crit_enter();
+ s = splusb();
sed->ed.ed_tailp = htole32(tail->physaddr);
opipe->tail.td = tail;
- crit_exit();
+ splx(s);
return (USBD_NORMAL_COMPLETION);
}
@@ -3163,10 +3173,11 @@
int pos = opipe->u.intr.pos;
int j;
ohci_soft_ed_t *p, *sed = opipe->sed;
+ int s;
DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
pipe, nslots, pos));
- crit_enter();
+ s = splusb();
sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
if ((le32toh(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
(le32toh(sed->ed.ed_headp) & OHCI_HEADMASK))
@@ -3186,7 +3197,7 @@
#endif
p->next = sed->next;
p->ed.ed_nexted = sed->ed.ed_nexted;
- crit_exit();
+ splx(s);
for (j = 0; j < nslots; j++)
--sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
@@ -3198,14 +3209,14 @@
static usbd_status
ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival)
{
- int i, j, best;
+ int i, j, s, best;
u_int npoll, slow, shigh, nslots;
u_int bestbw, bw;
ohci_soft_ed_t *hsed, *sed = opipe->sed;
DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe));
if (ival == 0) {
- kprintf("ohci_setintr: 0 interval\n");
+ printf("ohci_setintr: 0 interval\n");
return (USBD_INVAL);
}
@@ -3240,13 +3251,13 @@
DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n",
best, slow, shigh, bestbw));
- crit_enter();
+ s = splusb();
hsed = sc->sc_eds[best];
sed->next = hsed->next;
sed->ed.ed_nexted = hsed->ed.ed_nexted;
hsed->next = sed;
hsed->ed.ed_nexted = htole32(sed->physaddr);
- crit_exit();
+ splx(s);
for (j = 0; j < nslots; j++)
++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS];
@@ -3297,6 +3308,7 @@
ohci_soft_itd_t *sitd, *nsitd;
ohci_physaddr_t dataphys, bp0, physend, prevpage;
int curlen, i, len, ncur, nframes, npages, seg, segoff;
+ int s;
DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
"nframes=%d\n",
@@ -3383,7 +3395,7 @@
nsitd = ohci_alloc_sitd(sc);
if (nsitd == NULL) {
/* XXX what now? */
- kprintf("%s: isoc TD alloc failed\n",
+ printf("%s: isoc TD alloc failed\n",
device_get_nameunit(sc->sc_bus.bdev));
return;
}
@@ -3399,7 +3411,6 @@
OHCI_ITD_SET_DI(6) | /* delay intr a little */
OHCI_ITD_SET_FC(ncur));
sitd->flags = OHCI_ITD_ACTIVE;
-
} else {
sitd->itd.itd_flags = htole32(
OHCI_ITD_NOCC |
@@ -3410,7 +3421,7 @@
}
iso->next += ncur;
- sitd = nsitd;
+ sitd = nsitd;
}
iso->inuse += nframes;
@@ -3431,11 +3442,11 @@
}
#endif
- crit_enter();
+ s = splusb();
opipe->tail.itd = sitd;
sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP);
sed->ed.ed_tailp = htole32(sitd->physaddr);
- crit_exit();
+ splx(s);
#ifdef USB_DEBUG
if (ohcidebug > 5) {
@@ -3454,6 +3465,7 @@
struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed;
+ int s;
DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer));
@@ -3462,15 +3474,15 @@
#ifdef DIAGNOSTIC
if (xfer->status != USBD_IN_PROGRESS)
- kprintf("ohci_device_isoc_start: not in progress %p\n", xfer);
+ printf("ohci_device_isoc_start: not in progress %p\n", xfer);
#endif
/* XXX anything to do? */
- crit_enter();
+ s = splusb();
sed = opipe->sed; /* Turn off ED skip-bit to start processing */
sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* ED's ITD list.*/
- crit_exit();
+ splx(s);
return (USBD_IN_PROGRESS);
}
@@ -3482,9 +3494,9 @@
ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
ohci_soft_ed_t *sed;
ohci_soft_itd_t *sitd, *sitdnext, *tmp_sitd;
- int undone, num_sitds;
+ int s,undone,num_sitds;
- crit_enter();
+ s = splusb();
opipe->aborting = 1;
DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer));
@@ -3492,8 +3504,8 @@
/* Transfer is already done. */
if (xfer->status != USBD_NOT_STARTED &&
xfer->status != USBD_IN_PROGRESS) {
- crit_exit();
- kprintf("ohci_device_isoc_abort: early return\n");
+ splx(s);
+ printf("ohci_device_isoc_abort: early return\n");
return;
}
@@ -3507,8 +3519,8 @@
sitd = xfer->hcpriv;
#ifdef DIAGNOSTIC
if (sitd == NULL) {
- crit_exit();
- kprintf("ohci_device_isoc_abort: hcpriv==0\n");
+ splx(s);
+ printf("ohci_device_isoc_abort: hcpriv==0\n");
return;
}
#endif
@@ -3520,7 +3532,7 @@
#endif
}
- crit_exit();
+ splx(s);
/*
* Each sitd has up to OHCI_ITD_NOFFSET transfers, each can
@@ -3551,7 +3563,7 @@
ohci_free_sitd(sc, sitd);
}
- crit_enter();
+ s = splusb();
/* Run callback. */
usb_transfer_complete(xfer);
@@ -3561,7 +3573,7 @@
sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP); /* remove hardware skip */
- crit_exit();
+ splx(s);
}
void
@@ -3592,13 +3604,14 @@
struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
struct iso *iso = &opipe->u.iso;
+ int s;
iso->next = -1;
iso->inuse = 0;
- crit_enter();
+ s = splusb();
ohci_add_ed(opipe->sed, sc->sc_isoc_head);
- crit_exit();
+ splx(s);
return (USBD_NORMAL_COMPLETION);
}
--- ohci_pci.c 2008-05-19 00:26:21 +0000
+++ /root/src/sys/dev/usb/ohci_pci.c 2007-06-21 14:42:33 +0000
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -33,11 +33,11 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/dev/usb/ohci_pci.c,v 1.44.2.1 2006/01/29 01:26:46 iedowse Exp $
- * $DragonFly: src/sys/bus/usb/ohci_pci.c,v 1.9 2007/08/24 16:02:47 dillon Exp $
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/ohci_pci.c,v 1.50 2007/06/21 14:42:33 imp Exp $");
+
/*
* USB Open Host Controller driver.
*
@@ -55,20 +55,24 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <sys/queue.h>
+#include <machine/bus.h>
#include <sys/rman.h>
+#include <machine/resource.h>
-#include <bus/pci/pcivar.h>
-#include <bus/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
-#include <bus/usb/ohcireg.h>
-#include <bus/usb/ohcivar.h>
+#include <dev/usb/ohcireg.h>
+#include <dev/usb/ohcivar.h>
#define PCI_OHCI_VENDORID_ACERLABS 0x10b9
#define PCI_OHCI_VENDORID_AMD 0x1022
@@ -88,9 +92,6 @@
#define PCI_OHCI_DEVICEID_AMD756 0x740c1022
static const char *ohci_device_amd756 = "AMD-756 USB Controller";
-#define PCI_OHCI_DEVICEID_CS5536 0x20941022
-static const char *ohci_device_cs5536 = "AMD CS5536 [geode companion] USB Controller";
-
#define PCI_OHCI_DEVICEID_AMD766 0x74141022
static const char *ohci_device_amd766 = "AMD-766 USB Controller";
@@ -126,6 +127,7 @@
#define PCI_OHCI_BASE_REG 0x10
+
static device_attach_t ohci_pci_attach;
static device_detach_t ohci_pci_detach;
static device_suspend_t ohci_pci_suspend;
@@ -168,8 +170,6 @@
return (ohci_device_amd756);
case PCI_OHCI_DEVICEID_AMD766:
return (ohci_device_amd766);
- case PCI_OHCI_DEVICEID_CS5536:
- return (ohci_device_cs5536);
case PCI_OHCI_DEVICEID_SB400_1:
case PCI_OHCI_DEVICEID_SB400_2:
return (ohci_device_sb400);
@@ -263,42 +263,42 @@
device_set_desc(sc->sc_bus.bdev, ohci_pci_match(self));
switch (pci_get_vendor(self)) {
case PCI_OHCI_VENDORID_ACERLABS:
- ksprintf(sc->sc_vendor, "AcerLabs");
+ sprintf(sc->sc_vendor, "AcerLabs");
break;
case PCI_OHCI_VENDORID_AMD:
- ksprintf(sc->sc_vendor, "AMD");
+ sprintf(sc->sc_vendor, "AMD");
break;
case PCI_OHCI_VENDORID_APPLE:
- ksprintf(sc->sc_vendor, "Apple");
+ sprintf(sc->sc_vendor, "Apple");
break;
case PCI_OHCI_VENDORID_ATI:
- ksprintf(sc->sc_vendor, "ATI");
+ sprintf(sc->sc_vendor, "ATI");
break;
case PCI_OHCI_VENDORID_CMDTECH:
- ksprintf(sc->sc_vendor, "CMDTECH");
+ sprintf(sc->sc_vendor, "CMDTECH");
break;
case PCI_OHCI_VENDORID_NEC:
- ksprintf(sc->sc_vendor, "NEC");
+ sprintf(sc->sc_vendor, "NEC");
break;
case PCI_OHCI_VENDORID_NVIDIA:
case PCI_OHCI_VENDORID_NVIDIA2:
- ksprintf(sc->sc_vendor, "nVidia");
+ sprintf(sc->sc_vendor, "nVidia");
break;
case PCI_OHCI_VENDORID_OPTI:
- ksprintf(sc->sc_vendor, "OPTi");
+ sprintf(sc->sc_vendor, "OPTi");
break;
case PCI_OHCI_VENDORID_SIS:
- ksprintf(sc->sc_vendor, "SiS");
+ sprintf(sc->sc_vendor, "SiS");
break;
default:
if (bootverbose)
device_printf(self, "(New OHCI DeviceId=0x%08x)\n",
pci_get_devid(self));
- ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
+ sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
}
- err = bus_setup_intr(self, sc->irq_res, 0,
- (driver_intr_t *) ohci_intr, sc, &sc->ih, NULL);
+ err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, NULL, ohci_intr,
+ sc, &sc->ih);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->ih = NULL;
@@ -307,10 +307,10 @@
}
/* Allocate a parent dma tag for DMA maps */
- err = bus_dma_tag_create(/*XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.parent_dmatag);
+ NULL, NULL, &sc->sc_bus.parent_dmatag);
if (err) {
device_printf(self, "Could not allocate parent DMA tag (%d)\n",
err);
@@ -321,7 +321,7 @@
err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.buffer_dmatag);
+ busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag);
if (err) {
device_printf(self, "Could not allocate transfer tag (%d)\n",
err);
@@ -357,7 +357,7 @@
bus_dma_tag_destroy(sc->sc_bus.parent_dmatag);
if (sc->sc_bus.buffer_dmatag != NULL)
bus_dma_tag_destroy(sc->sc_bus.buffer_dmatag);
-
+
if (sc->irq_res && sc->ih) {
int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
@@ -376,7 +376,8 @@
sc->irq_res = NULL;
}
if (sc->io_res) {
- bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->io_res);
+ bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM,
+ sc->io_res);
sc->io_res = NULL;
sc->iot = 0;
sc->ioh = 0;
--- ohcireg.h 2008-05-19 00:19:46 +0000
+++ /root/src/sys/dev/usb/ohcireg.h 2006-05-28 05:27:08 +0000
@@ -1,9 +1,8 @@
/* $NetBSD: ohcireg.h,v 1.17 2000/04/01 09:27:35 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ohcireg.h,v 1.22 2005/01/06 01:43:28 imp Exp $ */
-/* $DragonFly: src/sys/bus/usb/ohcireg.h,v 1.4 2006/12/10 02:03:56 sephe Exp $ */
+/* $FreeBSD: src/sys/dev/usb/ohcireg.h,v 1.23 2006/05/28 05:27:08 iedowse Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
--- ohcivar.h 2008-05-19 00:18:53 +0000
+++ /root/src/sys/dev/usb/ohcivar.h 2007-06-14 16:23:31 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: ohcivar.h,v 1.30 2001/12/31 12:20:35 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.40.2.1 2005/12/04 05:52:23 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/ohcivar.h,v 1.9 2007/06/30 20:39:22 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.47 2007/06/14 16:23:31 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -133,6 +132,10 @@
char sc_vendor[16];
int sc_id_vendor;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+#endif
u_int32_t sc_control; /* Preserved during suspend/standby */
u_int32_t sc_intre;
@@ -140,7 +143,6 @@
struct timeval sc_overrun_ntc;
struct callout sc_tmo_rhsc;
-
char sc_dying;
} ohci_softc_t;
@@ -158,7 +160,5 @@
usbd_status ohci_init(ohci_softc_t *);
void ohci_intr(void *);
int ohci_detach(ohci_softc_t *, int);
-
-
void ohci_shutdown(void *v);
void ohci_power(int state, void *priv);
--- usb_quirks.c 2007-11-05 19:09:42 +0000
+++ /root/src/sys/dev/usb/usb_quirks.c 2008-03-14 15:59:30 +0000
@@ -1,8 +1,6 @@
/* $NetBSD: usb_quirks.c,v 1.50 2004/06/23 02:30:52 mycroft Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.41.2.4 2006/02/15 22:51:08 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/usb_quirks.c,v 1.9 2007/11/05 19:09:42 hasso Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -39,11 +37,16 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.65 2008/03/14 15:59:30 jkim Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usb_quirks.h>
+#include <dev/usb/usb.h>
+
+#include "usbdevs.h"
+#include <dev/usb/usb_quirks.h>
#ifdef USB_DEBUG
extern int usbdebug;
@@ -57,112 +60,60 @@
u_int16_t bcdDevice;
struct usbd_quirks quirks;
} usb_quirks[] = {
- /* KYE Niche mouse */
- { .idVendor = 0x0458, .idProduct = 0x0001, .bcdDevice = 0x100,
- .quirks = { UQ_NO_SET_PROTO}},
- /* Inside Out Networks EdgePort/4 RS232 */
- { .idVendor = 0x1608, .idProduct = 0x0001, .bcdDevice = 0x094,
- .quirks = { UQ_SWAP_UNICODE}},
- /* Dallas Semiconductor J-6502 speakers */
- { .idVendor = 0x04fa, .idProduct = 0x4201, .bcdDevice = 0x0a2,
- .quirks = { UQ_BAD_ADC | UQ_AU_NO_XU }},
- /* Altec Lansing ADA70 speakers */
- { .idVendor = 0x04d2, .idProduct = 0x0070, .bcdDevice = 0x103,
- .quirks = { UQ_BAD_ADC }},
- /* Altec Lansing ASC495 speakers */
- { .idVendor = 0x04d2, .idProduct = 0xff05, .bcdDevice = 0x000,
- .quirks = { UQ_BAD_AUDIO }},
- /* Qtronix Scorpion-980N keyboard */
- { .idVendor = 0x05c7, .idProduct = 0x2011, .bcdDevice = 0x110,
- .quirks = { UQ_SPUR_BUT_UP }},
- /* Alcor Micro, Inc. kbd hub */
- { .idVendor = 0x0566, .idProduct = 0x2802, .bcdDevice = 0x001,
- .quirks = { UQ_SPUR_BUT_UP }},
- /* MCT Corp. hub */
- { .idVendor = 0x0711, .idProduct = 0x0100, .bcdDevice = 0x102,
- .quirks = { UQ_BUS_POWERED }},
- /* MCT Corp. USB-232 interface */
- { .idVendor = 0x0711, .idProduct = 0x0210, .bcdDevice = 0x102,
- .quirks = { UQ_BUS_POWERED }},
- /* Metricom Ricochet GS */
- { .idVendor = 0x0870, .idProduct = 0x0001, .bcdDevice = 0x100,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* Sanyo SCP-4900 USB Phone */
- { .idVendor = 0x0474, .idProduct = 0x0701, .bcdDevice = 0x000,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* Texas Instruments UT-USB41 hub */
- { .idVendor = 0x0451, .idProduct = 0x1446, .bcdDevice = 0x110,
- .quirks = { UQ_POWER_CLAIM }},
- /* Telex Communications Enhanced USB Microphone */
- { .idVendor = 0x0562, .idProduct = 0x0001, .bcdDevice = 0x009,
- .quirks = { UQ_AU_NO_FRAC }},
- /* Silicon Portals Inc. YAP Phone */
- { .idVendor = 0x1527, .idProduct = 0x0201, .bcdDevice = 0x100,
- .quirks = { UQ_AU_INP_ASYNC }},
-
- /*
- * XXX All these HP devices should have a revision number,
- * but I don't know what they are.
- */
- /* HP DeskJet 895C */
- { .idVendor = 0x03f0, .idProduct = 0x0004, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
- /* HP DeskJet 880C */
- { .idVendor = 0x03f0, .idProduct = 0x0104, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
- /* HP DeskJet 815C */
- { .idVendor = 0x03f0, .idProduct = 0x0204, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
- /* HP DeskJet 810C/812C */
- { .idVendor = 0x03f0, .idProduct = 0x0304, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
- /* HP DeskJet 830C */
- { .idVendor = 0x03f0, .idProduct = 0x0404, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
- /* HP DeskJet 1220C */
- { .idVendor = 0x03f0, .idProduct = 0x0212, .bcdDevice = ANY,
- .quirks = { UQ_BROKEN_BIDIR }},
-
- /*
- * YAMAHA router's ucdDevice is the version of firmware and
- * often changes.
- */
- /* YAMAHA NetVolante RTA54i Broadband&ISDN Router */
- { .idVendor = 0x0499, .idProduct = 0x4000, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* YAMAHA NetVolante RTA55i Broadband VoIP Router */
- { .idVendor = 0x0499, .idProduct = 0x4004, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* YAMAHA NetVolante RTW65b Broadband Wireless Router */
- { .idVendor = 0x0499, .idProduct = 0x4001, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* YAMAHA NetVolante RTW65i Broadband&ISDN Wireless Router */
- { .idVendor = 0x0499, .idProduct = 0x4002, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
-
- /* Qualcomm CDMA Technologies MSM modem */
- { .idVendor = 0x05c6, .idProduct = 0x3196, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* Qualcomm CDMA Technologies MSM phone */
- { .idVendor = 0x1004, .idProduct = 0x6000, .bcdDevice = ANY,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
- /* SUNTAC U-Cable type A3 */
- { .idVendor = 0x05db, .idProduct = 0x000b, .bcdDevice = 0x100,
- .quirks = { UQ_ASSUME_CM_OVER_DATA }},
+ { USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
+ 0x094, { UQ_SWAP_UNICODE}},
+ { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }},
+ { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_AU_NO_XU }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }},
+ { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }},
+ { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, { UQ_SPUR_BUT_UP }},
+ { USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, { UQ_SPUR_BUT_UP }},
+ { USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100, 0x102, { UQ_BUS_POWERED }},
+ { USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0x102, { UQ_BUS_POWERED }},
+ { USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, { UQ_POWER_CLAIM }},
+ { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, { UQ_AU_NO_FRAC }},
+ { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE,
+ 0x100, { UQ_AU_INP_ASYNC }},
+ { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B, ANY, { UQ_NO_STRINGS }},
+ /* XXX These should have a revision number, but I don't know what they are. */
+ { USB_VENDOR_HP, USB_PRODUCT_HP_895C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_HP, USB_PRODUCT_HP_880C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_HP, USB_PRODUCT_HP_815C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_HP, USB_PRODUCT_HP_810C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_HP, USB_PRODUCT_HP_830C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_HP, USB_PRODUCT_HP_1220C, ANY, { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15, ANY, { UQ_BROKEN_BIDIR }},
+ /* MS keyboards do weird things */
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK,
+ ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2,
+ ANY, { UQ_MS_BAD_CLASS | UQ_MS_LEADING_BYTE }},
+ { USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE,
+ ANY, { UQ_MS_LEADING_BYTE }},
/* Devices which should be ignored by uhid */
- /* APC Back-UPS Pro 500 */
- { .idVendor = 0x051d, .idProduct = 0x0002, .bcdDevice = ANY,
- .quirks = { UQ_HID_IGNORE }},
- /* Delorme Publishing Earthmate GPS */
- { .idVendor = 0x1163, .idProduct = 0x0100, .bcdDevice = ANY,
- .quirks = { UQ_HID_IGNORE }},
- /* MGE UPS Systems ProtectionCenter */
- { .idVendor = 0x0463, .idProduct = 0x0001, .bcdDevice = ANY,
- .quirks = { UQ_HID_IGNORE }},
- /* MGE UPS Systems ProtectionCenter */
- { .idVendor = 0x0463, .idProduct = 0xffff, .bcdDevice = ANY,
- .quirks = { UQ_HID_IGNORE }},
+ { USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1,
+ ANY, { UQ_HID_IGNORE }},
+ { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,
+ ANY, { UQ_HID_IGNORE }},
+
+ /* Devices which should be ignored by both ukbd and uhid */
+ { USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
+ ANY, { UQ_KBD_IGNORE }},
+ { USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B,
+ ANY, { UQ_KBD_IGNORE }},
+ { USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X,
+ ANY, { UQ_KBD_IGNORE }},
{ 0, 0, 0, { 0 } }
};
@@ -184,7 +135,7 @@
}
#ifdef USB_DEBUG
if (usbdebug && t->quirks.uq_flags)
- kprintf("usbd_find_quirk 0x%04x/0x%04x/%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);
#endif
--- uhci_pci.c 2008-05-19 00:15:48 +0000
+++ /root/src/sys/dev/usb/uhci_pci.c 2008-04-11 05:50:53 +0000
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -33,11 +33,11 @@
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/dev/usb/uhci_pci.c,v 1.57 2005/03/01 07:50:11 imp Exp $
- * $DragonFly: src/sys/bus/usb/uhci_pci.c,v 1.11 2007/06/27 12:27:59 hasso Exp $
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/uhci_pci.c,v 1.64 2008/04/11 05:50:53 benno Exp $");
+
/* Universal Host Controller Interface
*
* UHCI spec: http://www.intel.com/
@@ -54,20 +54,26 @@
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/bus.h>
#include <sys/queue.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
#include <sys/rman.h>
-#include <bus/pci/pcivar.h>
-#include <bus/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
-#include <bus/usb/uhcireg.h>
-#include <bus/usb/uhcivar.h>
+#include <dev/usb/uhcireg.h>
+#include <dev/usb/uhcivar.h>
#define PCI_UHCI_VENDORID_INTEL 0x8086
#define PCI_UHCI_VENDORID_VIA 0x1106
@@ -186,7 +192,7 @@
static device_detach_t uhci_pci_detach;
static device_suspend_t uhci_pci_suspend;
static device_resume_t uhci_pci_resume;
-
+
static int
uhci_pci_suspend(device_t self)
{
@@ -361,16 +367,16 @@
device_set_desc(sc->sc_bus.bdev, uhci_pci_match(self));
switch (pci_get_vendor(self)) {
case PCI_UHCI_VENDORID_INTEL:
- ksprintf(sc->sc_vendor, "Intel");
+ sprintf(sc->sc_vendor, "Intel");
break;
case PCI_UHCI_VENDORID_VIA:
- ksprintf(sc->sc_vendor, "VIA");
+ sprintf(sc->sc_vendor, "VIA");
break;
default:
if (bootverbose)
device_printf(self, "(New UHCI DeviceId=0x%08x)\n",
pci_get_devid(self));
- ksprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
+ sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
}
switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) {
@@ -385,8 +391,8 @@
break;
}
- err = bus_setup_intr(self, sc->irq_res, 0,
- (driver_intr_t *) uhci_intr, sc, &sc->ih, NULL);
+ err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
+ NULL, (driver_intr_t *) uhci_intr, sc, &sc->ih);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->ih = NULL;
@@ -407,10 +413,10 @@
pci_write_config(self, PCI_LEGSUP, PCI_LEGSUP_USBPIRQDEN, 2);
/* Allocate a parent dma tag for DMA maps */
- err = bus_dma_tag_create(/* XXX: bus_get_dma_tag(self)*/NULL, 1, 0,
+ err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.parent_dmatag);
+ NULL, NULL, &sc->sc_bus.parent_dmatag);
if (err) {
device_printf(self, "Could not allocate parent DMA tag (%d)\n",
err);
@@ -421,7 +427,7 @@
err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- &sc->sc_bus.buffer_dmatag);
+ busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag);
if (err) {
device_printf(self, "Could not allocate transfer tag (%d)\n",
err);
--- uhcireg.h 2006-12-10 02:03:56 +0000
+++ /root/src/sys/dev/usb/uhcireg.h 2005-01-06 01:43:28 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: uhcireg.h,v 1.15 2002/02/11 11:41:30 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhcireg.h,v 1.22 2005/01/06 01:43:28 imp Exp $ */
-/* $DragonFly: src/sys/bus/usb/uhcireg.h,v 1.5 2006/12/10 02:03:56 sephe Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
--- uhcivar.h 2008-05-18 22:39:16 +0000
+++ /root/src/sys/dev/usb/uhcivar.h 2007-06-14 16:23:31 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: uhcivar.h,v 1.33 2002/02/11 11:41:30 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.40 2005/03/19 19:08:46 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/uhcivar.h,v 1.9 2007/06/30 20:39:22 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/uhcivar.h,v 1.45 2007/06/14 16:23:31 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -151,7 +150,6 @@
struct resource *io_res;
struct resource *irq_res;
-
uhci_physaddr_t *sc_pframes;
usb_dma_t sc_dma;
struct uhci_vframe sc_vframes[UHCI_VFRAMELIST_COUNT];
@@ -193,12 +191,16 @@
char sc_vendor[16]; /* vendor string for root hub */
int sc_id_vendor; /* vendor ID for root hub */
+
+#if defined(__NetBSD__)
+ void *sc_powerhook; /* cookie from power hook */
+ void *sc_shutdownhook; /* cookie from shutdown hook */
+#endif
} uhci_softc_t;
usbd_status uhci_init(uhci_softc_t *);
int uhci_intr(void *);
int uhci_detach(uhci_softc_t *, int);
-
void uhci_shutdown(void *v);
void uhci_power(int state, void *priv);
--- uhub.c 2008-05-18 22:38:02 +0000
+++ /root/src/sys/dev/usb/uhub.c 2007-06-30 20:18:44 +0000
@@ -1,8 +1,6 @@
/* $NetBSD: uhub.c,v 1.68 2004/06/29 06:30:05 mycroft Exp $ */
-/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.69.2.1 2005/12/18 15:51:31 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/uhub.c,v 1.20 2008/01/25 08:49:47 hasso Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -39,6 +37,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/uhub.c,v 1.82 2007/06/30 20:18:44 imp Exp $");
+
/*
* USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
@@ -50,22 +51,23 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/lock.h>
-#include <sys/thread2.h>
+#include <sys/mutex.h>
#include <sys/sysctl.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdi_util.h>
-#include <bus/usb/usbdivar.h>
+#include <machine/bus.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
#define UHUB_INTR_INTERVAL 255 /* ms */
#ifdef USB_DEBUG
-#define DPRINTF(x) if (uhubdebug) kprintf x
-#define DPRINTFN(n,x) if (uhubdebug > (n)) kprintf x
+#define DPRINTF(x) if (uhubdebug) printf x
+#define DPRINTFN(n,x) if (uhubdebug > (n)) printf x
#define DEVPRINTF(x) if (uhubdebug) device_printf x
#define DEVPRINTFN(n, x)if (uhubdebug > (n)) device_printf x
-
int uhubdebug = 0;
SYSCTL_NODE(_hw_usb, OID_AUTO, uhub, CTLFLAG_RW, 0, "USB uhub");
SYSCTL_INT(_hw_usb_uhub, OID_AUTO, debug, CTLFLAG_RW,
@@ -168,7 +170,7 @@
return (UMATCH_NONE);
}
-static int
+int
uhub_attach(device_t self)
{
struct uhub_softc *sc = device_get_softc(self);
@@ -236,7 +238,7 @@
goto bad;
}
- hub = kmalloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
+ hub = malloc(sizeof(*hub) + (nports-1) * sizeof(struct usbd_port),
M_USBDEV, M_NOWAIT);
if (hub == NULL) {
return (ENXIO);
@@ -314,8 +316,8 @@
*/
if (UHUB_IS_HIGH_SPEED(sc)) {
- tts = kmalloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) *
- sizeof(struct usbd_tt), M_USBDEV, M_NOWAIT);
+ tts = malloc((UHUB_IS_SINGLE_TT(sc) ? 1 : nports) *
+ sizeof (struct usbd_tt), M_USBDEV, M_NOWAIT);
if (!tts)
goto bad;
}
@@ -362,7 +364,7 @@
return (0);
bad:
if (hub)
- kfree(hub, M_USBDEV);
+ free(hub, M_USBDEV);
dev->hub = NULL;
return (ENXIO);
}
@@ -433,7 +435,7 @@
#if 0 && defined(DIAGNOSTIC)
if (up->device == NULL &&
(status & UPS_CURRENT_CONNECT_STATUS))
- device_printf(sc->sc_dev,
+ deivce_printf(sc->sc_dev,
"connected, no device\n");
#endif
continue;
@@ -560,10 +562,8 @@
int port, nports;
DPRINTF(("uhub_detach: sc=%port\n", sc));
-
- if (hub == NULL) { /* Must be partially working */
+ if (hub == NULL) /* Must be partially working */
return (0);
- }
usbd_abort_pipe(sc->sc_ipipe);
usbd_close_pipe(sc->sc_ipipe);
@@ -578,8 +578,8 @@
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, sc->sc_dev);
if (hub->ports[0].tt)
- kfree(hub->ports[0].tt, M_USBDEV);
- kfree(hub, M_USBDEV);
+ free(hub->ports[0].tt, M_USBDEV);
+ free(hub, M_USBDEV);
sc->sc_hub->hub = NULL;
return (0);
@@ -596,7 +596,7 @@
int port;
int i;
- get_mplock();
+ mtx_lock(&Giant);
nports = devhub->hub->hubdesc.bNbrPorts;
for (port = 0; port < nports; port++) {
dev = devhub->hub->ports[port].device;
@@ -604,10 +604,10 @@
for (i = 0; dev->subdevs[i]; i++) {
if (dev->subdevs[i] == child) {
if (dev->ifacenums == NULL) {
- ksnprintf(buf, buflen,
+ snprintf(buf, buflen,
"port=%i", port);
} else {
- ksnprintf(buf, buflen,
+ snprintf(buf, buflen,
"port=%i interface=%i",
port, dev->ifacenums[i]);
}
@@ -619,7 +619,7 @@
DPRINTFN(0,("uhub_child_location_str: device not on hub\n"));
buf[0] = '\0';
found_dev:
- rel_mplock();
+ mtx_unlock(&Giant);
return (0);
}
@@ -636,7 +636,7 @@
int port;
int i;
- get_mplock();
+ mtx_lock(&Giant);
nports = devhub->hub->hubdesc.bNbrPorts;
for (port = 0; port < nports; port++) {
dev = devhub->hub->ports[port].device;
@@ -650,7 +650,7 @@
}
DPRINTFN(0,("uhub_child_pnpinfo_str: device not on hub\n"));
buf[0] = '\0';
- rel_mplock();
+ mtx_unlock(&Giant);
return (0);
found_dev:
@@ -658,7 +658,7 @@
(void)usbd_get_string(dev, dev->ddesc.iSerialNumber, serial,
sizeof(serial));
if (dev->ifacenums == NULL) {
- ksnprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
+ snprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
"devclass=0x%02x devsubclass=0x%02x "
"release=0x%04x sernum=\"%s\"",
UGETW(dev->ddesc.idVendor), UGETW(dev->ddesc.idProduct),
@@ -666,7 +666,7 @@
UGETW(dev->ddesc.bcdDevice), serial);
} else {
iface = &dev->ifaces[dev->ifacenums[i]];
- ksnprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
+ snprintf(buf, buflen, "vendor=0x%04x product=0x%04x "
"devclass=0x%02x devsubclass=0x%02x "
"release=0x%04x sernum=\"%s\" "
"intclass=0x%02x intsubclass=0x%02x",
@@ -676,7 +676,7 @@
iface->idesc->bInterfaceClass,
iface->idesc->bInterfaceSubClass);
}
- rel_mplock();
+ mtx_unlock(&Giant);
return (0);
}
--- usb.c 2008-05-19 11:40:20 +0000
+++ /root/src/sys/dev/usb/usb.c 2007-10-20 23:23:18 +0000
@@ -1,8 +1,4 @@
-/*
- * $NetBSD: usb.c,v 1.68 2002/02/20 20:30:12 christos Exp $
- * $FreeBSD: src/sys/dev/usb/usb.c,v 1.106 2005/03/27 15:31:23 iedowse Exp $
- * $DragonFly: src/sys/bus/usb/usb.c,v 1.41 2008/04/26 23:09:40 sephe Exp $
- */
+/* $NetBSD: usb.c,v 1.68 2002/02/20 20:30:12 christos Exp $ */
/* Also already merged from NetBSD:
* $NetBSD: usb.c,v 1.70 2002/05/09 21:54:32 augustss Exp $
@@ -11,7 +7,10 @@
* $NetBSD: usb.c,v 1.80 2003/11/07 17:03:25 wiz Exp $
*/
-/*
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usb.c,v 1.121 2007/10/20 23:23:18 julian Exp $");
+
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -59,6 +58,7 @@
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
#include <sys/unistd.h>
#include <sys/module.h>
#include <sys/bus.h>
@@ -68,17 +68,15 @@
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/conf.h>
-#include <sys/device.h>
#include <sys/poll.h>
-#include <sys/select.h>
-#include <sys/vnode.h>
+#include <sys/selinfo.h>
#include <sys/signalvar.h>
#include <sys/sysctl.h>
-#include <sys/thread2.h>
+#include <sys/uio.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdi_util.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
#define USBUNIT(d) (minor(d)) /* usb_discover device nodes, kthread */
#define USB_DEV_MINOR 255 /* event queue device */
@@ -89,8 +87,10 @@
#include "usb_if.h"
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_quirks.h>
+#include <machine/bus.h>
+
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_quirks.h>
/* Define this unconditionally in case a kernel module is loaded that
* has been compiled with debugging options.
@@ -98,8 +98,8 @@
SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
int usbdebug = 0;
SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
&usbdebug, 0, "usb debug level");
@@ -116,22 +116,23 @@
struct usb_softc {
device_t sc_dev; /* base device */
- cdev_t sc_usbdev;
+ struct cdev *sc_usbdev; /* /dev/usbN device */
TAILQ_ENTRY(usb_softc) sc_coldexplist; /* cold needs-explore list */
usbd_bus_handle sc_bus; /* USB controller */
struct usbd_port sc_port; /* dummy port for root hub */
- struct thread *sc_event_thread;
+ struct proc *sc_event_thread;
char sc_dying;
};
struct usb_taskq {
- TAILQ_HEAD(, usb_task) tasks;
- struct thread *task_thread_proc;
- const char *name;
- int taskcreated; /* task thread exists. */
+ TAILQ_HEAD(, usb_task) tasks;
+ struct proc *task_thread_proc;
+ const char *name;
+ int taskcreated; /* task thread exists. */
};
+
static struct usb_taskq usb_taskq[USB_NUM_TASKQS];
d_open_t usbopen;
@@ -140,13 +141,15 @@
d_ioctl_t usbioctl;
d_poll_t usbpoll;
-struct dev_ops usb_ops = {
- { "usb", USB_CDEV_MAJOR, 0 },
+struct cdevsw usb_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = D_NEEDGIANT,
.d_open = usbopen,
.d_close = usbclose,
.d_read = usbread,
.d_ioctl = usbioctl,
.d_poll = usbpoll,
+ .d_name = "usb",
};
static void usb_discover(void *);
@@ -154,7 +157,7 @@
static void usb_event_thread(void *);
static void usb_task_thread(void *);
-static cdev_t usb_dev; /* The /dev/usb device. */
+static struct cdev *usb_dev; /* The /dev/usb device. */
static int usb_ndevs; /* Number of /dev/usbN devices. */
/* Busses to explore at the end of boot-time device configuration. */
static TAILQ_HEAD(, usb_softc) usb_coldexplist =
@@ -223,7 +226,6 @@
{
struct usb_softc *sc = device_get_softc(self);
void *aux = device_get_ivars(self);
- cdev_t tmp_dev;
usbd_device_handle dev;
usbd_status err;
int usbrev;
@@ -239,9 +241,9 @@
sc->sc_bus->usbctl = sc;
sc->sc_port.power = USB_MAX_POWER;
- kprintf("%s", device_get_nameunit(sc->sc_dev));
+ printf("%s", device_get_nameunit(sc->sc_dev));
usbrev = sc->sc_bus->usbrev;
- kprintf(": USB revision %s", usbrev_str[usbrev]);
+ printf(": USB revision %s", usbrev_str[usbrev]);
switch (usbrev) {
case USBREV_1_0:
case USBREV_1_1:
@@ -251,11 +253,11 @@
speed = USB_SPEED_HIGH;
break;
default:
- kprintf(", not supported\n");
+ printf(", not supported\n");
sc->sc_dying = 1;
return ENXIO;
}
- kprintf("\n");
+ printf("\n");
/* Make sure not to use tsleep() if we are cold booting. */
if (cold)
@@ -270,7 +272,7 @@
sc->sc_bus->soft = softintr_establish(IPL_SOFTNET,
sc->sc_bus->methods->soft_intr, sc->sc_bus);
if (sc->sc_bus->soft == NULL) {
- kprintf("%s: can't register softintr\n", device_get_nameunit(sc->sc_dev));
+ printf("%s: can't register softintr\n", device_get_nameunit(sc->sc_dev));
sc->sc_dying = 1;
return ENXIO;
}
@@ -285,7 +287,7 @@
dev = sc->sc_port.device;
if (dev->hub == NULL) {
sc->sc_dying = 1;
- kprintf("%s: root device is not a hub\n",
+ printf("%s: root device is not a hub\n",
device_get_nameunit(sc->sc_dev));
return ENXIO;
}
@@ -306,7 +308,7 @@
}
#endif
} else {
- kprintf("%s: root hub problem, error=%d\n",
+ printf("%s: root hub problem, error=%d\n",
device_get_nameunit(sc->sc_dev), err);
sc->sc_dying = 1;
}
@@ -317,19 +319,13 @@
usb_create_event_thread(sc);
/* The per controller devices (used for usb_discover) */
/* XXX This is redundant now, but old usbd's will want it */
- dev_ops_add(&usb_ops, -1, device_get_unit(self));
- tmp_dev = make_dev(&usb_ops, device_get_unit(self),
- UID_ROOT, GID_OPERATOR, 0660,
- "usb%d", device_get_unit(self));
- sc->sc_usbdev = reference_dev(tmp_dev);
+ sc->sc_usbdev = make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT,
+ GID_OPERATOR, 0660, "usb%d", device_get_unit(self));
if (usb_ndevs++ == 0) {
/* The device spitting out events */
- dev_ops_add(&usb_ops, -1, USB_DEV_MINOR);
- tmp_dev = make_dev(&usb_ops, USB_DEV_MINOR,
- UID_ROOT, GID_OPERATOR, 0660, "usb");
- usb_dev = reference_dev(tmp_dev);
+ usb_dev = make_dev(&usb_cdevsw, USB_DEV_MINOR, UID_ROOT,
+ GID_OPERATOR, 0660, "usb");
}
-
return 0;
}
@@ -342,13 +338,12 @@
struct usb_taskq *taskq;
int i;
- if (kthread_create(usb_event_thread, sc, &sc->sc_event_thread,
- "%s", device_get_nameunit(sc->sc_dev))) {
- kprintf("%s: unable to create event thread for\n",
+ if (kproc_create(usb_event_thread, sc, &sc->sc_event_thread,
+ RFHIGHPID, 0, device_get_nameunit(sc->sc_dev))) {
+ printf("%s: unable to create event thread for\n",
device_get_nameunit(sc->sc_dev));
panic("usb_create_event_thread");
}
-
for (i = 0; i < USB_NUM_TASKQS; i++) {
taskq = &usb_taskq[i];
@@ -356,9 +351,10 @@
taskq->taskcreated = 1;
taskq->name = taskq_names[i];
TAILQ_INIT(&taskq->tasks);
- if (kthread_create(usb_task_thread, taskq,
- &taskq->task_thread_proc, taskq->name)) {
- kprintf("unable to create task thread\n");
+ if (kproc_create(usb_task_thread, taskq,
+ &taskq->task_thread_proc, RFHIGHPID, 0,
+ taskq->name)) {
+ printf("unable to create task thread\n");
panic("usb_create_event_thread task");
}
}
@@ -374,9 +370,9 @@
usb_add_task(usbd_device_handle dev, struct usb_task *task, int queue)
{
struct usb_taskq *taskq;
+ int s;
- crit_enter();
-
+ s = splusb();
taskq = &usb_taskq[queue];
if (task->queue == -1) {
DPRINTFN(2,("usb_add_task: task=%p\n", task));
@@ -386,22 +382,22 @@
DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
}
wakeup(&taskq->tasks);
-
- crit_exit();
+ splx(s);
}
void
usb_rem_task(usbd_device_handle dev, struct usb_task *task)
{
struct usb_taskq *taskq;
+ int s;
- crit_enter();
+ s = splusb();
if (task->queue != -1) {
taskq = &usb_taskq[task->queue];
TAILQ_REMOVE(&taskq->tasks, task, next);
task->queue = -1;
}
- crit_exit();
+ splx(s);
}
void
@@ -410,7 +406,7 @@
static int newthread_wchan;
struct usb_softc *sc = arg;
- get_mplock();
+ mtx_lock(&Giant);
DPRINTF(("usb_event_thread: start\n"));
@@ -428,7 +424,7 @@
*/
wakeup(&newthread_wchan);
for (;;) {
- if (tsleep(&newthread_wchan , 0, "usbets", hz * 4) != 0)
+ if (tsleep(&newthread_wchan , PWAIT, "usbets", hz * 4) != 0)
break;
}
@@ -443,10 +439,10 @@
#endif
usb_discover(sc);
#ifdef USB_DEBUG
- (void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
+ (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
usb_noexplore ? 0 : hz * 60);
#else
- (void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
+ (void)tsleep(&sc->sc_bus->needs_explore, PWAIT, "usbevt",
hz * 60);
#endif
DPRINTFN(2,("usb_event_thread: woke up\n"));
@@ -457,7 +453,7 @@
wakeup(sc);
DPRINTF(("usb_event_thread: exit\n"));
- kthread_exit();
+ kproc_exit(0);
}
void
@@ -465,42 +461,41 @@
{
struct usb_task *task;
struct usb_taskq *taskq;
+ int s;
- get_mplock();
+ mtx_lock(&Giant);
taskq = arg;
DPRINTF(("usb_task_thread: start taskq %s\n", taskq->name));
- crit_enter();
+ s = splusb();
while (usb_ndevs > 0) {
task = TAILQ_FIRST(&taskq->tasks);
if (task == NULL) {
- tsleep(&taskq->tasks, 0, "usbtsk", 0);
+ tsleep(&taskq->tasks, PWAIT, "usbtsk", 0);
task = TAILQ_FIRST(&taskq->tasks);
}
DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
if (task != NULL) {
TAILQ_REMOVE(&taskq->tasks, task, next);
task->queue = -1;
- crit_exit();
+ splx(s);
task->fun(task->arg);
- crit_enter();
+ s = splusb();
}
}
-
- crit_exit();
+ splx(s);
taskq->taskcreated = 0;
wakeup(&taskq->taskcreated);
DPRINTF(("usb_event_thread: exit\n"));
- kthread_exit();
+ kproc_exit(0);
}
int
-usbopen(struct dev_open_args *ap)
+usbopen(struct cdev *dev, int flag, int mode, struct thread *p)
{
- cdev_t dev = ap->a_head.a_dev;
int unit = USBUNIT(dev);
struct usb_softc *sc;
@@ -508,14 +503,12 @@
if (usb_dev_open)
return (EBUSY);
usb_dev_open = 1;
- usb_async_proc = NULL;
+ usb_async_proc = 0;
return (0);
}
-
sc = devclass_get_softc(usb_devclass, unit);
if (sc == NULL)
return (ENXIO);
-
if (sc->sc_dying)
return (EIO);
@@ -523,13 +516,11 @@
}
int
-usbread(struct dev_read_args *ap)
+usbread(struct cdev *dev, struct uio *uio, int flag)
{
- cdev_t dev = ap->a_head.a_dev;
- struct uio *uio = ap->a_uio;
struct usb_event ue;
int unit = USBUNIT(dev);
- int error, n;
+ int s, error, n;
if (unit != USB_DEV_MINOR)
return (ENODEV);
@@ -538,20 +529,20 @@
return (EINVAL);
error = 0;
- crit_enter();
+ s = splusb();
for (;;) {
n = usb_get_next_event(&ue);
if (n != 0)
break;
- if (ap->a_ioflag & IO_NDELAY) {
+ if (flag & O_NONBLOCK) {
error = EWOULDBLOCK;
break;
}
- error = tsleep(&usb_events, PCATCH, "usbrea", 0);
+ error = tsleep(&usb_events, PZERO | PCATCH, "usbrea", 0);
if (error)
break;
}
- crit_exit();
+ splx(s);
if (!error)
error = uiomove((void *)&ue, uio->uio_resid, uio);
@@ -559,13 +550,12 @@
}
int
-usbclose(struct dev_close_args *ap)
+usbclose(struct cdev *dev, int flag, int mode, struct thread *p)
{
- cdev_t dev = ap->a_head.a_dev;
int unit = USBUNIT(dev);
if (unit == USB_DEV_MINOR) {
- usb_async_proc = NULL;
+ usb_async_proc = 0;
usb_dev_open = 0;
}
@@ -573,42 +563,39 @@
}
int
-usbioctl(struct dev_ioctl_args *ap)
+usbioctl(struct cdev *devt, u_long cmd, caddr_t data, int flag, struct thread *p)
{
- cdev_t devt = ap->a_head.a_dev;
struct usb_softc *sc;
int unit = USBUNIT(devt);
if (unit == USB_DEV_MINOR) {
- switch (ap->a_cmd) {
+ switch (cmd) {
case FIONBIO:
- /* XXX: True for DragonFly? */
/* All handled in the upper FS layer. */
return (0);
+
case FIOASYNC:
- if (*(int *)ap->a_data)
- usb_async_proc = curproc;
+ if (*(int *)data)
+ usb_async_proc = p->td_proc;
else
- usb_async_proc = NULL;
+ usb_async_proc = 0;
return (0);
default:
return (EINVAL);
}
}
-
sc = devclass_get_softc(usb_devclass, unit);
-
if (sc->sc_dying)
return (EIO);
- switch (ap->a_cmd) {
+ switch (cmd) {
/* This part should be deleted */
case USB_DISCOVER:
break;
case USB_REQUEST:
{
- struct usb_ctl_request *ur = (void *)ap->a_data;
+ struct usb_ctl_request *ur = (void *)data;
int len = UGETW(ur->ucr_request.wLength);
struct iovec iov;
struct uio uio;
@@ -634,8 +621,8 @@
uio.uio_rw =
ur->ucr_request.bmRequestType & UT_READ ?
UIO_READ : UIO_WRITE;
- uio.uio_td = curthread;
- ptr = kmalloc(len, M_TEMP, M_WAITOK);
+ uio.uio_td = p;
+ ptr = malloc(len, M_TEMP, M_WAITOK);
if (uio.uio_rw == UIO_WRITE) {
error = uiomove(ptr, len, &uio);
if (error)
@@ -658,13 +645,13 @@
}
ret:
if (ptr)
- kfree(ptr, M_TEMP);
+ free(ptr, M_TEMP);
return (error);
}
case USB_DEVICEINFO:
{
- struct usb_device_info *di = (void *)ap->a_data;
+ struct usb_device_info *di = (void *)data;
int addr = di->udi_addr;
usbd_device_handle dev;
@@ -678,7 +665,7 @@
}
case USB_DEVICESTATS:
- *(struct usb_device_stats *)ap->a_data = sc->sc_bus->stats;
+ *(struct usb_device_stats *)data = sc->sc_bus->stats;
break;
default:
@@ -688,26 +675,24 @@
}
int
-usbpoll(struct dev_poll_args *ap)
+usbpoll(struct cdev *dev, int events, struct thread *p)
{
- cdev_t dev = ap->a_head.a_dev;
- int revents, mask;
+ int revents, mask, s;
int unit = USBUNIT(dev);
if (unit == USB_DEV_MINOR) {
revents = 0;
mask = POLLIN | POLLRDNORM;
- crit_enter();
- if ((ap->a_events & mask) && usb_nevents > 0)
- revents |= ap->a_events & mask;
- if (revents == 0 && ap->a_events & mask)
- selrecord(curthread, &usb_selevent);
- crit_exit();
- ap->a_events = revents;
- return (0);
+ s = splusb();
+ if (events & mask && usb_nevents > 0)
+ revents |= events & mask;
+ if (revents == 0 && events & mask)
+ selrecord(p, &usb_selevent);
+ splx(s);
+
+ return (revents);
} else {
- ap->a_events = 0;
return (0); /* select/poll never wakes up - back compat */
}
}
@@ -718,6 +703,9 @@
{
struct usb_softc *sc = v;
+ /* splxxx should be changed to mutexes for preemption safety some day */
+ int s;
+
DPRINTFN(2,("usb_discover\n"));
#ifdef USB_DEBUG
if (usb_noexplore > 1)
@@ -729,15 +717,14 @@
* but this is guaranteed since this function is only called
* from the event thread for the controller.
*/
- crit_enter();
+ s = splusb();
while (sc->sc_bus->needs_explore && !sc->sc_dying) {
sc->sc_bus->needs_explore = 0;
-
- crit_exit();
+ splx(s);
sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
- crit_enter();
+ s = splusb();
}
- crit_exit();
+ splx(s);
}
void
@@ -748,7 +735,7 @@
wakeup(&dev->bus->needs_explore);
}
-/* Called from a critical section */
+/* Called at splusb() */
int
usb_get_next_event(struct usb_event *ue)
{
@@ -759,14 +746,14 @@
ueq = TAILQ_FIRST(&usb_events);
#ifdef DIAGNOSTIC
if (ueq == NULL) {
- kprintf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
+ printf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
usb_nevents = 0;
return (0);
}
#endif
*ue = ueq->ue;
TAILQ_REMOVE(&usb_events, ueq, next);
- kfree(ueq, M_USBDEV);
+ free(ueq, M_USBDEV);
usb_nevents--;
return (1);
}
@@ -787,7 +774,7 @@
ue.u.ue_driver.ue_cookie = udev->cookie;
strncpy(ue.u.ue_driver.ue_devname, device_get_nameunit(dev),
- sizeof ue.u.ue_driver.ue_devname);
+ sizeof ue.u.ue_driver.ue_devname);
usb_add_event(type, &ue);
}
@@ -797,14 +784,15 @@
struct usb_event_q *ueq;
struct usb_event ue;
struct timeval thetime;
+ int s;
- ueq = kmalloc(sizeof *ueq, M_USBDEV, M_WAITOK);
+ ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
ueq->ue = *uep;
ueq->ue.ue_type = type;
microtime(&thetime);
TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
- crit_enter();
+ s = splusb();
if (USB_EVENT_IS_DETACH(type)) {
struct usb_event_q *ueqi, *ueqi_next;
@@ -813,7 +801,7 @@
if (ueqi->ue.u.ue_driver.ue_cookie.cookie ==
uep->u.ue_device.udi_cookie.cookie) {
TAILQ_REMOVE(&usb_events, ueqi, next);
- kfree(ueqi, M_USBDEV);
+ free(ueqi, M_USBDEV);
usb_nevents--;
ueqi_next = TAILQ_FIRST(&usb_events);
}
@@ -827,11 +815,13 @@
TAILQ_INSERT_TAIL(&usb_events, ueq, next);
usb_nevents++;
wakeup(&usb_events);
- selwakeup(&usb_selevent);
+ selwakeuppri(&usb_selevent, PZERO);
if (usb_async_proc != NULL) {
- ksignal(usb_async_proc, SIGIO);
+ PROC_LOCK(usb_async_proc);
+ psignal(usb_async_proc, SIGIO);
+ PROC_UNLOCK(usb_async_proc);
}
- crit_exit();
+ splx(s);
}
void
@@ -874,8 +864,8 @@
/* Kill off event thread. */
if (sc->sc_event_thread != NULL) {
wakeup(&sc->sc_bus->needs_explore);
- if (tsleep(sc, 0, "usbdet", hz * 60))
- kprintf("%s: event thread didn't die\n",
+ if (tsleep(sc, PWAIT, "usbdet", hz * 60))
+ printf("%s: event thread didn't die\n",
device_get_nameunit(sc->sc_dev));
DPRINTF(("usb_detach: event thread dead\n"));
}
@@ -884,13 +874,12 @@
if (--usb_ndevs == 0) {
destroy_dev(usb_dev);
usb_dev = NULL;
-
for (i = 0; i < USB_NUM_TASKQS; i++) {
taskq = &usb_taskq[i];
wakeup(&taskq->tasks);
- if (tsleep(&taskq->taskcreated, 0, "usbtdt",
+ if (tsleep(&taskq->taskcreated, PWAIT, "usbtdt",
hz * 60)) {
- kprintf("usb task thread %s didn't die\n",
+ printf("usb task thread %s didn't die\n",
taskq->name);
}
}
--- usb_mem.c 2008-05-19 01:22:20 +0000
+++ /root/src/sys/dev/usb/usb_mem.c 2007-06-20 05:10:53 +0000
@@ -1,9 +1,7 @@
-/*
- * $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $
- * $FreeBSD: src/sys/dev/usb/usb_mem.c,v 1.5 2003/10/04 22:13:21 joe Exp $
- * $DragonFly: src/sys/bus/usb/usb_mem.c,v 1.12 2007/06/28 13:55:12 hasso Exp $
- */
-/*
+/* $NetBSD: usb_mem.c,v 1.26 2003/02/01 06:23:40 thorpej Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usb_mem.c,v 1.13 2007/06/20 05:10:53 imp Exp $ */
+
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -46,6 +44,10 @@
* memory blocks that can be used for DMA. Using the bus_dma
* routines directly would incur large overheads in space and time.
*/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usb_mem.c,v 1.13 2007/06/20 05:10:53 imp Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -54,42 +56,22 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/queue.h>
-#include <sys/sysctl.h>
-#include <sys/ktr.h>
+#include <machine/bus.h>
#include <machine/endian.h>
#ifdef DIAGNOSTIC
#include <sys/proc.h>
#endif
-#include <sys/thread2.h>
-
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdivar.h> /* just for usb_dma_t */
-#include <bus/usb/usb_mem.h>
-
-#define USBKTR_STRING "ptr=%p bus=%p size=%d align=%d"
-#define USBKTR_ARG_SIZE (sizeof(void *) * 2 + sizeof(int) * 2)
-
-#if !defined(KTR_USB_MEMORY)
-#define KTR_USB_MEMORY KTR_ALL
-#endif
-KTR_INFO_MASTER(usbmem);
-KTR_INFO(KTR_USB_MEMORY, usbmem, alloc_full, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, alloc_frag, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, free_full, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, free_frag, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, blkalloc, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, blkalloc2, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-KTR_INFO(KTR_USB_MEMORY, usbmem, blkfree, 0, USBKTR_STRING, USBKTR_ARG_SIZE);
-#define logmemory(name, ptr, bus, size, align) \
- KTR_LOG(usbmem_ ## name, ptr, bus, (int)size, (int)align);
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h> /* just for usb_dma_t */
+#include <dev/usb/usb_mem.h>
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
#else
#define DPRINTF(x)
@@ -126,7 +108,7 @@
usb_dma_block_t *p = arg;
if (error == EFBIG) {
- kprintf("usb: mapping to large\n");
+ printf("usb: mapping to large\n");
return;
}
@@ -140,37 +122,50 @@
usb_dma_block_t **dmap)
{
usb_dma_block_t *p;
+ int s;
DPRINTFN(5, ("usb_block_allocmem: size=%lu align=%lu\n",
(u_long)size, (u_long)align));
- crit_enter();
+#ifdef DIAGNOSTIC
+ if (!curproc) {
+ printf("usb_block_allocmem: in interrupt context, size=%lu\n",
+ (unsigned long) size);
+ }
+#endif
+
+ s = splusb();
/* First check the free list. */
for (p = LIST_FIRST(&usb_blk_freelist); p; p = LIST_NEXT(p, next)) {
if (p->tag == tag && p->size >= size && p->size < size * 2 &&
- align >= align) {
+ p->align >= align) {
LIST_REMOVE(p, next);
usb_blk_nfree--;
- crit_exit();
+ splx(s);
*dmap = p;
DPRINTFN(6,("usb_block_allocmem: free list size=%lu\n",
(u_long)p->size));
- logmemory(blkalloc2, p, NULL, size, align);
return (USBD_NORMAL_COMPLETION);
}
}
- crit_exit();
+ splx(s);
+
+#ifdef DIAGNOSTIC
+ if (!curproc) {
+ printf("usb_block_allocmem: in interrupt context, failed\n");
+ return (USBD_NOMEM);
+ }
+#endif
DPRINTFN(6, ("usb_block_allocmem: no free\n"));
- p = kmalloc(sizeof *p, M_USB, M_NOWAIT);
- logmemory(blkalloc, p, NULL, size, align);
+ p = malloc(sizeof *p, M_USB, M_NOWAIT);
if (p == NULL)
return (USBD_NOMEM);
if (bus_dma_tag_create(tag, align, 0,
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
size, sizeof(p->segs) / sizeof(p->segs[0]), size,
- BUS_DMA_ALLOCNOW, &p->tag) == ENOMEM)
+ 0, NULL, NULL, &p->tag) == ENOMEM)
{
goto free;
}
@@ -199,7 +194,7 @@
tagfree:
bus_dma_tag_destroy(p->tag);
free:
- kfree(p, M_USB);
+ free(p, M_USB);
return (USBD_NOMEM);
}
@@ -211,12 +206,13 @@
static void
usb_block_freemem(usb_dma_block_t *p)
{
+ int s;
+
DPRINTFN(6, ("usb_block_freemem: size=%lu\n", (u_long)p->size));
- logmemory(blkfree, p, NULL, p->size, p->align);
- crit_enter();
+ s = splusb();
LIST_INSERT_HEAD(&usb_blk_freelist, p, next);
usb_blk_nfree++;
- crit_exit();
+ splx(s);
}
usbd_status
@@ -227,6 +223,7 @@
struct usb_frag_dma *f;
usb_dma_block_t *b;
int i;
+ int s;
/* compat w/ Net/OpenBSD */
if (align == 0)
@@ -241,12 +238,11 @@
p->block->fullblock = 1;
p->offs = 0;
p->len = size;
- logmemory(alloc_full, p, NULL, size, align);
}
return (err);
}
- crit_enter();
+ s = splusb();
/* Check for free fragments. */
for (f = LIST_FIRST(&usb_frag_freelist); f; f = LIST_NEXT(f, next))
if (f->block->tag == tag)
@@ -255,7 +251,7 @@
DPRINTFN(1, ("usb_allocmem: adding fragments\n"));
err = usb_block_allocmem(tag, USB_MEM_BLOCK, USB_MEM_SMALL,&b);
if (err) {
- crit_exit();
+ splx(s);
return (err);
}
b->fullblock = 0;
@@ -275,8 +271,7 @@
p->offs = f->offs;
p->len = USB_MEM_SMALL;
LIST_REMOVE(f, next);
- crit_exit();
- logmemory(alloc_frag, p, NULL, size, align);
+ splx(s);
DPRINTFN(5, ("usb_allocmem: use frag=%p size=%d\n", f, (int)size));
return (USBD_NORMAL_COMPLETION);
}
@@ -285,19 +280,18 @@
usb_freemem(usbd_bus_handle bus, usb_dma_t *p)
{
struct usb_frag_dma *f;
+ int s;
if (p->block->fullblock) {
DPRINTFN(1, ("usb_freemem: large free\n"));
usb_block_freemem(p->block);
- logmemory(free_full, p, bus, 0, 0);
return;
}
- logmemory(free_frag, p, bus, 0, 0);
f = KERNADDR(p, 0);
f->block = p->block;
f->offs = p->offs;
- crit_enter();
+ s = splusb();
LIST_INSERT_HEAD(&usb_frag_freelist, f, next);
- crit_exit();
+ splx(s);
DPRINTFN(5, ("usb_freemem: frag=%p\n", f));
}
--- usb_mem.h 2007-06-27 12:27:59 +0000
+++ /root/src/sys/dev/usb/usb_mem.h 2007-06-13 05:45:48 +0000
@@ -1,10 +1,7 @@
-/*
- * $NetBSD: usb_mem.h,v 1.18 2002/05/28 17:45:17 augustss Exp $
- * $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.20 2003/09/01 01:07:24 jmg Exp $
- * $DragonFly: src/sys/bus/usb/usb_mem.h,v 1.5 2007/06/27 12:27:59 hasso Exp $
- */
+/* $NetBSD: usb_mem.h,v 1.18 2002/05/28 17:45:17 augustss Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usb_mem.h,v 1.22 2007/06/13 05:45:48 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
--- usb_port.h 2007-11-05 19:09:42 +0000
+++ /root/src/sys/dev/usb/usb_port.h 2007-10-20 23:23:18 +0000
@@ -1,16 +1,13 @@
-/*
- * $OpenBSD: usb_port.h,v 1.18 2000/09/06 22:42:10 rahnds Exp $
- * $NetBSD: usb_port.h,v 1.68 2005/07/30 06:14:50 skrll Exp $
- * $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.65 2003/11/09 23:54:21 joe Exp $
- * $DragonFly: src/sys/bus/usb/usb_port.h,v 1.21 2007/11/05 19:09:42 hasso Exp $
- */
+/* $OpenBSD: usb_port.h,v 1.18 2000/09/06 22:42:10 rahnds Exp $ */
+/* $NetBSD: usb_port.h,v 1.54 2002/03/28 21:49:19 ichiro Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usb_port.h,v 1.99 2007/10/20 23:23:18 julian Exp $ */
/* Also already merged from NetBSD:
* $NetBSD: usb_port.h,v 1.57 2002/09/27 20:42:01 thorpej Exp $
* $NetBSD: usb_port.h,v 1.58 2002/10/01 01:25:26 thorpej Exp $
*/
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -51,13 +48,17 @@
#define _USB_PORT_H
/*
- * Macros to ease the import of USB drivers from other BSD systems. Drivers
- * in the DragonFly tree don't use any of these macros.
- *
- * Driver that wants to use these can simply include <bus/usb/usb_port.h>.
+ * Macro's to cope with the differences between operating systems.
*/
-#include "opt_usb.h"
+/*
+ * FreeBSD
+ */
+
+/* We don't use the soft interrupt code in FreeBSD. */
+#if 0
+#define USB_USE_SOFTINTR
+#endif
#define Static static
@@ -65,8 +66,8 @@
#define USBBASEDEVICE device_t
#define USBDEV(bdev) (bdev)
#define USBDEVNAME(bdev) device_get_nameunit(bdev)
-#define USBDEVUNIT(bdev) device_get_unit(bdev)
#define USBDEVPTRNAME(bdev) device_get_nameunit(bdev)
+#define USBDEVUNIT(bdev) device_get_unit(bdev)
#define USBGETSOFTC(bdev) (device_get_softc(bdev))
#define DECLARE_USB_DMA_T \
@@ -77,44 +78,45 @@
u_int len; \
} usb_dma_t
-#define PROC_LOCK(p)
-#define PROC_UNLOCK(p)
-#define uio_procp uio_td
+typedef struct thread *usb_proc_ptr;
-#define selwakeuppri(p, pri) selwakeup(p)
+#define uio_procp uio_td
-typedef struct thread *usb_proc_ptr;
+#define usb_kthread_create1(f, s, p, a0, a1) \
+ kproc_create((f), (s), (p), RFHIGHPID, 0, (a0), (a1))
+#define usb_kthread_create2(f, s, p, a0) \
+ kproc_create((f), (s), (p), RFHIGHPID, 0, (a0))
+#define usb_kthread_create kproc_create
#define config_pending_incr()
#define config_pending_decr()
-#define usb_kthread_create(f, s) \
- kthread_create(f, s, NULL, "dummy")
-#define usb_kthread_create1(f, s, p, name, arg) \
- kthread_create(f, s, p, name, arg)
-#define usb_kthread_create2(f, s, p, name) \
- kthread_create(f, s, p, name)
-
typedef struct callout usb_callout_t;
-#define usb_callout_init(h) callout_init(&(h))
+#define usb_callout_init(h) callout_init(&(h), 0)
#define usb_callout(h, t, f, d) callout_reset(&(h), (t), (f), (d))
#define usb_uncallout(h, f, d) callout_stop(&(h))
+#define usb_uncallout_drain(h, f, d) callout_drain(&(h))
#define clalloc(p, s, x) (clist_alloc_cblocks((p), (s), (s)), 0)
#define clfree(p) clist_free_cblocks((p))
-#define config_detach(dev, flag) device_delete_child(device_get_parent(dev), dev)
+#define config_detach(dev, flag) \
+ do { \
+ device_detach(dev); \
+ free(device_get_ivars(dev), M_USB); \
+ device_delete_child(device_get_parent(dev), dev); \
+ } while (0);
typedef struct malloc_type *usb_malloc_type;
#define USB_DECLARE_DRIVER_INIT(dname, init...) \
-Static device_probe_t __CONCAT(dname,_match); \
-Static device_attach_t __CONCAT(dname,_attach); \
-Static device_detach_t __CONCAT(dname,_detach); \
+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 devclass_t __CONCAT(dname,_devclass); \
\
-Static device_method_t __CONCAT(dname,_methods)[] = { \
+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)), \
@@ -122,7 +124,7 @@
{0,0} \
}; \
\
-Static driver_t __CONCAT(dname,_driver) = { \
+static driver_t __CONCAT(dname,_driver) = { \
#dname, \
__CONCAT(dname,_methods), \
sizeof(struct __CONCAT(dname,_softc)) \
@@ -134,7 +136,7 @@
#define USB_DECLARE_DRIVER(dname) USB_DECLARE_DRIVER_INIT(dname, METHODS_NONE)
#define USB_MATCH(dname) \
-Static int \
+static int \
__CONCAT(dname,_match)(device_t self)
#define USB_MATCH_START(dname, uaa) \
@@ -144,7 +146,7 @@
sc->sc_dev = self
#define USB_ATTACH(dname) \
-Static int \
+static int \
__CONCAT(dname,_attach)(device_t self)
#define USB_ATTACH_START(dname, sc, uaa) \
@@ -152,15 +154,14 @@
struct usb_attach_arg *uaa = device_get_ivars(self)
/* Returns from attach */
-#define USB_ATTACH_ERROR_RETURN return ENXIO
+#define USB_ATTACH_ERROR_RETURN return ENXIO
#define USB_ATTACH_SUCCESS_RETURN return 0
#define USB_ATTACH_SETUP \
sc->sc_dev = self; \
- device_set_desc_copy(self, devinfo)
#define USB_DETACH(dname) \
-Static int \
+static int \
__CONCAT(dname,_detach)(device_t self)
#define USB_DETACH_START(dname, sc) \
@@ -190,7 +191,10 @@
#define SIMPLEQ_HEAD_INITIALIZER STAILQ_HEAD_INITIALIZER
#define SIMPLEQ_ENTRY STAILQ_ENTRY
-#define logprintf kprintf
+#include <sys/syslog.h>
+/*
+#define logprintf(args...) log(LOG_DEBUG, args)
+*/
+#define logprintf printf
#endif /* _USB_PORT_H */
-
--- usb_quirks.h 2008-05-18 21:02:46 +0000
+++ /root/src/sys/dev/usb/usb_quirks.h 2008-05-18 21:28:21 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: usb_quirks.h,v 1.20 2001/04/15 09:38:01 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.17.2.3 2006/02/15 22:51:08 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/usb_quirks.h,v 1.4 2006/12/10 02:03:56 sephe Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.25 2007/06/29 21:07:41 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -41,7 +40,6 @@
struct usbd_quirks {
u_int32_t uq_flags; /* Device problems: */
-#define UQ_NO_SET_PROTO 0x00000001 /* cannot handle SET PROTOCOL. */
#define UQ_SWAP_UNICODE 0x00000002 /* has some Unicode strings swapped. */
#define UQ_MS_REVZ 0x00000004 /* mouse has Z-axis reversed */
#define UQ_NO_STRINGS 0x00000008 /* string descriptors are broken. */
@@ -53,7 +51,6 @@
#define UQ_POWER_CLAIM 0x00000200 /* hub lies about power status */
#define UQ_AU_NO_FRAC 0x00000400 /* don't adjust for fractional samples */
#define UQ_AU_INP_ASYNC 0x00000800 /* input is async despite claim of adaptive */
-#define UQ_ASSUME_CM_OVER_DATA 0x1000 /* modem device breaks on cm over data */
#define UQ_BROKEN_BIDIR 0x00002000 /* printer has broken bidir mode */
#define UQ_OPEN_CLEARSTALL 0x04000 /* device needs clear endpoint stall */
#define UQ_HID_IGNORE 0x00008000 /* device should be ignored by hid class */
--- usb_subr.c 2008-05-18 21:34:04 +0000
+++ /root/src/sys/dev/usb/usb_subr.c 2007-06-30 20:18:44 +0000
@@ -1,6 +1,4 @@
/* $NetBSD: usb_subr.c,v 1.99 2002/07/11 21:14:34 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.76.2.3 2006/03/01 01:59:05 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/usb_subr.c,v 1.27 2008/01/11 11:41:50 hasso Exp $ */
/* Also already have from NetBSD:
* $NetBSD: usb_subr.c,v 1.102 2003/01/01 16:21:50 augustss Exp $
@@ -12,7 +10,10 @@
* $NetBSD: usb_subr.c,v 1.119 2004/10/23 13:26:33 augustss Exp $
*/
-/*
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.95 2007/06/30 20:18:44 imp Exp $");
+
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -58,19 +59,23 @@
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/proc.h>
+#include <sys/sysctl.h>
-#include <bus/usb/usb.h>
+#include <machine/bus.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdi_util.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_quirks.h>
+#include <dev/usb/usb.h>
+
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
+#include "usbdevs.h"
+#include <dev/usb/usb_quirks.h>
#define delay(d) DELAY(d)
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
#else
#define DPRINTF(x)
@@ -87,6 +92,24 @@
static u_int32_t usb_cookie_no = 0;
+#ifdef USBVERBOSE
+typedef u_int16_t usb_vendor_id_t;
+typedef u_int16_t usb_product_id_t;
+
+/*
+ * Descriptions of of known vendors and devices ("products").
+ */
+struct usb_knowndev {
+ usb_vendor_id_t vendor;
+ usb_product_id_t product;
+ int flags;
+ char *vendorname, *productname;
+};
+#define USB_KNOWNDEV_NOPROD 0x01 /* match on vendor only */
+
+#include "usbdevs_data.h"
+#endif /* USBVERBOSE */
+
static const char * const usbd_error_strs[] = {
"NORMAL_COMPLETION",
"IN_PROGRESS",
@@ -118,7 +141,7 @@
if (err < USBD_ERROR_MAX) {
return usbd_error_strs[err];
} else {
- ksnprintf(buffer, sizeof buffer, "%d", err);
+ snprintf(buffer, sizeof buffer, "%d", err);
return buffer;
}
}
@@ -180,6 +203,9 @@
{
usb_device_descriptor_t *udd = &dev->ddesc;
char *vendor = 0, *product = 0;
+#ifdef USBVERBOSE
+ const struct usb_knowndev *kdp;
+#endif
if (dev == NULL) {
v[0] = p[0] = '\0';
@@ -207,21 +233,39 @@
vendor = NULL;
product = NULL;
}
-
+#ifdef USBVERBOSE
+ if (vendor == NULL || product == NULL) {
+ for(kdp = usb_knowndevs;
+ kdp->vendorname != NULL;
+ kdp++) {
+ if (kdp->vendor == UGETW(udd->idVendor) &&
+ (kdp->product == UGETW(udd->idProduct) ||
+ (kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
+ break;
+ }
+ if (kdp->vendorname != NULL) {
+ if (vendor == NULL)
+ vendor = kdp->vendorname;
+ if (product == NULL)
+ product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
+ kdp->productname : NULL;
+ }
+ }
+#endif
if (vendor != NULL && *vendor)
strcpy(v, vendor);
else
- ksprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
+ sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor));
if (product != NULL && *product)
strcpy(p, product);
else
- ksprintf(p, "product 0x%04x", UGETW(udd->idProduct));
+ sprintf(p, "product 0x%04x", UGETW(udd->idProduct));
}
int
usbd_printBCD(char *cp, int bcd)
{
- return (ksprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
+ return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff));
}
void
@@ -235,24 +279,24 @@
usb_interface_descriptor_t *id;
usbd_devinfo_vp(dev, vendor, product, 1);
- cp += ksprintf(cp, "%s %s", vendor, product);
+ cp += sprintf(cp, "%s %s", vendor, product);
if (showclass & USBD_SHOW_DEVICE_CLASS)
- cp += ksprintf(cp, ", class %d/%d",
- udd->bDeviceClass, udd->bDeviceSubClass);
+ cp += sprintf(cp, ", class %d/%d",
+ udd->bDeviceClass, udd->bDeviceSubClass);
bcdUSB = UGETW(udd->bcdUSB);
bcdDevice = UGETW(udd->bcdDevice);
- cp += ksprintf(cp, ", rev ");
+ cp += sprintf(cp, ", rev ");
cp += usbd_printBCD(cp, bcdUSB);
*cp++ = '/';
cp += usbd_printBCD(cp, bcdDevice);
- cp += ksprintf(cp, ", addr %d", dev->address);
+ cp += sprintf(cp, ", addr %d", dev->address);
if (showclass & USBD_SHOW_INTERFACE_CLASS)
{
/* fetch the interface handle for the first interface */
(void)usbd_device2interface_handle(dev, 0, &iface);
id = usbd_get_interface_descriptor(iface);
- cp += ksprintf(cp, ", iclass %d/%d",
- id->bInterfaceClass, id->bInterfaceSubClass);
+ cp += sprintf(cp, ", iclass %d/%d",
+ id->bInterfaceClass, id->bInterfaceSubClass);
}
*cp = 0;
}
@@ -265,7 +309,7 @@
if (bus->use_polling || cold)
delay((ms+1) * 1000);
else
- tsleep(usb_delay_ms, 0, "usbdly", (ms*hz+999)/1000 + 1); /* XXX: port pause */
+ pause("usbdly", (ms*hz+999)/1000 + 1);
}
/* Delay given a device handle. */
@@ -404,13 +448,12 @@
nendpt = ifc->idesc->bNumEndpoints;
DPRINTFN(4,("usbd_fill_iface_data: found idesc nendpt=%d\n", nendpt));
if (nendpt != 0) {
- ifc->endpoints = kmalloc(nendpt * sizeof(struct usbd_endpoint),
+ ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint),
M_USB, M_NOWAIT);
if (ifc->endpoints == NULL)
return (USBD_NOMEM);
- } else {
+ } else
ifc->endpoints = NULL;
- }
ifc->priv = NULL;
p = (char *)ifc->idesc + ifc->idesc->bLength;
end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength);
@@ -429,7 +472,7 @@
break;
}
/* passed end, or bad desc */
- kprintf("usbd_fill_iface_data: bad descriptor(s): %s\n",
+ printf("usbd_fill_iface_data: bad descriptor(s): %s\n",
ed->bLength == 0 ? "0 length" :
ed->bDescriptorType == UDESC_INTERFACE ? "iface desc":
"out of data");
@@ -449,7 +492,7 @@
if (UGETW(ed->wMaxPacketSize) != mps) {
USETW(ed->wMaxPacketSize, mps);
#ifdef DIAGNOSTIC
- kprintf("usbd_fill_iface_data: bad max "
+ printf("usbd_fill_iface_data: bad max "
"packet size\n");
#endif
}
@@ -468,7 +511,7 @@
bad:
if (ifc->endpoints != NULL) {
- kfree(ifc->endpoints, M_USB);
+ free(ifc->endpoints, M_USB);
ifc->endpoints = NULL;
}
return (USBD_INVAL);
@@ -479,7 +522,7 @@
{
usbd_interface_handle ifc = &dev->ifaces[ifcno];
if (ifc->endpoints)
- kfree(ifc->endpoints, M_USB);
+ free(ifc->endpoints, M_USB);
}
static usbd_status
@@ -542,8 +585,8 @@
/* Free all configuration data structures. */
for (ifcidx = 0; ifcidx < nifc; ifcidx++)
usbd_free_iface_data(dev, ifcidx);
- kfree(dev->ifaces, M_USB);
- kfree(dev->cdesc, M_USB);
+ free(dev->ifaces, M_USB);
+ free(dev->cdesc, M_USB);
dev->ifaces = NULL;
dev->cdesc = NULL;
dev->config = USB_UNCONFIG_NO;
@@ -564,9 +607,10 @@
if (err)
return (err);
len = UGETW(cd.wTotalLength);
- cdp = kmalloc(len, M_USB, M_NOWAIT);
+ cdp = malloc(len, M_USB, M_NOWAIT);
if (cdp == NULL)
return (USBD_NOMEM);
+
/* Get the full descriptor. Try a few times for slow devices. */
for (i = 0; i < 3; i++) {
err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
@@ -641,7 +685,7 @@
DPRINTF(("power exceeded %d %d\n", power,dev->powersrc->power));
/* XXX print nicer message. */
if (msg)
- kprintf("%s: device addr %d (config %d) exceeds power "
+ printf("%s: device addr %d (config %d) exceeds power "
"budget, %d mA > %d mA\n",
device_get_nameunit(dev->bus->bdev), dev->address,
cdp->bConfigurationValue,
@@ -665,7 +709,7 @@
/* Allocate and fill interface data. */
nifc = cdp->bNumInterface;
- dev->ifaces = kmalloc(nifc * sizeof(struct usbd_interface),
+ dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
M_USB, M_NOWAIT);
if (dev->ifaces == NULL) {
err = USBD_NOMEM;
@@ -686,7 +730,7 @@
return (USBD_NORMAL_COMPLETION);
bad:
- kfree(cdp, M_USB);
+ free(cdp, M_USB);
return (err);
}
@@ -701,7 +745,7 @@
DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n",
dev, iface, ep, pipe));
- p = kmalloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
+ p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
if (p == NULL)
return (USBD_NOMEM);
p->device = dev;
@@ -720,7 +764,7 @@
DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error="
"%s\n",
ep->edesc->bEndpointAddress, usbd_errstr(err)));
- kfree(p, M_USB);
+ free(p, M_USB);
return (err);
}
@@ -729,7 +773,7 @@
if (UE_GET_ADDR(ep->edesc->bEndpointAddress) != USB_CONTROL_ENDPOINT) {
err = usbd_clear_endpoint_stall(p);
if (err && err != USBD_STALLED && err != USBD_TIMEOUT) {
- kprintf("usbd_setup_pipe: failed to start "
+ printf("usbd_setup_pipe: failed to start "
"endpoint, %s\n", usbd_errstr(err));
return (err);
}
@@ -747,7 +791,7 @@
usbd_abort_pipe(pipe);
pipe->methods->close(pipe);
pipe->endpoint->refcnt--;
- kfree(pipe, M_USB);
+ free(pipe, M_USB);
}
int
@@ -778,20 +822,20 @@
device_t bdev;
struct usb_attach_arg *uaap;
- devinfo = kmalloc(1024, M_USB, M_NOWAIT);
+ devinfo = malloc(1024, M_USB, M_NOWAIT);
if (devinfo == NULL) {
device_printf(parent, "Can't allocate memory for probe string\n");
return (USBD_NOMEM);
}
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
device_printf(parent, "Device creation failed\n");
return (USBD_INVAL);
}
- uaap = kmalloc(sizeof(uaa), M_USB, M_NOWAIT);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
if (uaap == NULL) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_INVAL);
}
device_set_ivars(bdev, uaap);
@@ -812,9 +856,9 @@
DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
dev->ifacenums = NULL;
- dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
+ dev->subdevs = malloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
if (dev->subdevs == NULL) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NOMEM);
}
dev->subdevs[0] = bdev;
@@ -823,7 +867,7 @@
usbd_devinfo(dev, 1, devinfo);
device_set_desc_copy(bdev, devinfo);
if (device_probe_and_attach(bdev) == 0) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NORMAL_COMPLETION);
}
@@ -833,7 +877,7 @@
*/
tmpdv = dev->subdevs;
dev->subdevs = NULL;
- kfree(tmpdv, M_USB);
+ free(tmpdv, M_USB);
DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
@@ -849,10 +893,10 @@
"error=%s\n", device_get_nameunit(parent), port,
addr, usbd_errstr(err)));
#else
- kprintf("%s: port %d, set config at addr %d failed\n",
+ printf("%s: port %d, set config at addr %d failed\n",
device_get_nameunit(parent), port, addr);
#endif
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (err);
}
nifaces = dev->cdesc->bNumInterface;
@@ -861,16 +905,15 @@
ifaces[i] = &dev->ifaces[i];
uaa.ifaces = ifaces;
uaa.nifaces = nifaces;
- dev->subdevs = kmalloc((nifaces+1) * sizeof(device_t),
- M_USB, M_NOWAIT);
+ dev->subdevs = malloc((nifaces+1) * sizeof(device_t), M_USB,M_NOWAIT);
if (dev->subdevs == NULL) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NOMEM);
}
- dev->ifacenums = kmalloc((nifaces) * sizeof(*dev->ifacenums),
- M_USB, M_NOWAIT);
+ dev->ifacenums = malloc((nifaces) * sizeof(*dev->ifacenums),
+ M_USB,M_NOWAIT);
if (dev->ifacenums == NULL) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NOMEM);
}
@@ -889,18 +932,17 @@
if (device_probe_and_attach(bdev) == 0) {
ifaces[i] = 0; /* consumed */
found++;
-
/* create another child for the next iface */
bdev = device_add_child(parent, NULL, -1);
if (!bdev) {
device_printf(parent,
"Device add failed\n");
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NORMAL_COMPLETION);
}
- uaap = kmalloc(sizeof(uaa), M_USB, M_NOWAIT);
+ uaap = malloc(sizeof(uaa), M_USB, M_NOWAIT);
if (uaap == NULL) {
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
return (USBD_NOMEM);
}
device_set_ivars(bdev, uaap);
@@ -910,16 +952,16 @@
}
if (found != 0) {
/* remove the last created child. It is unused */
- kfree(uaap, M_USB);
- kfree(devinfo, M_USB);
+ free(uaap, M_USB);
+ free(devinfo, M_USB);
device_delete_child(parent, bdev);
- /* kfree(uaap, M_USB); */ /* May be needed? xxx */
+ /* free(uaap, M_USB); */ /* May be needed? xxx */
return (USBD_NORMAL_COMPLETION);
}
tmpdv = dev->subdevs;
dev->subdevs = NULL;
- kfree(tmpdv, M_USB);
- kfree(dev->ifacenums, M_USB);
+ free(tmpdv, M_USB);
+ free(dev->ifacenums, M_USB);
dev->ifacenums = NULL;
}
/* No interfaces were attached in any of the configurations. */
@@ -934,9 +976,9 @@
uaa.usegeneric = 1;
uaa.configno = UHUB_UNK_CONFIGURATION;
uaa.ifaceno = UHUB_UNK_INTERFACE;
- dev->subdevs = kmalloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
- if (dev->subdevs == NULL) {
- kfree(devinfo, M_USB);
+ dev->subdevs = malloc(2 * sizeof(device_t), M_USB, M_NOWAIT);
+ if (dev->subdevs == 0) {
+ free(devinfo, M_USB);
return (USBD_NOMEM);
}
dev->subdevs[0] = bdev;
@@ -944,7 +986,7 @@
*uaap = uaa;
usbd_devinfo(dev, 1, devinfo);
device_set_desc_copy(bdev, devinfo);
- kfree(devinfo, M_USB);
+ free(devinfo, M_USB);
if (device_probe_and_attach(bdev) == 0)
return (USBD_NORMAL_COMPLETION);
@@ -981,15 +1023,15 @@
bus, port, depth, speed));
addr = usbd_getnewaddr(bus);
if (addr < 0) {
- kprintf("%s: No free USB addresses, new device ignored.\n",
+ printf("%s: No free USB addresses, new device ignored.\n",
device_get_nameunit(bus->bdev));
return (USBD_NO_ADDR);
}
- dev = kmalloc(sizeof *dev, M_USB, M_NOWAIT | M_ZERO);
+ dev = malloc(sizeof *dev, M_USB, M_NOWAIT|M_ZERO);
if (dev == NULL)
return (USBD_NOMEM);
-
+
dev->bus = bus;
/* Set up default endpoint handle. */
@@ -1014,7 +1056,7 @@
if (up->parent && speed > up->parent->speed) {
#ifdef USB_DEBUG
- kprintf("%s: maxium speed of attached "
+ printf("%s: maxium speed of attached "
"device, %d, is higher than speed "
"of parent HUB, %d.\n",
__FUNCTION__, speed, up->parent->speed);
@@ -1025,7 +1067,7 @@
*/
speed = up->parent->speed;
}
-
+
/* Locate port on upstream high speed hub */
for (adev = dev, hub = up->parent;
hub != NULL && hub->speed != USB_SPEED_HIGH;
@@ -1070,8 +1112,8 @@
"failed - trying a port reset\n", addr));
usbd_reset_port(up->parent, port, &ps);
}
- }
+ }
if (err) {
DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc "
"failed\n", addr));
@@ -1083,7 +1125,7 @@
/* Max packet size must be 64 (sec 5.5.3). */
if (dd->bMaxPacketSize != USB_2_MAX_CTRL_PACKET) {
#ifdef DIAGNOSTIC
- kprintf("usbd_new_device: addr=%d bad max packet size\n",
+ printf("usbd_new_device: addr=%d bad max packet size\n",
addr);
#endif
dd->bMaxPacketSize = USB_2_MAX_CTRL_PACKET;
@@ -1203,7 +1245,7 @@
up->device = NULL;
dev->bus->devices[dev->address] = NULL;
- kfree(dev, M_USB);
+ free(dev, M_USB);
}
void
@@ -1280,15 +1322,15 @@
nifc = dev->cdesc->bNumInterface;
for (ifcidx = 0; ifcidx < nifc; ifcidx++)
usbd_free_iface_data(dev, ifcidx);
- kfree(dev->ifaces, M_USB);
+ free(dev->ifaces, M_USB);
}
if (dev->cdesc != NULL)
- kfree(dev->cdesc, M_USB);
+ free(dev->cdesc, M_USB);
if (dev->subdevs != NULL)
- kfree(dev->subdevs, M_USB);
+ free(dev->subdevs, M_USB);
if (dev->ifacenums != NULL)
- kfree(dev->ifacenums, M_USB);
- kfree(dev, M_USB);
+ free(dev->ifacenums, M_USB);
+ free(dev, M_USB);
}
/*
@@ -1320,7 +1362,7 @@
#ifdef DIAGNOSTIC
if (dev == NULL) {
- kprintf("usb_disconnect_port: no device\n");
+ printf("usb_disconnect_port: no device\n");
return;
}
#endif
@@ -1328,15 +1370,15 @@
if (dev->subdevs != NULL) {
DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
for (i = 0; dev->subdevs[i]; i++) {
- kprintf("%s: at %s", device_get_nameunit(dev->subdevs[i]),
+ printf("%s: at %s", device_get_nameunit(dev->subdevs[i]),
hubname);
if (up->portno != 0)
- kprintf(" port %d", up->portno);
- kprintf(" (addr %d) disconnected\n", dev->address);
+ printf(" port %d", up->portno);
+ printf(" (addr %d) disconnected\n", dev->address);
struct usb_attach_arg *uaap =
device_get_ivars(dev->subdevs[i]);
device_detach(dev->subdevs[i]);
- kfree(uaap, M_USB);
+ free(uaap, M_USB);
device_delete_child(device_get_parent(dev->subdevs[i]),
dev->subdevs[i]);
dev->subdevs[i] = NULL;
@@ -1348,4 +1390,3 @@
up->device = NULL;
usb_free_device(dev);
}
-
--- usbcdc.h 2008-05-18 21:31:07 +0000
+++ /root/src/sys/dev/usb/usbcdc.h 2005-03-01 06:35:04 +0000
@@ -1,10 +1,7 @@
-/*
- * $NetBSD: usbcdc.h,v 1.6 2000/04/27 15:26:50 augustss Exp $
- * $FreeBSD: src/sys/dev/usb/usbcdc.h,v 1.10 2003/01/09 04:24:28 imp Exp $
- * $DragonFly: src/sys/bus/usb/usbcdc.h,v 1.3 2003/12/30 01:01:44 dillon Exp $
- */
+/* $NetBSD: usbcdc.h,v 1.9 2004/10/23 13:24:24 augustss Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usbcdc.h,v 1.12 2005/03/01 06:35:04 sobomax Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -108,7 +105,7 @@
uWord wNumberMCFikters;
uByte bNumberPowerFilters;
} UPACKED usb_cdc_ethernet_descriptor_t;
-
+
#define UCDC_SEND_ENCAPSULATED_COMMAND 0x00
#define UCDC_GET_ENCAPSULATED_RESPONSE 0x01
#define UCDC_SET_COMM_FEATURE 0x02
--- usbdi.c 2008-05-18 22:22:00 +0000
+++ /root/src/sys/dev/usb/usbdi.c 2008-03-20 16:04:13 +0000
@@ -1,8 +1,9 @@
/* $NetBSD: usbdi.c,v 1.106 2004/10/24 12:52:40 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.91.2.1 2005/12/15 00:36:00 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/usbdi.c,v 1.18 2007/06/29 22:56:31 hasso Exp $ */
-/*
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usbdi.c,v 1.106 2008/03/20 16:04:13 sam Exp $");
+
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -49,20 +50,22 @@
#endif
#include <sys/malloc.h>
#include <sys/proc.h>
-#include <sys/thread2.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdi_util.h>
-#include <bus/usb/usbdivar.h>
-#include <bus/usb/usb_mem.h>
-#include <bus/usb/usb_quirks.h>
+#include <machine/bus.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usb_quirks.h>
+
+#include "usb_if.h"
#define delay(d) DELAY(d)
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
#else
#define DPRINTF(x)
@@ -80,7 +83,7 @@
int error);
static void usbd_alloc_callback(void *arg, bus_dma_segment_t *segs, int nseg,
int error);
-
+
static int usbd_nbuses = 0;
void
@@ -109,10 +112,10 @@
void
usbd_dump_iface(struct usbd_interface *iface)
{
- kprintf("usbd_dump_iface: iface=%p\n", iface);
+ printf("usbd_dump_iface: iface=%p\n", iface);
if (iface == NULL)
return;
- kprintf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n",
+ printf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n",
iface->device, iface->idesc, iface->index, iface->altindex,
iface->priv);
}
@@ -120,11 +123,11 @@
void
usbd_dump_device(struct usbd_device *dev)
{
- kprintf("usbd_dump_device: dev=%p\n", dev);
+ printf("usbd_dump_device: dev=%p\n", dev);
if (dev == NULL)
return;
- kprintf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe);
- kprintf(" address=%d config=%d depth=%d speed=%d self_powered=%d "
+ printf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe);
+ printf(" address=%d config=%d depth=%d speed=%d self_powered=%d "
"power=%d langid=%d\n",
dev->address, dev->config, dev->depth, dev->speed,
dev->self_powered, dev->power, dev->langid);
@@ -133,12 +136,12 @@
void
usbd_dump_endpoint(struct usbd_endpoint *endp)
{
- kprintf("usbd_dump_endpoint: endp=%p\n", endp);
+ printf("usbd_dump_endpoint: endp=%p\n", endp);
if (endp == NULL)
return;
- kprintf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt);
+ printf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt);
if (endp->edesc)
- kprintf(" bEndpointAddress=0x%02x\n",
+ printf(" bEndpointAddress=0x%02x\n",
endp->edesc->bEndpointAddress);
}
@@ -147,24 +150,24 @@
{
usbd_xfer_handle xfer;
- kprintf("usbd_dump_queue: pipe=%p\n", pipe);
+ printf("usbd_dump_queue: pipe=%p\n", pipe);
STAILQ_FOREACH(xfer, &pipe->queue, next) {
- kprintf(" xfer=%p\n", xfer);
+ printf(" xfer=%p\n", xfer);
}
}
void
usbd_dump_pipe(usbd_pipe_handle pipe)
{
- kprintf("usbd_dump_pipe: pipe=%p\n", pipe);
+ printf("usbd_dump_pipe: pipe=%p\n", pipe);
if (pipe == NULL)
return;
usbd_dump_iface(pipe->iface);
usbd_dump_device(pipe->device);
usbd_dump_endpoint(pipe->endpoint);
- kprintf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n",
+ printf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n",
pipe->refcnt, pipe->running, pipe->aborting);
- kprintf(" intrxfer=%p, repeat=%d, interval=%d\n",
+ printf(" intrxfer=%p, repeat=%d, interval=%d\n",
pipe->intrxfer, pipe->repeat, pipe->interval);
}
#endif
@@ -254,7 +257,7 @@
{
#ifdef DIAGNOSTIC
if (pipe == NULL) {
- kprintf("usbd_close_pipe: pipe==NULL\n");
+ printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
#endif
@@ -268,7 +271,7 @@
pipe->methods->close(pipe);
if (pipe->intrxfer != NULL)
usbd_free_xfer(pipe->intrxfer);
- kfree(pipe, M_USB);
+ free(pipe, M_USB);
return (USBD_NORMAL_COMPLETION);
}
@@ -279,12 +282,12 @@
struct usb_dma_mapping *dmap = &xfer->dmamap;
usbd_status err;
u_int size;
+ int s;
DPRINTFN(5,("%s: xfer=%p, flags=0x%b, rqflags=0x%b, "
"length=%d, buffer=%p, allocbuf=%p, pipe=%p, running=%d\n",
__func__, xfer, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS,
xfer->length, xfer->buffer, xfer->allocbuf, pipe, pipe->running));
-
#ifdef USB_DEBUG
if (usbdebug > 5)
usbd_dump_queue(pipe);
@@ -301,7 +304,7 @@
#ifdef DIAGNOSTIC
if (xfer->rqflags & URQ_AUTO_DMABUF)
- kprintf("usbd_transfer: has old buffer!\n");
+ printf("usbd_transfer: has old buffer!\n");
#endif
err = bus_dmamap_create(tag, 0, &dmap->map);
if (err)
@@ -325,13 +328,13 @@
return (xfer->done ? 0 : USBD_IN_PROGRESS);
/* Sync transfer, wait for completion. */
- crit_enter();
+ s = splusb();
while (!xfer->done) {
if (pipe->device->bus->use_polling)
panic("usbd_transfer: not done");
- tsleep(xfer, 0, "usbsyn", 0);
+ tsleep(xfer, PRIBIO, "usbsyn", 0);
}
- crit_exit();
+ splx(s);
return (xfer->status);
}
@@ -422,14 +425,14 @@
bus_dma_tag_t tag = xfer->device->bus->buffer_dmatag;
void *buf;
usbd_status err;
- int error;
+ int error, s;
KASSERT((xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) == 0,
("usbd_alloc_buffer: xfer already has a buffer"));
err = bus_dmamap_create(tag, 0, &dmap->map);
if (err)
return (NULL);
- buf = kmalloc(size, M_USB, M_WAITOK);
+ buf = malloc(size, M_USB, M_WAITOK);
allocstate.xfer = xfer;
allocstate.done = 0;
@@ -439,22 +442,22 @@
&allocstate, 0);
if (error && error != EINPROGRESS) {
bus_dmamap_destroy(tag, dmap->map);
- kfree(buf, M_USB);
+ free(buf, M_USB);
return (NULL);
}
if (error == EINPROGRESS) {
/* Wait for completion. */
- crit_enter();
+ s = splusb();
allocstate.waiting = 1;
while (!allocstate.done)
- tsleep(&allocstate, 0, "usbdab", 0);
- crit_exit();
+ tsleep(&allocstate, PRIBIO, "usbdab", 0);
+ splx(s);
error = allocstate.error;
}
if (error) {
bus_dmamap_unload(tag, dmap->map);
bus_dmamap_destroy(tag, dmap->map);
- kfree(buf, M_USB);
+ free(buf, M_USB);
return (NULL);
}
@@ -475,7 +478,7 @@
xfer->rqflags &= ~URQ_DEV_DMABUF;
bus_dmamap_unload(tag, dmap->map);
bus_dmamap_destroy(tag, dmap->map);
- kfree(xfer->allocbuf, M_USB);
+ free(xfer->allocbuf, M_USB);
xfer->allocbuf = NULL;
}
@@ -505,7 +508,7 @@
if (allocstate->waiting)
wakeup(&allocstate);
}
-
+
usbd_xfer_handle
usbd_alloc_xfer(usbd_device_handle dev)
{
@@ -515,7 +518,7 @@
if (xfer == NULL)
return (NULL);
xfer->device = dev;
- callout_init(&xfer->timeout_handle);
+ callout_init(&xfer->timeout_handle, 0);
DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer));
return (xfer);
}
@@ -530,7 +533,7 @@
#if defined(__NetBSD__) && defined(DIAGNOSTIC)
if (callout_pending(&xfer->timeout_handle)) {
callout_stop(&xfer->timeout_handle);
- kprintf("usbd_free_xfer: timout_handle pending");
+ printf("usbd_free_xfer: timout_handle pending");
}
#endif
xfer->device->bus->methods->freex(xfer->device->bus, xfer);
@@ -619,13 +622,14 @@
{
#ifdef DIAGNOSTIC
if (dev == NULL) {
- kprintf("usbd_get_config_descriptor: dev == NULL\n");
+ printf("usbd_get_config_descriptor: dev == NULL\n");
return (NULL);
}
#endif
return (dev->cdesc);
}
+int
usbd_get_speed(usbd_device_handle dev)
{
return (dev->speed);
@@ -636,7 +640,7 @@
{
#ifdef DIAGNOSTIC
if (iface == NULL) {
- kprintf("usbd_get_interface_descriptor: dev == NULL\n");
+ printf("usbd_get_interface_descriptor: dev == NULL\n");
return (NULL);
}
#endif
@@ -661,16 +665,17 @@
usbd_abort_pipe(usbd_pipe_handle pipe)
{
usbd_status err;
+ int s;
#ifdef DIAGNOSTIC
if (pipe == NULL) {
- kprintf("usbd_close_pipe: pipe==NULL\n");
+ printf("usbd_close_pipe: pipe==NULL\n");
return (USBD_NORMAL_COMPLETION);
}
#endif
- crit_enter();
+ s = splusb();
err = usbd_ar_pipe(pipe);
- crit_exit();
+ splx(s);
return (err);
}
@@ -740,7 +745,7 @@
{
#ifdef DIAGNOSTIC
if (iface == NULL || iface->idesc == NULL) {
- kprintf("usbd_endpoint_count: NULL pointer\n");
+ printf("usbd_endpoint_count: NULL pointer\n");
return (USBD_INVAL);
}
#endif
@@ -800,11 +805,11 @@
/* new setting works, we can free old endpoints */
if (endpoints != NULL)
- kfree(endpoints, M_USB);
+ free(endpoints, M_USB);
#ifdef DIAGNOSTIC
if (iface->idesc == NULL) {
- kprintf("usbd_set_interface: NULL pointer\n");
+ printf("usbd_set_interface: NULL pointer\n");
return (USBD_INVAL);
}
#endif
@@ -856,12 +861,14 @@
/*** Internal routines ***/
-/* Dequeue all pipe operations, called from critical section. */
+/* Dequeue all pipe operations, called at splusb(). */
static usbd_status
usbd_ar_pipe(usbd_pipe_handle pipe)
{
usbd_xfer_handle xfer;
+ SPLUSBCHECK;
+
DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
#ifdef USB_DEBUG
if (usbdebug > 5)
@@ -881,7 +888,7 @@
return (USBD_NORMAL_COMPLETION);
}
-/* Called from critical section */
+/* Called at splusb() */
void
usb_transfer_complete(usbd_xfer_handle xfer)
{
@@ -894,15 +901,16 @@
int repeat = pipe->repeat;
int polling;
+ SPLUSBCHECK;
+
DPRINTFN(5, ("%s: pipe=%p xfer=%p status=%d actlen=%d\n",
__func__, pipe, xfer, xfer->status, xfer->actlen));
DPRINTFN(5,("%s: flags=0x%b, rqflags=0x%b, length=%d, buffer=%p\n",
__func__, xfer->flags, USBD_BITS, xfer->rqflags, URQ_BITS,
xfer->length, xfer->buffer));
-
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_ONQU) {
- kprintf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
+ printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
xfer, xfer->busy_free);
return;
}
@@ -910,7 +918,7 @@
#ifdef DIAGNOSTIC
if (pipe == NULL) {
- kprintf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
+ printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
return;
}
#endif
@@ -993,18 +1001,19 @@
{
usbd_pipe_handle pipe = xfer->pipe;
usbd_status err;
+ int s;
DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
pipe, pipe->running, xfer->timeout));
#ifdef DIAGNOSTIC
if (xfer->busy_free != XFER_BUSY) {
- kprintf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
+ printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
xfer, xfer->busy_free);
return (USBD_INVAL);
}
xfer->busy_free = XFER_ONQU;
#endif
- crit_enter();
+ s = splusb();
KASSERT(STAILQ_FIRST(&pipe->queue) != xfer, ("usb_insert_transfer"));
STAILQ_INSERT_TAIL(&pipe->queue, xfer, next);
if (pipe->running)
@@ -1013,24 +1022,26 @@
pipe->running = 1;
err = USBD_NORMAL_COMPLETION;
}
- crit_exit();
+ splx(s);
return (err);
}
-/* Called from critical section */
+/* Called at splusb() */
void
usbd_start_next(usbd_pipe_handle pipe)
{
usbd_xfer_handle xfer;
usbd_status err;
+ SPLUSBCHECK;
+
#ifdef DIAGNOSTIC
if (pipe == NULL) {
- kprintf("usbd_start_next: pipe == NULL\n");
+ printf("usbd_start_next: pipe == NULL\n");
return;
}
if (pipe->methods == NULL || pipe->methods->start == NULL) {
- kprintf("usbd_start_next: pipe=%p no start method\n", pipe);
+ printf("usbd_start_next: pipe=%p no start method\n", pipe);
return;
}
#endif
@@ -1043,7 +1054,7 @@
} else {
err = pipe->methods->start(xfer);
if (err != USBD_IN_PROGRESS) {
- kprintf("usbd_start_next: error=%d\n", err);
+ printf("usbd_start_next: error=%d\n", err);
pipe->running = 0;
/* XXX do what? */
}
@@ -1074,10 +1085,13 @@
usbd_status err;
#ifdef DIAGNOSTIC
- KASSERT(mycpu->gd_intr_nesting_level == 0,
- ("usbd_do_request: in interrupt context"));
+/* XXX amd64 too? */
+#if defined(__i386__)
+ KASSERT(curthread->td_intr_nesting_level == 0,
+ ("usbd_do_request: in interrupt context"));
+#endif
if (dev->bus->intr_context) {
- kprintf("usbd_do_request: not in process context\n");
+ printf("usbd_do_request: not in process context\n");
return (USBD_INVAL);
}
#endif
@@ -1191,7 +1205,7 @@
{
#ifdef DIAGNOSTIC
if (dev == NULL) {
- kprintf("usbd_get_quirks: dev == NULL\n");
+ printf("usbd_get_quirks: dev == NULL\n");
return 0;
}
#endif
@@ -1286,17 +1300,17 @@
if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
if (iter->cur != iter->end)
- kprintf("usb_desc_iter_next: bad descriptor\n");
+ printf("usb_desc_iter_next: bad descriptor\n");
return NULL;
}
desc = (const usb_descriptor_t *)iter->cur;
if (desc->bLength == 0) {
- kprintf("usb_desc_iter_next: descriptor length = 0\n");
+ printf("usb_desc_iter_next: descriptor length = 0\n");
return NULL;
}
iter->cur += desc->bLength;
if (iter->cur > iter->end) {
- kprintf("usb_desc_iter_next: descriptor length too large\n");
+ printf("usb_desc_iter_next: descriptor length too large\n");
return NULL;
}
return desc;
@@ -1358,4 +1372,3 @@
return (0);
}
-
--- usbdi.h 2008-05-18 21:55:33 +0000
+++ /root/src/sys/dev/usb/usbdi.h 2008-03-20 03:09:59 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: usbdi.h,v 1.64 2004/10/23 13:26:34 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.59 2005/05/16 06:58:43 imp Exp $ */
-/* $DragonFly: src/sys/bus/usb/usbdi.h,v 1.10 2007/11/05 13:32:27 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usbdi.h,v 1.64 2008/03/20 03:09:59 sam Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -94,8 +93,6 @@
#define USBD_NO_TIMEOUT 0
#define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */
-#define USB_CDEV_MAJOR 108
-
usbd_status usbd_open_pipe(usbd_interface_handle, u_int8_t,
u_int8_t, usbd_pipe_handle *);
usbd_status usbd_close_pipe(usbd_pipe_handle);
@@ -179,7 +176,7 @@
int usbd_ratecheck(struct timeval *last);
usbd_status usbd_get_string(usbd_device_handle dev, int si, char *buf,
- size_t len);
+ size_t len);
/* An iterator for descriptors. */
typedef struct {
@@ -214,8 +211,6 @@
u_int16_t ud_vendor;
u_int16_t ud_product;
};
-#define USB_DEVICE(vid, pid) \
- .ud_vendor = (vid), .ud_product = (pid)
const struct usb_devno *usb_match_device(const struct usb_devno *,
u_int, u_int, u_int16_t, u_int16_t);
#define usb_lookup(tbl, vendor, product) \
@@ -262,20 +257,31 @@
int usbd_driver_load(module_t mod, int what, void *arg);
-static __inline int
+static inline int
usb_get_port(device_t dev)
{
struct usb_attach_arg *uap = device_get_ivars(dev);
return (uap->port);
}
-static __inline struct usbd_interface *
+static inline struct usbd_interface *
usb_get_iface(device_t dev)
{
struct usb_attach_arg *uap = device_get_ivars(dev);
return (uap->iface);
}
+/* XXX Perhaps USB should have its own levels? */
+#ifdef USB_USE_SOFTINTR
+#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
+#define splusb splsoftnet
+#else
+#define splusb splsoftclock
+#endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
+#else
+#define splusb splbio
+#endif /* USB_USE_SOFTINTR */
+#define splhardusb splbio
#define IPL_USB IPL_BIO
#endif /* _USBDI_H_ */
--- usbdi_util.c 2008-05-18 21:53:59 +0000
+++ /root/src/sys/dev/usb/usbdi_util.c 2007-06-20 05:10:54 +0000
@@ -1,8 +1,6 @@
/* $NetBSD: usbdi_util.c,v 1.42 2004/12/03 08:53:40 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.34 2005/03/01 08:01:22 sobomax Exp $ */
-/* $DragonFly: src/sys/bus/usb/usbdi_util.c,v 1.16 2007/08/02 16:19:17 hasso Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -39,23 +37,25 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: src/sys/dev/usb/usbdi_util.c,v 1.38 2007/06/20 05:10:54 imp Exp $");
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/malloc.h>
#include <sys/bus.h>
-#include <sys/thread2.h>
-#include <bus/usb/usb.h>
-#include <bus/usb/usbhid.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbhid.h>
-#include <bus/usb/usbdi.h>
-#include <bus/usb/usbdi_util.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
#ifdef USB_DEBUG
-#define DPRINTF(x) if (usbdebug) kprintf x
-#define DPRINTFN(n,x) if (usbdebug>(n)) kprintf x
+#define DPRINTF(x) if (usbdebug) printf x
+#define DPRINTFN(n,x) if (usbdebug>(n)) printf x
extern int usbdebug;
#else
#define DPRINTF(x)
@@ -394,13 +394,13 @@
if (hid == NULL)
return (USBD_IOERROR);
*sizep = UGETW(hid->descrs[0].wDescriptorLength);
- *descp = kmalloc(*sizep, mem, M_NOWAIT);
+ *descp = malloc(*sizep, mem, M_NOWAIT);
if (*descp == NULL)
return (USBD_NOMEM);
err = usbd_get_report_descriptor(dev, id->bInterfaceNumber,
*sizep, *descp);
if (err) {
- kfree(*descp, mem);
+ free(*descp, mem);
*descp = NULL;
return (err);
}
@@ -435,19 +435,19 @@
u_int32_t *size, char *lbl)
{
usbd_status err;
- int error;
+ int s, error;
usbd_setup_xfer(xfer, pipe, 0, buf, *size,
flags, timeout, usbd_bulk_transfer_cb);
DPRINTFN(1, ("usbd_bulk_transfer: start transfer %d bytes\n", *size));
- crit_enter();
+ s = splusb(); /* don't want callback until tsleep() */
err = usbd_transfer(xfer);
if (err != USBD_IN_PROGRESS) {
- crit_exit();
+ splx(s);
return (err);
}
- error = tsleep((caddr_t)xfer, PCATCH, lbl, 0);
- crit_exit();
+ error = tsleep((caddr_t)xfer, PZERO | PCATCH, lbl, 0);
+ splx(s);
if (error) {
DPRINTF(("usbd_bulk_transfer: tsleep=%d\n", error));
usbd_abort_pipe(pipe);
@@ -477,19 +477,19 @@
u_int32_t *size, char *lbl)
{
usbd_status err;
- int error;
+ int s, error;
usbd_setup_xfer(xfer, pipe, 0, buf, *size,
flags, timeout, usbd_intr_transfer_cb);
DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
- crit_enter(); /* don't want callback until tsleep() */
+ s = splusb(); /* don't want callback until tsleep() */
err = usbd_transfer(xfer);
if (err != USBD_IN_PROGRESS) {
- crit_exit();
+ splx(s);
return (err);
}
- error = tsleep(xfer, PCATCH, lbl, 0);
- crit_exit();
+ error = tsleep(xfer, PZERO | PCATCH, lbl, 0);
+ splx(s);
if (error) {
DPRINTF(("usbd_intr_transfer: tsleep=%d\n", error));
usbd_abort_pipe(pipe);
@@ -508,8 +508,8 @@
usb_detach_wait(device_t dv)
{
DPRINTF(("usb_detach_wait: waiting for %s\n", device_get_nameunit(dv)));
- if (tsleep(dv, 0, "usbdet", hz * 60))
- kprintf("usb_detach_wait: %s didn't detach\n",
+ if (tsleep(dv, PZERO, "usbdet", hz * 60))
+ printf("usb_detach_wait: %s didn't detach\n",
device_get_nameunit(dv));
DPRINTF(("usb_detach_wait: %s done\n", device_get_nameunit(dv)));
}
@@ -537,30 +537,3 @@
}
return desc;
}
-
-/* same as usb_find_desc(), but searches only in the specified interface. */
-const usb_descriptor_t *
-usb_find_desc_if(usbd_device_handle dev, int type, int subtype,
- usb_interface_descriptor_t *id)
-{
- usbd_desc_iter_t iter;
- const usb_descriptor_t *desc;
-
- usb_desc_iter_init(dev, &iter);
-
- iter.cur = (void *)id; /* start from the interface desc */
- usb_desc_iter_next(&iter); /* and skip it */
-
- while ((desc = usb_desc_iter_next(&iter)) != NULL) {
- if (desc->bDescriptorType == UDESC_INTERFACE) {
- /* we ran into the next interface --- not found */
- return NULL;
- }
- if (desc->bDescriptorType == type &&
- (subtype == USBD_SUBTYPE_ANY ||
- subtype == desc->bDescriptorSubtype))
- break;
- }
- return desc;
-}
-
--- usbdi_util.h 2008-05-18 21:51:12 +0000
+++ /root/src/sys/dev/usb/usbdi_util.h 2007-01-03 10:50:03 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: usbdi_util.h,v 1.31 2004/12/03 08:53:40 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.19 2005/03/01 08:01:22 sobomax Exp $ */
-/* $DragonFly: src/sys/bus/usb/usbdi_util.h,v 1.7 2007/08/02 16:19:17 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usbdi_util.h,v 1.21 2007/01/03 10:50:03 luigi Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -41,7 +40,6 @@
#ifndef _USBI_UTIL_H_
#define _USBI_UTIL_H_
-
usbd_status usbd_get_desc(usbd_device_handle dev, int type,
int index, int len, void *desc);
usbd_status usbd_get_config_desc(usbd_device_handle, int,
@@ -74,7 +72,7 @@
int *sizep, struct malloc_type *mem);
usbd_status usbd_get_config(usbd_device_handle dev, u_int8_t *conf);
usbd_status usbd_get_string_desc(usbd_device_handle dev, int sindex,
- int langid, usb_string_descriptor_t *sdesc,
+ int langid,usb_string_descriptor_t *sdesc,
int *sizep);
void usbd_delay_ms(usbd_device_handle, u_int);
@@ -95,9 +93,6 @@
const usb_descriptor_t *usb_find_desc(usbd_device_handle dev, int type,
int subtype);
-const usb_descriptor_t *usb_find_desc_if(usbd_device_handle dev, int type,
- int subtype,
- usb_interface_descriptor_t *id);
#define USBD_SUBTYPE_ANY (~0)
#endif /* _USBI_UTIL_H_ */
--- usbdivar.h 2008-05-18 21:49:04 +0000
+++ /root/src/sys/dev/usb/usbdivar.h 2008-03-20 03:09:59 +0000
@@ -1,8 +1,7 @@
/* $NetBSD: usbdivar.h,v 1.70 2002/07/11 21:14:36 augustss Exp $ */
-/* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.43.2.1 2006/03/01 01:59:05 iedowse Exp $ */
-/* $DragonFly: src/sys/bus/usb/usbdivar.h,v 1.11 2007/07/03 19:28:16 hasso Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.51 2008/03/20 03:09:59 sam Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -228,7 +227,7 @@
struct usbd_device *device;
struct usb_dma_mapping dmamap;
void *allocbuf;
-
+
int rqflags;
#define URQ_REQUEST 0x01
#define URQ_AUTO_DMABUF 0x10
@@ -280,6 +279,20 @@
void usb_needs_explore(usbd_device_handle);
void usb_schedsoftintr(struct usbd_bus *);
+/*
+ * XXX This check is extremely bogus. Bad Bad Bad.
+ */
+#if defined(DIAGNOSTIC) && 0
+#define SPLUSBCHECK \
+ do { int _s = splusb(), _su = splusb(); \
+ if (!cold && _s != _su) printf("SPLUSBCHECK failed 0x%x!=0x%x, %s:%d\n", \
+ _s, _su, __FILE__, __LINE__); \
+ splx(_s); \
+ } while (0)
+#else
+#define SPLUSBCHECK
+#endif
+
/* Locator stuff. */
/* XXX these values are used to statically bind some elements in the USB tree
--- usbhid.h 2008-05-18 21:44:11 +0000
+++ /root/src/sys/dev/usb/usbhid.h 2005-01-06 01:43:29 +0000
@@ -1,10 +1,7 @@
-/*
- * $NetBSD: usbhid.h,v 1.9 2000/09/03 19:09:14 augustss Exp $
- * $FreeBSD: src/sys/dev/usb/usbhid.h,v 1.13 2002/01/02 20:16:53 joe Exp $
- * $DragonFly: src/sys/bus/usb/usbhid.h,v 1.4 2007/12/30 20:02:56 hasso Exp $
- */
+/* $NetBSD: usbhid.h,v 1.9 2000/09/03 19:09:14 augustss Exp $ */
+/* $FreeBSD: src/sys/dev/usb/usbhid.h,v 1.15 2005/01/06 01:43:29 imp Exp $ */
-/*
+/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
More information about the Submit
mailing list