Attempt to follow the correct procedure for synchronising with the

system BIOS to disable legacy device emulation as per the "EHCI
Extended Capability: Pre-OS to OS Handoff Synchronisation" section
of the EHCI spec. BIOSes that implement legacy emulation using SMIs
are supposed to disable the emulation when this procedure is performed.
This commit is contained in:
iedowse 2004-08-02 12:56:01 +00:00
parent 8ff42923d7
commit 63868484d5
4 changed files with 83 additions and 7 deletions

View File

@ -169,7 +169,6 @@ struct ehci_pipe {
};
#if defined(__NetBSD__) || defined(__OpenBSD__)
Static void ehci_shutdown(void *);
Static void ehci_power(int, void *);
#endif
@ -1057,7 +1056,6 @@ OOO
/*
* Shut down the controller when the system is going down.
*/
#if defined(__NetBSD__) || defined(__OpenBSD__)
void
ehci_shutdown(void *v)
{
@ -1067,7 +1065,6 @@ ehci_shutdown(void *v)
EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
}
#endif
usbd_status
ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)

View File

@ -101,6 +101,24 @@ static const char *ehci_device_generic = "EHCI (generic) USB 2.0 controller";
static int ehci_pci_attach(device_t self);
static int ehci_pci_detach(device_t self);
static int ehci_pci_shutdown(device_t self);
static void ehci_pci_givecontroller(device_t self);
static void ehci_pci_takecontroller(device_t self);
static int
ehci_pci_shutdown(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
int err;
err = bus_generic_shutdown(self);
if (err)
return (err);
ehci_shutdown(sc);
ehci_pci_givecontroller(self);
return 0;
}
static const char *
ehci_pci_match(device_t self)
@ -276,6 +294,7 @@ ehci_pci_attach(device_t self)
}
sc->sc_ncomp = ncomp;
ehci_pci_takecontroller(self);
err = ehci_init(sc);
if (!err)
err = device_probe_and_attach(sc->sc_bus.bdev);
@ -332,11 +351,62 @@ ehci_pci_detach(device_t self)
return 0;
}
static void
ehci_pci_takecontroller(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
u_int32_t cparams, eec, legsup;
int eecp, i;
cparams = EREAD4(sc, EHCI_HCCPARAMS);
/* Synchronise with the BIOS if it owns the controller. */
for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
eecp = EHCI_EECP_NEXT(eec)) {
eec = pci_read_config(self, eecp, 4);
if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP)
continue;
legsup = eec;
pci_write_config(self, eecp, legsup | EHCI_LEGSUP_OSOWNED, 4);
if (legsup & EHCI_LEGSUP_BIOSOWNED) {
printf("%s: waiting for BIOS to give up control\n",
USBDEVNAME(sc->sc_bus.bdev));
for (i = 0; i < 5000; i++) {
legsup = pci_read_config(self, eecp, 4);
if ((legsup & EHCI_LEGSUP_BIOSOWNED) == 0)
break;
DELAY(1000);
}
if (legsup & EHCI_LEGSUP_BIOSOWNED)
printf("%s: timed out waiting for BIOS\n",
USBDEVNAME(sc->sc_bus.bdev));
}
}
}
static void
ehci_pci_givecontroller(device_t self)
{
ehci_softc_t *sc = device_get_softc(self);
u_int32_t cparams, eec, legsup;
int eecp;
cparams = EREAD4(sc, EHCI_HCCPARAMS);
for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
eecp = EHCI_EECP_NEXT(eec)) {
eec = pci_read_config(self, eecp, 4);
if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP)
continue;
legsup = eec;
pci_write_config(self, eecp, legsup & ~EHCI_LEGSUP_OSOWNED, 4);
}
}
static device_method_t ehci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ehci_pci_probe),
DEVMETHOD(device_attach, ehci_pci_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_shutdown, ehci_pci_shutdown),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),

View File

@ -64,9 +64,17 @@
#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */
/* Regs ar EECP + offset */
#define PCI_EHCI_USBLEGSUP 0x00
#define PCI_EHCI_USBLEGCTLSTS 0x04
/* EHCI Extended Capabilities */
#define EHCI_EC_LEGSUP 0x01
#define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff)
#define EHCI_EECP_ID(x) ((x) & 0xff)
/* Legacy support extended capability */
#define EHCI_LEGSUP_LEGSUP 0x01
#define EHCI_LEGSUP_OSOWNED 0x01000000 /* OS owned semaphore */
#define EHCI_LEGSUP_BIOSOWNED 0x00010000 /* BIOS owned semaphore */
#define EHCI_LEGSUP_USBLEGCTLSTS 0x04
/*** EHCI capability registers ***/

View File

@ -165,6 +165,7 @@ int ehci_intr(void *);
int ehci_detach(ehci_softc_t *, int);
int ehci_activate(device_ptr_t, enum devact);
#endif
void ehci_shutdown(void *v);
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)