Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Updates from t-hash
details: https://anonhg.NetBSD.org/src/rev/39857d55d4d7
branches: trunk
changeset: 344977:39857d55d4d7
user: skrll <skrll%NetBSD.org@localhost>
date: Sat Apr 30 15:02:53 2016 +0000
description:
Updates from t-hash
+ Split out printing PSI and taking ownership.
+ Split out resetting HC.
+ Split out calculating TRB index.
XXX magic numbers
XXX waits
diffstat:
sys/dev/usb/xhci.c | 264 ++++++++++++++++++++++++++++++----------------------
1 files changed, 151 insertions(+), 113 deletions(-)
diffs (truncated from 337 to 300 lines):
diff -r 918ef4a06bd7 -r 39857d55d4d7 sys/dev/usb/xhci.c
--- a/sys/dev/usb/xhci.c Sat Apr 30 15:00:24 2016 +0000
+++ b/sys/dev/usb/xhci.c Sat Apr 30 15:02:53 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: xhci.c,v 1.39 2016/04/30 15:00:24 skrll Exp $ */
+/* $NetBSD: xhci.c,v 1.40 2016/04/30 15:02:53 skrll Exp $ */
/*
* Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.39 2016/04/30 15:00:24 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.40 2016/04/30 15:02:53 skrll Exp $");
#include "opt_usb.h"
@@ -495,6 +495,22 @@
trb->trb_3 = htole32(control);
}
+static int
+xhci_trb_get_idx(struct xhci_ring *xr, uint64_t trb_0, int *idx)
+{
+ /* base address of TRBs */
+ bus_addr_t trbp = xhci_ring_trbp(xr, 0);
+
+ /* trb_0 range sanity check */
+ if (trb_0 == 0 || trb_0 < trbp ||
+ (trb_0 - trbp) % sizeof(struct xhci_trb) != 0 ||
+ (trb_0 - trbp) / sizeof(struct xhci_trb) >= xr->xr_ntrb) {
+ return 1;
+ }
+ *idx = (trb_0 - trbp) / sizeof(struct xhci_trb);
+ return 0;
+}
+
/* --- */
void
@@ -582,6 +598,59 @@
return false;
}
+static int
+xhci_hc_reset(struct xhci_softc * const sc)
+{
+ uint32_t usbcmd, usbsts;
+ int i;
+
+ /* Check controller not ready */
+ for (i = 0; i < 100; i++) {
+ usbsts = xhci_op_read_4(sc, XHCI_USBSTS);
+ if ((usbsts & XHCI_STS_CNR) == 0)
+ break;
+ usb_delay_ms(&sc->sc_bus, 1);
+ }
+ if (i >= 100) {
+ aprint_error_dev(sc->sc_dev, "controller not ready timeout\n");
+ return EIO;
+ }
+
+ /* Halt controller */
+ usbcmd = 0;
+ xhci_op_write_4(sc, XHCI_USBCMD, usbcmd);
+ usb_delay_ms(&sc->sc_bus, 1);
+
+ /* Reset controller */
+ usbcmd = XHCI_CMD_HCRST;
+ xhci_op_write_4(sc, XHCI_USBCMD, usbcmd);
+ for (i = 0; i < 100; i++) {
+ usbcmd = xhci_op_read_4(sc, XHCI_USBCMD);
+ if ((usbcmd & XHCI_CMD_HCRST) == 0)
+ break;
+ usb_delay_ms(&sc->sc_bus, 1);
+ }
+ if (i >= 100) {
+ aprint_error_dev(sc->sc_dev, "host controller reset timeout\n");
+ return EIO;
+ }
+
+ /* Check controller not ready */
+ for (i = 0; i < 100; i++) {
+ usbsts = xhci_op_read_4(sc, XHCI_USBSTS);
+ if ((usbsts & XHCI_STS_CNR) == 0)
+ break;
+ usb_delay_ms(&sc->sc_bus, 1);
+ }
+ if (i >= 100) {
+ aprint_error_dev(sc->sc_dev,
+ "controller not ready timeout after reset\n");
+ return EIO;
+ }
+
+ return 0;
+}
+
static void
hexdump(const char *msg, const void *base, size_t len)
@@ -610,6 +679,75 @@
#endif
}
+/* Process extended capabilities */
+static void
+xhci_ecp(struct xhci_softc *sc, uint32_t hcc)
+{
+ uint32_t ecp, ecr;
+
+ XHCIHIST_FUNC(); XHCIHIST_CALLED();
+
+ ecp = XHCI_HCC_XECP(hcc) * 4;
+ while (ecp != 0) {
+ ecr = xhci_read_4(sc, ecp);
+ aprint_debug_dev(sc->sc_dev, "ECR %x: %08x\n", ecp, ecr);
+ switch (XHCI_XECP_ID(ecr)) {
+ case XHCI_ID_PROTOCOLS: {
+ uint32_t w4, w8, wc;
+ uint16_t w2;
+ w2 = (ecr >> 16) & 0xffff;
+ w4 = xhci_read_4(sc, ecp + 4);
+ w8 = xhci_read_4(sc, ecp + 8);
+ wc = xhci_read_4(sc, ecp + 0xc);
+ aprint_debug_dev(sc->sc_dev,
+ " SP: %08x %08x %08x %08x\n", ecr, w4, w8, wc);
+ /* unused */
+ if (w4 == 0x20425355 && (w2 & 0xff00) == 0x0300) {
+ sc->sc_ss_port_start = (w8 >> 0) & 0xff;;
+ sc->sc_ss_port_count = (w8 >> 8) & 0xff;;
+ }
+ if (w4 == 0x20425355 && (w2 & 0xff00) == 0x0200) {
+ sc->sc_hs_port_start = (w8 >> 0) & 0xff;
+ sc->sc_hs_port_count = (w8 >> 8) & 0xff;
+ }
+ break;
+ }
+ case XHCI_ID_USB_LEGACY: {
+ uint8_t bios_sem;
+
+ /* Take host controller ownership from BIOS */
+ bios_sem = xhci_read_1(sc, ecp + XHCI_XECP_BIOS_SEM);
+ if (bios_sem) {
+ /* sets xHCI to be owned by OS */
+ xhci_write_1(sc, ecp + XHCI_XECP_OS_SEM, 1);
+ aprint_debug_dev(sc->sc_dev,
+ "waiting for BIOS to give up control\n");
+ for (int i = 0; i < 5000; i++) {
+ bios_sem = xhci_read_1(sc, ecp +
+ XHCI_XECP_BIOS_SEM);
+ if (bios_sem == 0)
+ break;
+ DELAY(1000);
+ }
+ if (bios_sem) {
+ aprint_error_dev(sc->sc_dev,
+ "timed out waiting for BIOS\n");
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ ecr = xhci_read_4(sc, ecp);
+ if (XHCI_XECP_NEXT(ecr) == 0) {
+ ecp = 0;
+ } else {
+ ecp += XHCI_XECP_NEXT(ecr) * 4;
+ }
+ }
+}
+
#define XHCI_HCCPREV1_BITS \
"\177\020" /* New bitmask */ \
"f\020\020XECP\0" \
@@ -650,9 +788,8 @@
{
bus_size_t bsz;
uint32_t cap, hcs1, hcs2, hcs3, hcc, dboff, rtsoff;
- uint32_t ecp, ecr;
- uint32_t usbcmd, usbsts, pagesize, config;
- int i;
+ uint32_t pagesize, config;
+ int i = 0;
uint16_t hciversion;
uint8_t caplength;
@@ -702,62 +839,8 @@
aprint_debug_dev(sc->sc_dev, "hcc=%s\n", sbuf);
aprint_debug_dev(sc->sc_dev, "xECP %x\n", XHCI_HCC_XECP(hcc) * 4);
- ecp = XHCI_HCC_XECP(hcc) * 4;
- while (ecp != 0) {
- ecr = xhci_read_4(sc, ecp);
- aprint_debug_dev(sc->sc_dev, "ECR %x: %08x\n", ecp, ecr);
- switch (XHCI_XECP_ID(ecr)) {
- case XHCI_ID_PROTOCOLS: {
- uint32_t w0, w4, w8;
- uint16_t w2;
- w0 = xhci_read_4(sc, ecp + 0);
- w2 = (w0 >> 16) & 0xffff;
- w4 = xhci_read_4(sc, ecp + 4);
- w8 = xhci_read_4(sc, ecp + 8);
- aprint_debug_dev(sc->sc_dev, "SP: %08x %08x %08x\n",
- w0, w4, w8);
- if (w4 == 0x20425355 && w2 == 0x0300) {
- sc->sc_ss_port_start = (w8 >> 0) & 0xff;;
- sc->sc_ss_port_count = (w8 >> 8) & 0xff;;
- }
- if (w4 == 0x20425355 && w2 == 0x0200) {
- sc->sc_hs_port_start = (w8 >> 0) & 0xff;
- sc->sc_hs_port_count = (w8 >> 8) & 0xff;
- }
- break;
- }
- case XHCI_ID_USB_LEGACY: {
- uint8_t bios_sem;
-
- /* Take host controller from BIOS */
- bios_sem = xhci_read_1(sc, ecp + XHCI_XECP_BIOS_SEM);
- if (bios_sem) {
- /* sets xHCI to be owned by OS */
- xhci_write_1(sc, ecp + XHCI_XECP_OS_SEM, 1);
- aprint_debug(
- "waiting for BIOS to give up control\n");
- for (i = 0; i < 5000; i++) {
- bios_sem = xhci_read_1(sc, ecp +
- XHCI_XECP_BIOS_SEM);
- if (bios_sem == 0)
- break;
- DELAY(1000);
- }
- if (bios_sem)
- printf("timed out waiting for BIOS\n");
- }
- break;
- }
- default:
- break;
- }
- ecr = xhci_read_4(sc, ecp);
- if (XHCI_XECP_NEXT(ecr) == 0) {
- ecp = 0;
- } else {
- ecp += XHCI_XECP_NEXT(ecr) * 4;
- }
- }
+ /* print PSI and take ownership from BIOS */
+ xhci_ecp(sc, hcc);
bsz = XHCI_PORTSC(sc->sc_maxports + 1);
if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, caplength, bsz,
@@ -780,44 +863,10 @@
return ENOMEM;
}
- for (i = 0; i < 100; i++) {
- usbsts = xhci_op_read_4(sc, XHCI_USBSTS);
- if ((usbsts & XHCI_STS_CNR) == 0)
- break;
- usb_delay_ms(&sc->sc_bus, 1);
- }
- if (i >= 100) {
- aprint_error_dev(sc->sc_dev, "controller not ready timeout\n");
- return EIO;
- }
-
- usbcmd = 0;
- xhci_op_write_4(sc, XHCI_USBCMD, usbcmd);
- usb_delay_ms(&sc->sc_bus, 1);
-
- usbcmd = XHCI_CMD_HCRST;
- xhci_op_write_4(sc, XHCI_USBCMD, usbcmd);
- for (i = 0; i < 100; i++) {
- usbcmd = xhci_op_read_4(sc, XHCI_USBCMD);
- if ((usbcmd & XHCI_CMD_HCRST) == 0)
- break;
- usb_delay_ms(&sc->sc_bus, 1);
- }
- if (i >= 100) {
- aprint_error_dev(sc->sc_dev, "host controller reset timeout\n");
- return EIO;
- }
-
- for (i = 0; i < 100; i++) {
- usbsts = xhci_op_read_4(sc, XHCI_USBSTS);
- if ((usbsts & XHCI_STS_CNR) == 0)
- break;
- usb_delay_ms(&sc->sc_bus, 1);
- }
- if (i >= 100) {
- aprint_error_dev(sc->sc_dev,
- "controller not ready timeout after reset\n");
- return EIO;
+ int rv;
+ rv = xhci_hc_reset(sc);
+ if (rv != 0) {
+ return rv;
Home |
Main Index |
Thread Index |
Old Index