FreeBSD Bugzilla – Attachment 37861 Details for
Bug 60099
Fix suspend and resume on USB ohci controllers
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ohci-sr-20031209.patch
ohci-sr-20031209.patch (text/plain), 5.96 KB, created by
amistry
on 2003-12-10 01:10:15 UTC
(
hide
)
Description:
ohci-sr-20031209.patch
Filename:
MIME Type:
Creator:
amistry
Created:
2003-12-10 01:10:15 UTC
Size:
5.96 KB
patch
obsolete
>diff -u sys/dev/usb.orig/ohci.c sys/dev/usb/ohci.c >--- sys/dev/usb.orig/ohci.c Mon Dec 8 21:23:51 2003 >+++ sys/dev/usb/ohci.c Tue Dec 9 19:42:29 2003 >@@ -1010,7 +1010,7 @@ > DPRINTF(("ohci_shutdown: stopping the HC\n")); > OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); > } >- >+#endif > /* > * Handle suspend/resume. > * >@@ -1018,6 +1018,139 @@ > * called from an intterupt context. This is all right since we > * are almost suspended anyway. > */ >+usbd_status >+ohci_resume(struct ohci_softc *sc) >+{ >+ uint32_t ctl, ival, fm, per; >+#ifdef USB_DEBUG >+ uint32_t rev; >+#endif >+ int s; >+#ifdef USB_DEBUG >+#if defined(__OpenBSD__) >+ DPRINTF((",")); >+#else >+ DPRINTF(("%s:", USBDEVNAME(sc->sc_bus.bdev))); >+#endif >+ rev = OREAD4(sc, OHCI_REVISION); >+ DPRINTF((" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), >+ OHCI_REV_LEGACY(rev) ? ", legacy support" : "")); >+ DPRINTF(("ohci_resume: controller state: ")); >+ switch(OREAD4(sc, OHCI_CONTROL) & OHCI_HCFS_MASK) { >+ case OHCI_HCFS_SUSPEND: >+ DPRINTF(("SUSPEND")); >+ break; >+ case OHCI_HCFS_RESUME: >+ DPRINTF(("RESUME")); >+ break; >+ case OHCI_HCFS_RESET: >+ DPRINTF(("RESET")); >+ break; >+ case OHCI_HCFS_OPERATIONAL: >+ DPRINTF(("OPERATIONAL")); >+ break; >+ } >+ DPRINTF(("\n")); >+#endif >+ s = splhardusb(); >+ /* The controller only responds to resume or reset writes at this point, so lets resume */ >+ /* We are only supposed to enter resume state from a suspend state. Should we check? */ >+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESUME); >+ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); >+#ifdef USB_DEBUG >+ /* check if the controller has resumed */ >+ ctl = OREAD4(sc, OHCI_CONTROL); >+ if((ctl & OHCI_HCFS_RESUME) == OHCI_HCFS_RESUME) { >+ DPRINTF(("ohci_resume: controller state: RESUME\n")); >+ } else { >+ /* panic or abort? */ >+ DPRINTF(("ohci_resume: ??? controller did not resume!\n")); >+ DPRINTF(("ohci_resume: OHCI_CONTROL: 0x%x\n",ctl)); >+ } >+ >+ ohci_dumpregs(sc); >+#endif >+ >+ /* reset or controller may not start */ >+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); >+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); >+ >+ /* spec says save frame interrupt value, reset, then restore */ >+ ival = OHCI_GET_IVAL(OREAD4(sc, OHCI_FM_INTERVAL)); >+ OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */ >+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); >+ >+ /* Some broken BIOSes do not recover these values */ >+ OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); >+ OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr); >+ OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr); >+ /* disable all interrupts and then switch on all desired interrupts */ >+ OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); >+ OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre | OHCI_MIE ); >+ >+ fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT; >+ fm |= OHCI_FSMPS(ival) | ival; >+ OWRITE4(sc, OHCI_FM_INTERVAL, fm); >+ per = OHCI_PERIODIC(ival); >+ OWRITE4(sc, OHCI_PERIODIC_START, per); >+ >+ /* start controller */ >+ ctl = sc->sc_control; >+ OWRITE4(sc, OHCI_CONTROL, ctl); >+ usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); >+ >+ /* power up ports */ >+ OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); >+ usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY); >+ splx(s); >+#ifdef USB_DEBUG >+ ohci_dumpregs(sc); >+#endif >+ return (USBD_NORMAL_COMPLETION); >+} >+ >+usbd_status >+ohci_suspend(struct ohci_softc *sc) >+{ >+ uint32_t ctl; >+ int s; >+ >+#ifdef USB_DEBUG >+ ohci_dumpregs(sc); >+#endif >+ >+ /* >+ * Preserve register values, in case that APM BIOS >+ * does not recover them. >+ */ >+ sc->sc_control = OREAD4(sc, OHCI_CONTROL); >+ sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE); >+ s = splhardusb(); >+ /* disable interrupts */ >+ OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); >+ splx(s); >+ /* Reset to stop processing frames or the controller might not suspend */ >+ OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); >+ usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY); >+ /* now suspend */ >+ ctl = OHCI_HCFS_SUSPEND; >+ OWRITE4(sc, OHCI_CONTROL, ctl); >+ usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); >+#ifdef USB_DEBUG >+ /* check if the controller is suspended */ >+ ctl = OREAD4(sc, OHCI_CONTROL); >+ if((ctl & OHCI_HCFS_SUSPEND) == OHCI_HCFS_SUSPEND) { >+ DPRINTF(("ohci_suspend: controller state: SUSPEND.\n")); >+ } else { >+ /* panic or abort? */ >+ DPRINTF(("ohci_suspend: ??? controller did not suspend!\n")); >+ DPRINTF(("ohci_suspend: OHCI_CONTROL: 0x%x\n", ctl)); >+ } >+#endif >+ return (USBD_NORMAL_COMPLETION); >+} >+ >+#if defined(__NetBSD__) || defined(__OpenBSD__) > void > ohci_power(int why, void *v) > { >diff -u sys/dev/usb.orig/ohci_pci.c sys/dev/usb/ohci_pci.c >--- sys/dev/usb.orig/ohci_pci.c Mon Dec 8 21:23:54 2003 >+++ sys/dev/usb/ohci_pci.c Tue Dec 9 19:13:39 2003 >@@ -304,10 +304,38 @@ > return 0; > } > >+/* implement suspend and resume */ >+static int >+ohci_pci_suspend(device_t self) >+{ >+ int err; >+ ohci_softc_t *sc = device_get_softc(self); >+ err = bus_generic_suspend(self); >+ if (err) >+ return err; >+ ohci_suspend(sc); >+ return 0; >+} >+ >+static int >+ohci_pci_resume(device_t self) >+{ >+ ohci_softc_t *sc = device_get_softc(self); >+ pci_set_powerstate(self, PCI_POWERSTATE_D0); >+ if(ohci_resume(sc) != USBD_NORMAL_COMPLETION) { >+ return ENXIO; >+ } >+ bus_generic_resume(self); >+ return 0; >+} >+ > static device_method_t ohci_methods[] = { > /* Device interface */ > DEVMETHOD(device_probe, ohci_pci_probe), > DEVMETHOD(device_attach, ohci_pci_attach), >+ DEVMETHOD(device_detach, bus_generic_detach), >+ DEVMETHOD(device_suspend, ohci_pci_suspend), >+ DEVMETHOD(device_resume, ohci_pci_resume), > DEVMETHOD(device_shutdown, bus_generic_shutdown), > > /* Bus interface */ >diff -u sys/dev/usb.orig/ohcivar.h sys/dev/usb/ohcivar.h >--- sys/dev/usb.orig/ohcivar.h Mon Dec 8 21:23:51 2003 >+++ sys/dev/usb/ohcivar.h Mon Dec 8 21:24:21 2003 >@@ -158,6 +158,8 @@ > #define OXFER(xfer) ((struct ohci_xfer *)(xfer)) > > usbd_status ohci_init(ohci_softc_t *); >+usbd_status ohci_suspend(ohci_softc_t *); >+usbd_status ohci_resume(ohci_softc_t *); > int ohci_intr(void *); > #if defined(__NetBSD__) || defined(__OpenBSD__) > int ohci_detach(ohci_softc_t *, int);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 60099
: 37861