Date: Sun, 1 Aug 2010 21:21:31 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 181695 for review Message-ID: <201008012121.o71LLVt1059936@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@181695?ac=10 Change 181695 by hselasky@hselasky_laptop001 on 2010/08/01 21:20:47 USB controller (XHCI): - add code to allocate, initialise and free XHCI device contexts. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#8 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#10 edit .. //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#11 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#8 (text+ko) ==== @@ -112,6 +112,7 @@ 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 *); +static void xhci_free_device_ext(struct usb_device *udev); extern struct usb_bus_methods xhci_bus_methods; @@ -175,18 +176,30 @@ i = XHCI_HCS1_N_PORTS(temp); - if ((i < 1) || (i > 15)) { + if (i == 0) { device_printf(sc->sc_bus.bdev, "Invalid number " "of ports: %u\n", i); - if (i < 1) - return (USB_ERR_IOERROR); - else - i = 15; + return (USB_ERR_IOERROR); } sc->sc_noport = i; sc->sc_nodev = XHCI_HCS1_DEVSLOT_MAX(temp); + temp = XREAD4(sc, capa, XHCI_HCSPARAMS2); + + sc->sc_noscratch = XHCI_HCS2_SPB_MAX(temp); + + if (sc->sc_noscratch > XHCI_MAX_SCRATCHPADS) { + device_printf(sc->sc_bus.bdev, "XHCI request " + "too many scratchpads\n"); + return (USB_ERR_NOMEM); + } + + temp = XREAD4(sc, capa, XHCI_HCSPARAMS3); + + sc->sc_exit_lat_max = XHCI_HCS3_U1_DEL(temp) + + XHCI_HCS3_U2_DEL(temp) + 250 /* us */; + temp = XREAD4(sc, oper, XHCI_USBSTS); /* clear interrupts */ @@ -1316,6 +1329,186 @@ } static usb_error_t +xhci_set_slot_scratch(struct xhci_softc *sc, uint8_t index, + uint64_t dev_addr, uint64_t scratch_addr) +{ + struct usb_page_search buf_res; + volatile uint64_t *ptr; + + usbd_get_page(&sc->sc_hw.ctx_pc, 0, &buf_res); + + ptr = buf_res.buffer; + ptr[(2*index) + 0] = htole64(dev_addr); + ptr[(2*index) + 1] = htole64(scratch_addr); + + usb_pc_cpu_flush(&sc->sc_hw.ctx_pc); +} + +static usb_error_t +xhci_alloc_device_ext(struct usb_device *udev) +{ + struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); + struct usb_page_search buf_scp; + struct usb_page_search buf_dev; + struct usb_page_cache *pcd; + struct usb_page *pgd; + struct usb_page_cache *pcs; + struct usb_page *pgs; + struct xhci_dev_ctx *pdctx; + struct usb_device *hubdev; + uint64_t addr; + uint32_t temp; + uint8_t index; + uint8_t failure; + uint8_t i; + uint8_t rh_port; + + index = udev->device_index; + failure = 0; + + pcd = &sc->sc_hw.devs[index].device_pc; + pgd = &sc->sc_hw.devs[index].device_pg; + + /* need to initialize the page cache */ + pcd->tag_parent = sc->sc_bus.dma_parent_tag; + + if (usb_pc_alloc_mem(pcd, pgd, sizeof(*pdctx), XHCI_PAGE_SIZE)) + failure = 1; + + if (failure == 0) { + + usbd_get_page(pcd, 0, &buf_dev); + + pdctx = buf_dev.buffer; + addr = buf_dev.physaddr; + + hubdev = udev; + temp = XHCI_SCTX_0_CTX_NUM_SET(XHCI_MAX_ENDPOINTS - 1); + + while (hubdev->parent_hub != NULL) { + temp |= (hubdev->port_no & 0xF) << ((hubdev->depth - 1) * 4); + hubdev = hubdev->parent_hub; + } + + rh_port = hubdev->port_no; + + switch (udev->speed) { + case USB_SPEED_LOW: + temp |= XHCI_SCTX_0_SPEED_SET(2); + break; + case USB_SPEED_HIGH: + temp |= XHCI_SCTX_0_SPEED_SET(3); + break; + case USB_SPEED_FULL: + temp |= XHCI_SCTX_0_SPEED_SET(1); + break; + default: + temp |= XHCI_SCTX_0_SPEED_SET(4); + break; + } + + if (udev->hub != NULL) + temp |= XHCI_SCTX_0_HUB_SET(1); + + pdctx->ctx_slot.dwSctx0 = htole32(temp); + + temp = XHCI_SCTX_1_RH_PORT_SET(rh_port); + + if (udev->hub != NULL) + temp |= XHCI_SCTX_1_NUM_PORTS_SET(udev->hub->nports); + + switch (udev->speed) { + case USB_SPEED_LOW: + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + default: + temp |= XHCI_SCTX_1_MAX_EL_SET(sc->sc_exit_lat_max); + break; + } + + pdctx->ctx_slot.dwSctx1 = htole32(temp); + + temp = XHCI_SCTX_2_IRQ_TARGET_SET(0); + + if ((udev->hub != NULL) && + (udev->speed == USB_SPEED_HIGH)) + temp |= XHCI_SCTX_2_TT_THINK_TIME_SET(3); + + hubdev = udev->parent_hs_hub; + + if (hubdev != NULL) { + temp |= XHCI_SCTX_2_TT_HUB_SID_SET(hubdev->device_index); + temp |= XHCI_SCTX_2_TT_PORT_NUM_SET(hubdev->port_no); + } + + pdctx->ctx_slot.dwSctx2 = htole32(temp); + + temp = XHCI_SCTX_3_DEV_ADDR_SET(udev->address) | + XHCI_SCTX_3_SLOT_STATE_SET(3); + + pdctx->ctx_slot.dwSctx3 = htole32(temp); + + } else { + pdctx = NULL; + } + + for (i = 0; i != sc->sc_noscratch; i++) { + + pcs = &sc->sc_hw.devs[index].scratch_pc[i]; + pgs = &sc->sc_hw.devs[index].scratch_pg[i]; + + /* need to initialize the page cache */ + pcs->tag_parent = sc->sc_bus.dma_parent_tag; + + if (usb_pc_alloc_mem(pcs, pgs, XHCI_PAGE_SIZE, XHCI_PAGE_SIZE)) + failure = 1; + + if (failure == 0) { + usbd_get_page(pcs, 0, &buf_scp); + pdctx->ctx_sp_buf_ptr[i] = htole64((uint64_t)buf_scp.physaddr); + } + } + if (failure) + goto error; + + usb_pc_cpu_flush(pcd); + + xhci_set_slot_scratch(sc, udev->device_index, addr, + addr + (uintptr_t)&((struct xhci_dev_ctx *)0)->ctx_sp_buf_ptr[0]); + + return (0); + +error: + xhci_free_device_ext(udev); + + return (USB_ERR_NOMEM); +} + +static void +xhci_free_device_ext(struct usb_device *udev) +{ + struct xhci_softc *sc = XHCI_BUS2SC(udev->bus); + struct usb_page_cache *pcd; + struct usb_page_cache *pcs; + uint8_t index; + uint8_t i; + + index = udev->device_index; + + pcd = &sc->sc_hw.devs[index].device_pc; + + usb_pc_free_mem(pcd); + + for (i = 0; i != sc->sc_noscratch; i++) { + pcs = &sc->sc_hw.devs[index].scratch_pc[i]; + + usb_pc_free_mem(pcs); + } + + xhci_set_slot_scratch(sc, udev->device_index, 0, 0); +} + +static usb_error_t xhci_alloc_endpoint_ext(struct xhci_softc *sc, uint8_t index, struct usb_endpoint_descriptor *edesc) { @@ -1931,13 +2124,6 @@ } break; - case C(UR_SET_HUB_DEPTH, UT_WRITE_CLASS_DEVICE): - if ((index != 0) || (value != 0)) { - err = USB_ERR_IOERROR; - goto done; - } - break; - case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE): if ((value & 0xff) != 0) { err = USB_ERR_IOERROR; ==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#10 (text+ko) ==== @@ -148,7 +148,6 @@ }; struct xhci_dev_ctx { - struct xhci_slot_ctx ctx_input; struct xhci_slot_ctx ctx_slot; struct xhci_endp_ctx ctx_ep0; struct xhci_endp_ctx ctx_epN[XHCI_MAX_ENDPOINTS - 2]; @@ -408,6 +407,7 @@ uint32_t sc_cmd; /* copy of cmd register */ uint32_t sc_cmd_dp; /* copy of command dequeue pointer */ + uint32_t sc_exit_lat_max; /* worst case exit latency */ uint32_t sc_oper_off; /* offset to operational registers */ uint32_t sc_capa_off; /* offset to capability registers */ @@ -423,6 +423,7 @@ uint8_t sc_command_ccs; uint8_t sc_nodev; /* number of devices on root HUB */ uint8_t sc_noport; /* number of ports on root HUB */ + uint8_t sc_noscratch; /* number of scratch pages */ uint8_t sc_addr; /* root HUB device address */ uint8_t sc_conf; /* root HUB device configuration */ uint8_t sc_hub_idata[2]; ==== //depot/projects/usb/src/sys/dev/usb/controller/xhcireg.h#11 (text+ko) ====
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008012121.o71LLVt1059936>