diff options
Diffstat (limited to 'sys/dev/usb/ohci.c')
-rw-r--r-- | sys/dev/usb/ohci.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index f0ad030..84ec03c 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.71 2000/02/01 05:42:52 augustss Exp $ */ +/* $NetBSD: ohci.c,v 1.73 2000/02/22 22:59:49 augustss Exp $ */ /* $FreeBSD$ */ /* @@ -135,11 +135,10 @@ 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 __P((struct usbd_bus *)); Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); -Static void ohci_process_done(ohci_softc_t *, - ohci_physaddr_t); Static usbd_status ohci_device_request(usbd_xfer_handle xfer); Static void ohci_add_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); @@ -268,6 +267,7 @@ struct ohci_pipe { Static struct usbd_bus_methods ohci_bus_methods = { ohci_open, + ohci_softintr, ohci_poll, ohci_allocm, ohci_freem, @@ -669,6 +669,7 @@ ohci_init(sc) SIMPLEQ_INIT(&sc->sc_free_xfers); + /* XXX determine alignment by R/W */ /* Allocate the HCCA area. */ err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE, OHCI_HCCA_ALIGN, &sc->sc_hccadma); @@ -730,6 +731,17 @@ ohci_init(sc) sc->sc_hcca->hcca_interrupt_table[revbits[i]] = htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr); +#ifdef OHCI_DEBUG + if (ohcidebug > 15) { + for (i = 0; i < OHCI_NO_EDS; i++) { + printf("ed#%d ", i); + ohci_dump_ed(sc->sc_eds[i]); + } + printf("iso "); + ohci_dump_ed(sc->sc_isoc_head); + } +#endif + /* Determine in what context we are running. */ ctl = OREAD4(sc, OHCI_CONTROL); if (ctl & OHCI_IR) { @@ -1036,7 +1048,6 @@ ohci_intr1(sc) * HcInterruptStatus should be checked to determine its cause. */ if (done != 0) { - sc->sc_hcca->hcca_done_head = 0; if (done & ~OHCI_DONE_INTRS) intrs = OHCI_WDH; if (done & OHCI_DONE_INTRS) { @@ -1062,7 +1073,7 @@ ohci_intr1(sc) sc->sc_bus.intr_context++; sc->sc_bus.no_intrs++; - DPRINTFN(7, ("ohci_intr: sc=%p intrs=%x(%x) eintr=%x\n", + DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n", sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), (u_int)eintrs)); @@ -1072,7 +1083,21 @@ ohci_intr1(sc) intrs &= ~OHCI_SO; } if (eintrs & OHCI_WDH) { - ohci_process_done(sc, done); + done &= ~OHCI_DONE_INTRS; + if (sc->sc_done == 0) + sc->sc_done = done; + else { + /* Tack on at the end of sc_done. */ + ohci_physaddr_t ldone; + ohci_soft_td_t *std; + + for (ldone = sc->sc_done; ldone != 0; + ldone = le32toh(std->td.td_nexttd)) + std = ohci_hash_find_td(sc, ldone); + std->td.td_nexttd = le32toh(done); + } + sc->sc_hcca->hcca_done_head = 0; + usb_schedsoftintr(&sc->sc_bus); intrs &= ~OHCI_WDH; } if (eintrs & OHCI_RD) { @@ -1142,13 +1167,21 @@ char *ohci_cc_strs[] = { #endif void -ohci_process_done(sc, done) - ohci_softc_t *sc; - ohci_physaddr_t done; +ohci_softintr(bus) + struct usbd_bus *bus; { + ohci_softc_t *sc = (ohci_softc_t *)bus; + ohci_physaddr_t done; ohci_soft_td_t *std, *sdone, *stdnext; usbd_xfer_handle xfer; - int len, cc; + int len, cc, s; + + sc->sc_bus.intr_context++; + + s = splhardusb(); + done = sc->sc_done; + sc->sc_done = 0; + splx(s); DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done)); @@ -1258,6 +1291,8 @@ ohci_process_done(sc, done) usb_transfer_complete(xfer); } } + + sc->sc_bus.intr_context--; } void @@ -1709,8 +1744,8 @@ void ohci_dump_ed(sed) ohci_soft_ed_t *sed; { - DPRINTF(("ED(%p) at %08lx: addr=%d endpt=%d maxp=%d %b\n" - "tailp=0x%8b headp=0x%8b nexted=0x%08lx\n", + DPRINTF(("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d %b\ntailp=0x%08lx " + "headflags=%b headp=0x%08lx nexted=0x%08lx\n", sed, (u_long)sed->physaddr, OHCI_ED_GET_FA(le32toh(sed->ed.ed_flags)), OHCI_ED_GET_EN(le32toh(sed->ed.ed_flags)), @@ -1721,6 +1756,7 @@ ohci_dump_ed(sed) "\20\1BIT1\2BIT2", (int)(uintptr_t)le32toh(sed->ed.ed_headp), "\20\1HALT\2CARRY", + (u_long)le32toh(sed->ed.ed_headp), (u_long)le32toh(sed->ed.ed_nexted))); } #endif |