diff -rup dev/usb-1/ehci.c dev/usb/ehci.c --- dev/usb-1/ehci.c Fri Feb 25 15:31:11 2005 +++ dev/usb/ehci.c Fri Feb 25 15:31:55 2005 @@ -267,6 +267,7 @@ Static void ehci_dump_exfer(struct ehci Static struct usbd_bus_methods ehci_bus_methods = { ehci_open, ehci_softintr, + ehci_intr, ehci_poll, ehci_allocm, ehci_freem, diff -rup dev/usb-1/ohci.c dev/usb/ohci.c --- dev/usb-1/ohci.c Fri Feb 25 15:31:11 2005 +++ dev/usb/ohci.c Fri Feb 25 15:31:55 2005 @@ -279,6 +279,7 @@ struct ohci_pipe { Static struct usbd_bus_methods ohci_bus_methods = { ohci_open, ohci_softintr, + ohci_intr, ohci_poll, ohci_allocm, ohci_freem, diff -rup dev/usb-1/uhci.c dev/usb/uhci.c --- dev/usb-1/uhci.c Fri Feb 25 15:31:11 2005 +++ dev/usb/uhci.c Fri Feb 25 15:31:55 2005 @@ -297,6 +297,7 @@ void uhci_dump(void); struct usbd_bus_methods uhci_bus_methods = { uhci_open, uhci_softintr, + uhci_intr, uhci_poll, uhci_allocm, uhci_freem, diff -rup dev/usb-1/usb.c dev/usb/usb.c --- dev/usb-1/usb.c Sun Dec 12 15:17:40 2004 +++ dev/usb/usb.c Fri Feb 25 15:31:55 2005 @@ -185,7 +185,7 @@ USB_ATTACH(usb) /* Make sure not to use tsleep() if we are cold booting. */ if (cold) - sc->sc_bus->use_polling++; + usb_set_polling(sc->sc_bus, 1); ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev); usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue); @@ -231,12 +231,34 @@ USB_ATTACH(usb) sc->sc_dying = 1; } if (cold) - sc->sc_bus->use_polling--; + usb_set_polling(sc->sc_bus, 0); config_pending_incr(); usb_kthread_create(usb_create_event_thread, sc); USB_ATTACH_SUCCESS_RETURN; +} + +void +usb_set_polling(usbd_bus_handle bus, int on) +{ + int s = splusb(); + + if (on) { + bus->use_polling++; + if (bus->use_polling == 1) { + /* Process pending events */ + bus->methods->soft_intr(bus); + } + } else { + bus->use_polling--; + if (bus->use_polling == 0) { + /* Process preserved interrupts */ + splhardusb(); + bus->methods->hard_intr(bus); + } + } + splx(s); } #if defined(__NetBSD__) || defined(__OpenBSD__) diff -rup dev/usb-1/usbdi.c dev/usb/usbdi.c --- dev/usb-1/usbdi.c Fri Jul 9 08:18:45 2004 +++ dev/usb/usbdi.c Fri Feb 25 15:31:55 2005 @@ -282,7 +282,7 @@ usbd_transfer(usbd_xfer_handle xfer) usb_dma_t *dmap = &xfer->dmabuf; usbd_status err; u_int size; - int s; + int polling, s; DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n", xfer, xfer->flags, pipe, pipe->running)); @@ -315,8 +315,16 @@ usbd_transfer(usbd_xfer_handle xfer) !usbd_xfer_isread(xfer)) memcpy(KERNADDR(dmap, 0), xfer->buffer, size); + if (xfer->flags & USBD_USE_POLLING) + usbd_set_polling(pipe->device, 1); + + polling = pipe->device->bus->use_polling; + err = pipe->methods->transfer(xfer); + if (xfer->flags & USBD_USE_POLLING) + usbd_set_polling(pipe->device, 0); + if (err != USBD_IN_PROGRESS && err) { /* The transfer has not been queued, so free buffer. */ if (xfer->rqflags & URQ_AUTO_DMABUF) { @@ -335,7 +343,7 @@ usbd_transfer(usbd_xfer_handle xfer) return (err); s = splusb(); if (!xfer->done) { - if (pipe->device->bus->use_polling) + if (polling) panic("usbd_transfer: not done"); tsleep(xfer, PRIBIO, "usbsyn", 0); } @@ -1082,13 +1090,7 @@ usbd_dopoll(usbd_interface_handle iface) void usbd_set_polling(usbd_device_handle dev, int on) { - if (on) - dev->bus->use_polling++; - else - dev->bus->use_polling--; - /* When polling we need to make sure there is nothing pending to do. */ - if (dev->bus->use_polling) - dev->bus->methods->soft_intr(dev->bus); + usb_set_polling(dev->bus, on); } usb_endpoint_descriptor_t * diff -rup dev/usb-1/usbdi.h dev/usb/usbdi.h --- dev/usb-1/usbdi.h Sun Dec 12 16:13:15 2004 +++ dev/usb/usbdi.h Fri Feb 25 15:31:55 2005 @@ -85,6 +85,7 @@ typedef void (*usbd_callback)(usbd_xfer_ #define USBD_SYNCHRONOUS 0x02 /* wait for completion */ /* in usb.h #define USBD_SHORT_XFER_OK 0x04*/ /* allow short reads */ #define USBD_FORCE_SHORT_XFER 0x08 /* force last short packet on write */ +#define USBD_USE_POLLING 0x10 /* poll for request completion */ #define USBD_NO_TIMEOUT 0 #define USBD_DEFAULT_TIMEOUT 5000 /* ms = 5 s */ @@ -191,6 +192,7 @@ struct usb_task { char onqueue; }; +void usb_set_polling(usbd_bus_handle dev, int on); void usb_add_task(usbd_device_handle dev, struct usb_task *task); void usb_rem_task(usbd_device_handle dev, struct usb_task *task); #define usb_init_task(t, f, a) ((t)->fun = (f), (t)->arg = (a), (t)->onqueue = 0) diff -rup dev/usb-1/usbdivar.h dev/usb/usbdivar.h --- dev/usb-1/usbdivar.h Sun Dec 12 15:21:14 2004 +++ dev/usb/usbdivar.h Fri Feb 25 15:31:55 2005 @@ -57,6 +57,7 @@ struct usbd_endpoint { struct usbd_bus_methods { usbd_status (*open_pipe)(struct usbd_pipe *pipe); void (*soft_intr)(void *); + int (*hard_intr)(void *); void (*do_poll)(struct usbd_bus *); usbd_status (*allocm)(struct usbd_bus *, usb_dma_t *, u_int32_t bufsize);