diff options
-rw-r--r-- | sys/dev/usb/uhci.c | 17 | ||||
-rw-r--r-- | sys/dev/usb/uhcivar.h | 3 |
2 files changed, 15 insertions, 5 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 1095fe6..ea9a802 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -250,6 +250,7 @@ Static void uhci_dump_tds(uhci_soft_td_t *); Static void uhci_dump_td(uhci_soft_td_t *); #endif +#define UWRITE1(sc, r, x) bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)) #define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) #define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) #define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r)) @@ -565,17 +566,17 @@ uhci_power(int why, void *v) sc->sc_has_timo->timo_handle); sc->sc_bus.use_polling++; uhci_run(sc, 0); /* stop the controller */ + + /* save some state if BIOS doesn't */ + sc->sc_saved_frnum = UREAD2(sc, UHCI_FRNUM); + sc->sc_saved_sof = UREAD1(sc, UHCI_SOF); + UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */ usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); sc->sc_suspend = why; sc->sc_bus.use_polling--; DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); } else { - /* - * XXX We should really do much more here in case the - * controller registers have been lost and BIOS has - * not restored them. - */ #ifdef DIAGNOSTIC if (sc->sc_suspend == PWR_RESUME) printf("uhci_power: weird, resume without suspend.\n"); @@ -584,6 +585,12 @@ uhci_power(int why, void *v) sc->sc_suspend = why; if (cmd & UHCI_CMD_RS) uhci_run(sc, 0); /* in case BIOS has started it */ + + /* restore saved state */ + UWRITE4(sc, UHCI_FLBASEADDR, DMAADDR(&sc->sc_dma, 0)); + UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum); + UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof); + UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */ usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index 5e73e71..ead3495 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -154,6 +154,9 @@ typedef struct uhci_softc { u_int8_t sc_addr; /* device address */ u_int8_t sc_conf; /* device configuration */ + u_int8_t sc_saved_sof; + u_int16_t sc_saved_frnum; + char sc_isreset; char sc_suspend; |