Date: Sat, 31 Jul 2010 18:39:05 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 181655 for review Message-ID: <201007311839.o6VId5xL015266@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181655?ac=10 Change 181655 by hselasky@hselasky_laptop001 on 2010/07/31 18:38:39 USB controller (XHCI): - implement event ring decoding - compile fixes Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#4 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#7 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci_pci.c#3 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#8 edit .. //depot/projects/usb/src/sys/dev/usb/usb.h#52 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#4 (text+ko) ==== @@ -109,6 +109,12 @@ uint8_t direction; }; +static void xhci_do_poll(struct usb_bus *); +static void xhci_device_done(struct usb_xfer *, usb_error_t); +static void xhci_root_intr(struct xhci_softc *); + +extern struct usb_bus_methods xhci_bus_methods; + void xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb) { @@ -117,16 +123,16 @@ cb(bus, &sc->sc_hw.root_pc, &sc->sc_hw.root_pg, sizeof(struct xhci_hw_root), XHCI_PAGE_SIZE); - cb(bus, &sc->sc_ctx.root_pc, &sc->sc_ctx.root_pg, - sizeof(struct xhci_ctx_root), XHCI_PAGE_SIZE); + cb(bus, &sc->sc_hw.ctx_pc, &sc->sc_hw.ctx_pg, + sizeof(struct xhci_dev_ctx_addr), XHCI_PAGE_SIZE); } -static usb_error_t +usb_error_t xhci_start_controller(struct xhci_softc *sc) { struct usb_page_search buf_res; struct xhci_hw_root *phwr; - struct xhci_ctx_root *pctxr; + struct xhci_dev_ctx_addr *pctxa; uint64_t addr; uint32_t temp; uint16_t i; @@ -138,6 +144,9 @@ sc->sc_runt_off = XREAD4(sc, capa, XHCI_RTSOFF) & ~0xF; sc->sc_door_off = XREAD4(sc, capa, XHCI_DBOFF) & ~0x3; + sc->sc_event_ccs = 1; + sc->sc_event_idx = 0; + DPRINTF("xHCI version = 0x%04x\n", XREAD2(sc, capa, XHCI_HCIVERSION)); /* Reset controller */ @@ -145,7 +154,7 @@ for (i = 0; i != 100; i++) { usb_pause_mtx(NULL, hz / 1000); - temp = XREAD4(sc, XHCI_USBCMD) & XHCI_CMD_HCRST; + temp = XREAD4(sc, oper, XHCI_USBCMD) & XHCI_CMD_HCRST; if (!temp) break; } @@ -160,10 +169,26 @@ return (USB_ERR_IOERROR); } + temp = XREAD4(sc, capa, XHCI_HCSPARAMS1); + + i = XHCI_HCS1_N_PORTS(temp); + + if ((i < 1) || (i > 15)) { + device_printf(sc->sc_bus.bdev, "Invalid number " + "of ports: %u\n", i); + if (i < 1) + return (USB_ERR_IOERROR); + else + i = 15; + } + + sc->sc_noport = i; + sc->sc_nodev = XHCI_HCS1_DEVSLOT_MAX(temp); + temp = XREAD4(sc, oper, XHCI_USBSTS); /* clear interrupts */ - XWRITE4(sc, oper, XHCI_USBSTS, status); + XWRITE4(sc, oper, XHCI_USBSTS, temp); /* disable all device notifications */ XWRITE4(sc, oper, XHCI_DNCTRL, 0); @@ -173,9 +198,9 @@ usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res); addr = buf_res.physaddr; - pctxr = buf_res.ptr; + pctxa = buf_res.buffer; - memset(pctxr, 0, sizeof(*pctxr)); + memset(pctxa, 0, sizeof(*pctxa)); XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr); XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32)); @@ -187,16 +212,16 @@ /* Setup interrupter registers */ temp = XREAD4(sc, runt, XHCI_IMAN(0)); - temp |= XHCI_IMAN_IE_BIT | XHCI_IMAN_IP_BIT; - XWRITE4(sc, runt, XHCI_IMAN(0)); + temp |= XHCI_IMAN_INTR_ENA | XHCI_IMAN_INTR_PEND; + XWRITE4(sc, runt, XHCI_IMAN(0), temp); /* Setup interrupt rate */ - XWRITE4(sc, runt, XHCI_IMOD, XHCI_IMOD_DEFAULT); + XWRITE4(sc, runt, XHCI_IMOD(0), XHCI_IMOD_DEFAULT); usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res); - phwr = buf_res.ptr; + phwr = buf_res.buffer; addr = (uint64_t)buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[0]; /* reset hardware root structure */ @@ -219,10 +244,10 @@ sc->sc_erst_max = temp; - XWRITE4(sc, runt, XHCI_ERSTSZ(0), temp); + XWRITE4(sc, runt, XHCI_ERSTS_SET(0), temp); - XWRITE4(sc, oper, XHCI_ERDP_LO(0), (uint32_t)addr); - XWRITE4(sc, oper, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32)); + XWRITE4(sc, oper, XHCI_ERSTDP_LO(0), (uint32_t)addr); + XWRITE4(sc, oper, XHCI_ERSTDP_HI(0), (uint32_t)(addr >> 32)); addr = (uint64_t)buf_res.physaddr; @@ -236,7 +261,7 @@ XWRITE4(sc, oper, XHCI_CRCR_LO, (uint32_t)addr); XWRITE4(sc, oper, XHCI_CRCR_HI, (uint32_t)(addr >> 32)); - usb_bus_mem_flush_all(&sc->sc_bus, &ehci_iterate_hw_softc); + usb_bus_mem_flush_all(&sc->sc_bus, &xhci_iterate_hw_softc); /* Go! */ XWRITE4(sc, oper, XHCI_USBCMD, XHCI_CMD_RS | XHCI_CMD_INTE | XHCI_CMD_HSEE); @@ -248,6 +273,7 @@ break; } if (temp) { + XWRITE4(sc, oper, XHCI_USBCMD, 0); device_printf(sc->sc_bus.bdev, "Run timeout.\n"); return (USB_ERR_IOERROR); } @@ -258,7 +284,7 @@ return (0); } -static usb_error_t +usb_error_t xhci_halt_controller(struct xhci_softc *sc) { uint32_t temp; @@ -284,43 +310,45 @@ } usb_error_t -xhci_init(struct xhci_softc *sc) +xhci_init(struct xhci_softc *sc, device_t self) { /* set the bus revision */ sc->sc_bus.usbrev = USB_REV_3_0; - /* set up the bus struct */ - sc->sc_bus.methods = &ehci_bus_methods; + /* set up the bus struct */ + sc->sc_bus.methods = &xhci_bus_methods; - return (0); -} + /* setup devices array */ + sc->sc_bus.devices = sc->sc_devices; + sc->sc_bus.devices_max = XHCI_MAX_DEVICES; -void -xhci_detach(struct xhci_softc *sc) -{ + /* get all DMA memory */ + if (usb_bus_mem_alloc_all(&sc->sc_bus, + USB_GET_DMA_TAG(self), &xhci_iterate_hw_softc)) { + return (ENOMEM); + } - + return (0); } void xhci_suspend(struct xhci_softc *sc) { - - + /* XXX TODO */ } void xhci_resume(struct xhci_softc *sc) { - - + /* XXX TODO */ } void xhci_shutdown(struct xhci_softc *sc) { + DPRINTF("Stopping the XHCI\n"); - + xhci_halt_controller(sc); } static usb_error_t @@ -526,18 +554,62 @@ static void xhci_interrupt_poll(struct xhci_softc *sc) { - struct usb_xfer *xfer; + struct usb_page_search buf_res; + struct xhci_hw_root *phwr; + uint32_t temp; + uint16_t i; + uint8_t j; + uint8_t k; + uint8_t t; + + usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res); + + phwr = buf_res.buffer; + + usb_pc_cpu_invalidate(&sc->sc_hw.root_pc); + + i = sc->sc_event_idx; + j = sc->sc_event_ccs; + t = 2; + + while (1) { + + temp = le32toh(phwr->hwr_events[i].dwTrb3); + k = (temp & XHCI_TRB_3_CYCLE_BIT) ? 1 : 0; + + if (j != k) + break; + + switch (XHCI_TRB_3_TYPE_GET(temp)) { + case XHCI_TRB_EVENT_TRANSFER: + xhci_check_transfer(sc, &phwr->hwr_events[i]); + break; + default: + DPRINTF("Received event = 0x%x\n", + XHCI_TRB_3_TYPE_GET(temp)); + break; + } + + i++; + + if (i == XHCI_MAX_EVENTS) { + i = 0; + j ^= 1; -repeat: - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - /* - * check if transfer is transferred - */ - if (xhci_check_transfer(xfer)) { - /* queue has been modified */ - goto repeat; + /* check for timeout */ + if (!--t) + break; } } + + temp = buf_res.physaddr + (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[i]; + + /* we are within a PAGE - no need to update the high bits */ + + XWRITE4(sc, oper, XHCI_ERSTDP_LO(0), temp); + + sc->sc_event_idx = i; + sc->sc_event_ccs = j; } /*------------------------------------------------------------------------* @@ -1037,10 +1109,6 @@ /* must have at least one frame! */ xfer->td_transfer_last = td; - - if (xfer->xroot->udev->flags.self_suspended == 0) { - EHCI_APPEND_QH(qh, *qh_last); XXX; - } } static void @@ -1227,8 +1295,7 @@ }; static const -struct usb_hub_ss_descriptor xhci_hubd = -{ +struct usb_hub_ss_descriptor xhci_hubd = { .bLength = sizeof(xhci_hubd), .bDescriptorType = UDESC_SS_HUB, }; @@ -1473,7 +1540,7 @@ DeviceRemovable[j / 8] |= 1U << (j % 8); } } - len = sc->sc_hub_desc.hubd.bDescLength; + len = sc->sc_hub_desc.hubd.bLength; break; case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE): @@ -1842,103 +1909,31 @@ static void xhci_device_resume(struct usb_device *udev) { - struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); - struct usb_xfer *xfer; - struct usb_pipe_methods *methods; - DPRINTF("\n"); USB_BUS_LOCK(udev->bus); - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - - if (xfer->xroot->udev == udev) { - - methods = xfer->endpoint->methods; - - if ((methods == &xhci_device_bulk_methods) || - (methods == &xhci_device_ctrl_methods)) { - XHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set], - sc->sc_async_p_last); - } - if (methods == &xhci_device_intr_methods) { - XHCI_APPEND_QH(xfer->qh_start[xfer->flags_int.curr_dma_set], - sc->sc_intr_p_last[xfer->qh_pos]); - } - } - } + /* start endpoint */ USB_BUS_UNLOCK(udev->bus); - - return; } static void xhci_device_suspend(struct usb_device *udev) { - struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); - struct usb_xfer *xfer; - struct usb_pipe_methods *methods; - DPRINTF("\n"); USB_BUS_LOCK(udev->bus); - TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) { - - if (xfer->xroot->udev == udev) { + /* stop endpoint */ - methods = xfer->endpoint->methods; - - if ((methods == &xhci_device_bulk_methods) || - (methods == &xhci_device_ctrl_methods)) { - XHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set], - sc->sc_async_p_last); - } - if (methods == &xhci_device_intr_methods) { - XHCI_REMOVE_QH(xfer->qh_start[xfer->flags_int.curr_dma_set], - sc->sc_intr_p_last[xfer->qh_pos]); - } - } - } - USB_BUS_UNLOCK(udev->bus); - - return; } static void xhci_set_hw_power(struct usb_bus *bus) { - struct xhci_softc *sc = XHCI_BUS2SC(bus); - uint32_t temp; - uint32_t flags; - DPRINTF("\n"); - - USB_BUS_LOCK(bus); - - flags = bus->hw_power_state; - - temp = EOREAD4(sc, XHCI_USBCMD); - - temp &= ~(XHCI_CMD_ASE | XHCI_CMD_PSE); - - if (flags & (USB_HW_POWER_CONTROL | - USB_HW_POWER_BULK)) { - DPRINTF("Async is active\n"); - temp |= XHCI_CMD_ASE; - } - if (flags & (USB_HW_POWER_INTERRUPT | - USB_HW_POWER_ISOC)) { - DPRINTF("Periodic is active\n"); - temp |= XHCI_CMD_PSE; - } - EOWRITE4(sc, XHCI_USBCMD, temp); - - USB_BUS_UNLOCK(bus); - - return; } struct usb_bus_methods xhci_bus_methods = ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#7 (text+ko) ==== @@ -326,10 +326,6 @@ struct xhci_trb hwr_commands[XHCI_MAX_COMMANDS]; }; -struct xhci_ctx_root { - volatile uint64_t ctxr_ptr[XHCI_MAX_DEVICES]; -}; - struct xhci_endpoint_ext { TAILQ_HEAD(, xhci_qh) head; @@ -407,7 +403,10 @@ uint16_t sc_flags; /* chip specific flags */ uint16_t sc_erst_max; + uint16_t sc_event_idx; + uint8_t sc_event_ccs; + uint8_t sc_nodev; /* number of devices on root HUB */ uint8_t sc_noport; /* number of ports on root HUB */ uint8_t sc_addr; /* root HUB device address */ uint8_t sc_conf; /* root HUB device configuration */ @@ -422,7 +421,7 @@ void xhci_suspend(struct xhci_softc *); void xhci_resume(struct xhci_softc *); void xhci_shutdown(struct xhci_softc *); -usb_error_t xhci_init(struct xhci_softc *); +usb_error_t xhci_init(struct xhci_softc *, device_t); usb_error_t xhci_start_controller(struct xhci_softc *); void xhci_iterate_hw_softc(struct usb_bus *, usb_bus_mem_sub_cb_t *); usb_error_t xhci_halt_controller(struct xhci_softc *); ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci_pci.c#3 (text+ko) ==== @@ -169,7 +169,7 @@ /* XXX check for 64-bit capability */ - if (xhci_init(sc)) { + if (xhci_init(sc, self)) { device_printf(self, "Could not initialize softc\n"); goto error; } ==== //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#8 (text+ko) ==== @@ -156,24 +156,24 @@ /* XHCI runtime registers. Offset given by XHCI_CAPLENGTH + XHCI_RTSOFF registers */ #define XHCI_MFINDEX 0x0000 /* RO - microframe index */ #define XHCI_MFINDEX_GET(x) ((x) & 0x1FFF) -#define XHCI_IMAN(n) (0x0020 + (0x20 * (n)) /* XHCI interrupt management */ +#define XHCI_IMAN(n) (0x0020 + (0x20 * (n))) /* XHCI interrupt management */ #define XHCI_IMAN_INTR_PEND 0x00000001 /* RW - interrupt pending */ #define XHCI_IMAN_INTR_ENA 0x00000002 /* RW - interrupt enable */ -#define XHCI_IMOD(n) (0x0024 + (0x20 * (n)) /* XHCI interrupt moderation */ +#define XHCI_IMOD(n) (0x0024 + (0x20 * (n))) /* XHCI interrupt moderation */ #define XHCI_IMOD_IVAL_GET(x) (((x) >> 0) & 0xFFFF) /* 250ns unit */ #define XHCI_IMOD_IVAL_SET(x) (((x) & 0xFFFF) << 0) /* 250ns unit */ #define XHCI_IMOD_ICNT_GET(x) (((x) >> 16) & 0xFFFF) /* 250ns unit */ #define XHCI_IMOD_ICNT_SET(x) (((x) & 0xFFFF) << 16) /* 250ns unit */ #define XHCI_IMOD_DEFAULT 0x000001F4U /* 8000 IRQ/second */ -#define XHCI_ERSTSZ(n) (0x0028 + (0x20 * (n)) /* XHCI event ring segment table size */ +#define XHCI_ERSTSZ(n) (0x0028 + (0x20 * (n))) /* XHCI event ring segment table size */ #define XHCI_ERSTS_GET(x) ((x) & 0xFFFF) #define XHCI_ERSTS_SET(x) ((x) & 0xFFFF) -#define XHCI_ERSTBA_LO(n) (0x0030 + (0x20 * (n)) /* XHCI event ring segment table BA */ -#define XHCI_ERSTBA_HI(n) (0x0034 + (0x20 * (n)) /* XHCI event ring segment table BA */ -#define XHCI_ERSTDP_LO(n) (0x0038 + (0x20 * (n)) /* XHCI event ring dequeue pointer */ +#define XHCI_ERSTBA_LO(n) (0x0030 + (0x20 * (n))) /* XHCI event ring segment table BA */ +#define XHCI_ERSTBA_HI(n) (0x0034 + (0x20 * (n))) /* XHCI event ring segment table BA */ +#define XHCI_ERSTDP_LO(n) (0x0038 + (0x20 * (n))) /* XHCI event ring dequeue pointer */ #define XHCI_ERSTDP_LO_SIGET(x) ((x) & 0x7) /* RO - dequeue segment index */ #define XHCI_ERSTDP_LO_BUSY 0x00000008 /* RW - event handler busy */ -#define XHCI_ERSTDP_HI(n) (0x003C + (0x20 * (n)) /* XHCI event ring dequeue pointer */ +#define XHCI_ERSTDP_HI(n) (0x003C + (0x20 * (n))) /* XHCI event ring dequeue pointer */ /* XHCI doorbell registers. Offset given by XHCI_CAPLENGTH + XHCI_DBOFF registers */ #define XHCI_DOORBELL 0x0000 ==== //depot/projects/usb/src/sys/dev/usb/usb.h#52 (text+ko) ==== @@ -593,7 +593,7 @@ typedef struct usb_hub_descriptor usb_hub_descriptor_t; struct usb_hub_ss_descriptor { - uByte bDescLength; + uByte bLength; uByte bDescriptorType; uByte bNbrPorts; /* max 15 */ uWord wHubCharacteristics;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201007311839.o6VId5xL015266>