Save and restore the registers SOF and FRAMENUMBER on suspend. In some

cases the registers are not correctly set on resume.

This solves the problem of USB failing after resuming a machine.

Submitted by:	mike+fbsd@medianstrip.net
PR:		18261
This commit is contained in:
n_hibma 2000-08-07 00:04:53 +00:00
parent 7a93943baf
commit 38a807f0b0
2 changed files with 15 additions and 5 deletions

View File

@ -250,6 +250,7 @@ Static void uhci_dump_tds(uhci_soft_td_t *);
Static void uhci_dump_td(uhci_soft_td_t *); Static void uhci_dump_td(uhci_soft_td_t *);
#endif #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 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 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)) #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_has_timo->timo_handle);
sc->sc_bus.use_polling++; sc->sc_bus.use_polling++;
uhci_run(sc, 0); /* stop the controller */ 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 */ UHCICMD(sc, cmd | UHCI_CMD_EGSM); /* enter global suspend */
usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
sc->sc_suspend = why; sc->sc_suspend = why;
sc->sc_bus.use_polling--; sc->sc_bus.use_polling--;
DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD))); DPRINTF(("uhci_power: cmd=0x%x\n", UREAD2(sc, UHCI_CMD)));
} else { } 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 #ifdef DIAGNOSTIC
if (sc->sc_suspend == PWR_RESUME) if (sc->sc_suspend == PWR_RESUME)
printf("uhci_power: weird, resume without suspend.\n"); printf("uhci_power: weird, resume without suspend.\n");
@ -584,6 +585,12 @@ uhci_power(int why, void *v)
sc->sc_suspend = why; sc->sc_suspend = why;
if (cmd & UHCI_CMD_RS) if (cmd & UHCI_CMD_RS)
uhci_run(sc, 0); /* in case BIOS has started it */ 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 */ UHCICMD(sc, cmd | UHCI_CMD_FGR); /* force global resume */
usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */ UHCICMD(sc, cmd & ~UHCI_CMD_EGSM); /* back to normal */

View File

@ -154,6 +154,9 @@ typedef struct uhci_softc {
u_int8_t sc_addr; /* device address */ u_int8_t sc_addr; /* device address */
u_int8_t sc_conf; /* device configuration */ u_int8_t sc_conf; /* device configuration */
u_int8_t sc_saved_sof;
u_int16_t sc_saved_frnum;
char sc_isreset; char sc_isreset;
char sc_suspend; char sc_suspend;