Date: Tue, 9 Sep 2003 03:18:50 -0400 From: Anish Mistry <mistry.7@osu.edu> To: freebsd-current@freebsd.org Cc: Mark Sergeant <msergeant@snsonline.net> Subject: [patch] usb ohci suspend/resume v2 Message-ID: <200309090318.50846.mistry.7@osu.edu>
next in thread | raw e-mail | index | archive | help
--Boundary-03=_a7XX/yXtniDRQ/N Content-Type: multipart/mixed; boundary="Boundary-01=_a7XX/U1scR9TTaL" Content-Transfer-Encoding: 7bit Content-Description: signed data Content-Disposition: inline --Boundary-01=_a7XX/U1scR9TTaL Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Description: body text Content-Disposition: inline On Monday 08 September 2003 02:39 am, you wrote: > I've tried this patch but was unable to compile my kernel against it > with any of the sources from the past couple of weeks, it does apply > cleanly though. > > Cheers, > > Mark > Updated patch at (same as attached): http://am-productions.biz/docs/usb-3.patch This still causes the same problem as setting hw.acpi.sleep_delay on my laptop which cause a reset. I can't seem to figure out what in this patch that is causing that same behavior, but I've yet to see anyone with that same problem, so I'm going to assume that this should work for everyone else :(. Please if you are a usb guru, I could use some help, I've looked at the spec and some of the usb code, but am stuck for now. If you try it, let me know your outcome so I can then clean up the patch so that someone can commit it. Anish Mistry --Boundary-01=_a7XX/U1scR9TTaL Content-Type: text/x-diff; charset="us-ascii"; name="usb-3.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="usb-3.patch" diff -u usb.orig/ohci.c usb/ohci.c =2D-- usb.orig/ohci.c Tue Sep 9 02:56:49 2003 +++ usb/ohci.c Tue Sep 9 03:05:42 2003 @@ -1020,7 +1020,7 @@ DPRINTF(("ohci_shutdown: stopping the HC\n")); OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); } =2D +#endif /* * Handle suspend/resume. * @@ -1028,6 +1028,141 @@ * called from an intterupt context. This is all right since we * are almost suspended anyway. */ +usbd_status +ohci_resume(struct ohci_softc *sc) +{ + int s; + u_int32_t ctl, ival, hcr, fm, per, rev, desca; + =09 + DPRINTF(("ohci_resume: start\n")); +#if defined(__OpenBSD__) + printf(","); +#else + printf("%s:", USBDEVNAME(sc->sc_bus.bdev)); +#endif + rev =3D OREAD4(sc, OHCI_REVISION); + printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev), + OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); + printf("ohci_resume: controller state: "); + switch(OREAD4(sc, OHCI_CONTROL) & OHCI_HCFS_MASK) { + case OHCI_HCFS_SUSPEND: + printf("SUSPEND"); + break; + case OHCI_HCFS_RESUME: + printf("RESUME"); + break; + case OHCI_HCFS_RESET: + printf("RESET"); + break; + case OHCI_HCFS_OPERATIONAL: + printf("OPERATIONAL"); + break; + } + printf("\n"); + s =3D 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. Shou= ld we check? */ + OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESUME); + usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);=09 + /* check if the controller has resumed */ + ctl =3D OREAD4(sc, OHCI_CONTROL); + if((ctl & OHCI_HCFS_RESUME) =3D=3D OHCI_HCFS_RESUME) { + printf("ohci_resume: Controller resumed.\n"); + } else { + /* panic or abort? */ + printf("ohci_resume: ??? Controller not resumeded!\n"); + printf("ohci_resume: OHCI_CONTROL: 0x%x\n",ctl); + } + +#ifdef USB_DEBUG + 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 =3D 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); +/* OWRITE4(sc, OHCI_FM_INTERVAL, ival);*/ + + /* 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 =3D (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT; + fm |=3D OHCI_FSMPS(ival) | ival; + OWRITE4(sc, OHCI_FM_INTERVAL, fm); + per =3D OHCI_PERIODIC(ival); + OWRITE4(sc, OHCI_PERIODIC_START, per); + printf("ohci_resume: fm=3D0x%x per=3D0x%x\n",fm,per); + + /* start controller */ + ctl =3D 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 +=09 + return (USBD_NORMAL_COMPLETION); +} + +usbd_status +ohci_suspend(struct ohci_softc *sc) +{ + u_int32_t ctl,i; + int s; + +#ifdef USB_DEBUG + ohci_dumpregs(sc); +#endif + /* + * Preserve register values, in case that APM BIOS + * does not recover them. + */ + sc->sc_control =3D OREAD4(sc, OHCI_CONTROL); + sc->sc_intre =3D OREAD4(sc, OHCI_INTERRUPT_ENABLE); +/* sc->sc_port1 =3D OREAD4(sc, OHCI_RH_PORT_STATUS(1)); + sc->sc_port2 =3D OREAD4(sc, OHCI_RH_PORT_STATUS(2));*/ + s =3D splhardusb(); + /* disable interrupts */ + OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS); + splx(s); + /* */ +/* sc->sc_fmrem =3D OREAD4(sc, OHCI_FM_REMAINING); + sc->sc_fmnum =3D OREAD4(sc, OHCI_FM_NUMBER);*/ + /* 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 =3D OHCI_HCFS_SUSPEND; + OWRITE4(sc, OHCI_CONTROL, ctl); + usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); + /* check if the controller is suspended */ + ctl =3D OREAD4(sc, OHCI_CONTROL); + if((ctl & OHCI_HCFS_SUSPEND) =3D=3D OHCI_HCFS_SUSPEND) { + printf("ohci_suspend: Controller suspended.\n"); + } else { + /* panic or abort? */ + printf("ohci_suspend: ??? Controller not suspended!\n"); + printf("ohci_suspend: OHCI_CONTROL: 0x%x\n",ctl); + } + return (USBD_NORMAL_COMPLETION); +} + +#if defined(__NetBSD__) || defined(__OpenBSD__) void ohci_power(int why, void *v) { diff -u usb.orig/ohci_pci.c usb/ohci_pci.c =2D-- usb.orig/ohci_pci.c Tue Sep 9 02:56:49 2003 +++ usb/ohci_pci.c Tue Sep 9 03:03:33 2003 @@ -304,11 +304,42 @@ return 0; } =20 +/* implement suspend and resume */ +static int +ohci_pci_suspend(device_t self) +{ + int err; + ohci_softc_t *sc =3D device_get_softc(self); + err =3D 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 =3D device_get_softc(self); + device_printf(self, "ohci_pci_resume: power_state =3D 0x%08x\n", + pci_get_powerstate(self)); + pci_set_powerstate(self, PCI_POWERSTATE_D0); + if(ohci_resume(sc) !=3D USBD_NORMAL_COMPLETION) { + return ENXIO; + } + bus_generic_resume(self); + + return 0; +} + static device_method_t ohci_methods[] =3D { /* Device interface */ DEVMETHOD(device_probe, ohci_pci_probe), DEVMETHOD(device_attach, ohci_pci_attach), =2D DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_suspend, ohci_pci_suspend), + DEVMETHOD(device_resume, ohci_pci_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), =20 /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), diff -u usb.orig/ohcivar.h usb/ohcivar.h =2D-- usb.orig/ohcivar.h Tue Sep 9 02:56:49 2003 +++ usb/ohcivar.h Tue Sep 9 03:03:33 2003 @@ -158,6 +158,8 @@ #define OXFER(xfer) ((struct ohci_xfer *)(xfer)) =20 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); --Boundary-01=_a7XX/U1scR9TTaL-- --Boundary-03=_a7XX/yXtniDRQ/N Content-Type: application/pgp-signature Content-Description: signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.3 (FreeBSD) iD8DBQA/XX7axqA5ziudZT0RArerAJ9DxkiYhVBC/hEvj3hVal8D4N3thACeMNQT De+UzX0NruQ6WDmDTvfmS0A= =M8pK -----END PGP SIGNATURE----- --Boundary-03=_a7XX/yXtniDRQ/N--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309090318.50846.mistry.7>