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