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:
parent
2e77b96f4a
commit
5b775a536b
@ -169,7 +169,6 @@ struct ehci_pipe {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
Static void ehci_shutdown(void *);
|
|
||||||
Static void ehci_power(int, void *);
|
Static void ehci_power(int, void *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1057,7 +1056,6 @@ OOO
|
|||||||
/*
|
/*
|
||||||
* Shut down the controller when the system is going down.
|
* Shut down the controller when the system is going down.
|
||||||
*/
|
*/
|
||||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
|
||||||
void
|
void
|
||||||
ehci_shutdown(void *v)
|
ehci_shutdown(void *v)
|
||||||
{
|
{
|
||||||
@ -1067,7 +1065,6 @@ ehci_shutdown(void *v)
|
|||||||
EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
|
EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */
|
||||||
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
|
EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
usbd_status
|
usbd_status
|
||||||
ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
|
ehci_allocm(struct usbd_bus *bus, usb_dma_t *dma, u_int32_t size)
|
||||||
|
@ -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_attach(device_t self);
|
||||||
static int ehci_pci_detach(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 *
|
static const char *
|
||||||
ehci_pci_match(device_t self)
|
ehci_pci_match(device_t self)
|
||||||
@ -276,6 +294,7 @@ ehci_pci_attach(device_t self)
|
|||||||
}
|
}
|
||||||
sc->sc_ncomp = ncomp;
|
sc->sc_ncomp = ncomp;
|
||||||
|
|
||||||
|
ehci_pci_takecontroller(self);
|
||||||
err = ehci_init(sc);
|
err = ehci_init(sc);
|
||||||
if (!err)
|
if (!err)
|
||||||
err = device_probe_and_attach(sc->sc_bus.bdev);
|
err = device_probe_and_attach(sc->sc_bus.bdev);
|
||||||
@ -332,11 +351,62 @@ ehci_pci_detach(device_t self)
|
|||||||
return 0;
|
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[] = {
|
static device_method_t ehci_methods[] = {
|
||||||
/* Device interface */
|
/* Device interface */
|
||||||
DEVMETHOD(device_probe, ehci_pci_probe),
|
DEVMETHOD(device_probe, ehci_pci_probe),
|
||||||
DEVMETHOD(device_attach, ehci_pci_attach),
|
DEVMETHOD(device_attach, ehci_pci_attach),
|
||||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
DEVMETHOD(device_shutdown, ehci_pci_shutdown),
|
||||||
|
|
||||||
/* Bus interface */
|
/* Bus interface */
|
||||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||||
|
@ -64,9 +64,17 @@
|
|||||||
|
|
||||||
#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */
|
#define PCI_EHCI_PORTWAKECAP 0x62 /* RW Port wake caps (opt) */
|
||||||
|
|
||||||
/* Regs ar EECP + offset */
|
/* EHCI Extended Capabilities */
|
||||||
#define PCI_EHCI_USBLEGSUP 0x00
|
#define EHCI_EC_LEGSUP 0x01
|
||||||
#define PCI_EHCI_USBLEGCTLSTS 0x04
|
|
||||||
|
#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 ***/
|
/*** EHCI capability registers ***/
|
||||||
|
|
||||||
|
@ -165,6 +165,7 @@ int ehci_intr(void *);
|
|||||||
int ehci_detach(ehci_softc_t *, int);
|
int ehci_detach(ehci_softc_t *, int);
|
||||||
int ehci_activate(device_ptr_t, enum devact);
|
int ehci_activate(device_ptr_t, enum devact);
|
||||||
#endif
|
#endif
|
||||||
|
void ehci_shutdown(void *v);
|
||||||
|
|
||||||
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
|
#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user