diff options
author | sam <sam@FreeBSD.org> | 2008-12-23 04:42:10 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2008-12-23 04:42:10 +0000 |
commit | bb64ee0d8690157aadd890072d66aece6a5c8c01 (patch) | |
tree | 344f5514b5ff42f0a84ac8bd8622880dbd1466ee /sys/dev | |
parent | 95b2457edfed9c954582bdeac5fbb5c317f21e76 (diff) | |
download | FreeBSD-src-bb64ee0d8690157aadd890072d66aece6a5c8c01.zip FreeBSD-src-bb64ee0d8690157aadd890072d66aece6a5c8c01.tar.gz |
o add Transaction Translator support (still missing ISOC xfers)
o add EHCI_SCFLG_BIGEMMIO flag to force big-endian byte-select to be
set in USBMODE
o split reset work into new public routine ehci_reset so bus shim drivers
can force big-endian byte-select before ehci_init
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/ehci.c | 58 | ||||
-rw-r--r-- | sys/dev/usb/ehcivar.h | 3 |
2 files changed, 40 insertions, 21 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index 1b4c0080..11a5e83 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -310,33 +310,18 @@ static struct usbd_pipe_methods ehci_device_isoc_methods = { ehci_device_isoc_done, }; -static usbd_status -ehci_hcreset(ehci_softc_t *sc) +usbd_status +ehci_reset(ehci_softc_t *sc) { u_int32_t hcr; u_int i; - EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ - for (i = 0; i < 100; i++) { - usb_delay_ms(&sc->sc_bus, 1); - hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; - if (hcr) - break; - } - if (!hcr) - /* - * Fall through and try reset anyway even though - * Table 2-9 in the EHCI spec says this will result - * in undefined behavior. - */ - device_printf(sc->sc_bus.bdev, "stop timeout\n"); - EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET); for (i = 0; i < 100; i++) { usb_delay_ms(&sc->sc_bus, 1); hcr = EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_HCRESET; if (!hcr) { - if (sc->sc_flags & EHCI_SCFLG_SETMODE) { + if (sc->sc_flags & (EHCI_SCFLG_SETMODE | EHCI_SCFLG_BIGEMMIO)) { /* * Force USBMODE as requested. Controllers * may have multiple operating modes. @@ -347,6 +332,11 @@ ehci_hcreset(ehci_softc_t *sc) device_printf(sc->sc_bus.bdev, "set host controller mode\n"); } + if (sc->sc_flags & EHCI_SCFLG_BIGEMMIO) { + usbmode = (usbmode &~ EHCI_UM_ES) | EHCI_UM_ES_BE; + device_printf(sc->sc_bus.bdev, + "set big-endian mode\n"); + } EOWRITE4(sc, EHCI_USBMODE, usbmode); } return (USBD_NORMAL_COMPLETION); @@ -356,6 +346,30 @@ ehci_hcreset(ehci_softc_t *sc) return (USBD_IOERROR); } +static usbd_status +ehci_hcreset(ehci_softc_t *sc) +{ + u_int32_t hcr; + u_int i; + + EOWRITE4(sc, EHCI_USBCMD, 0); /* Halt controller */ + for (i = 0; i < 100; i++) { + usb_delay_ms(&sc->sc_bus, 1); + hcr = EOREAD4(sc, EHCI_USBSTS) & EHCI_STS_HCH; + if (hcr) + break; + } + if (!hcr) + /* + * Fall through and try reset anyway even though + * Table 2-9 in the EHCI spec says this will result + * in undefined behavior. + */ + device_printf(sc->sc_bus.bdev, "stop timeout\n"); + + return ehci_reset(sc); +} + usbd_status ehci_init(ehci_softc_t *sc) { @@ -2008,7 +2022,7 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer) i = UPS_HIGH_SPEED; - if (sc->sc_flags & EHCI_SCFLG_FORCESPEED) { + if (sc->sc_flags & (EHCI_SCFLG_FORCESPEED | EHCI_SCFLG_TT)) { if ((v & 0xc000000) == 0x8000000) i = UPS_HIGH_SPEED; else if ((v & 0xc000000) == 0x4000000) @@ -2056,7 +2070,8 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer) case UHF_PORT_RESET: DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n", index)); - if (EHCI_PS_IS_LOWSPEED(v)) { + if (EHCI_PS_IS_LOWSPEED(v) && + (sc->sc_flags & EHCI_SCFLG_TT) == 0) { /* Low speed device, give up ownership. */ ehci_disown(sc, index, 1); break; @@ -2089,7 +2104,8 @@ ehci_root_ctrl_start(usbd_xfer_handle xfer) device_get_nameunit(sc->sc_bus.bdev)); return (USBD_TIMEOUT); } - if (!(v & EHCI_PS_PE)) { + if (!(v & EHCI_PS_PE) && + (sc->sc_flags & EHCI_SCFLG_TT) == 0) { /* Not a high speed device, give up ownership.*/ ehci_disown(sc, index, 0); break; diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index 86720fe..fdd19ba 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -126,6 +126,8 @@ struct ehci_soft_islot { #define EHCI_SCFLG_FORCESPEED 0x0008 /* force speed (Marvell) */ #define EHCI_SCFLG_NORESTERM 0x0010 /* don't terminate reset sequence (Marvell) */ #define EHCI_SCFLG_BIGEDESC 0x0020 /* big-endian byte order descriptors */ +#define EHCI_SCFLG_BIGEMMIO 0x0040 /* big-endian byte order MMIO */ +#define EHCI_SCFLG_TT 0x0080 /* transaction translator present */ typedef struct ehci_softc { struct usbd_bus sc_bus; /* base device */ @@ -257,6 +259,7 @@ hc16toh(const struct ehci_softc *sc, const uint16_t v) } #endif +usbd_status ehci_reset(ehci_softc_t *); usbd_status ehci_init(ehci_softc_t *); int ehci_intr(void *); int ehci_detach(ehci_softc_t *, int); |