PERFORCE change 181695 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Aug 1 21:21:32 UTC 2010
http://p4web.freebsd.org/@@181695?ac=10
Change 181695 by hselasky at 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) ====
More information about the p4-projects
mailing list