PERFORCE change 181655 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sat Jul 31 18:39:07 UTC 2010
http://p4web.freebsd.org/@@181655?ac=10
Change 181655 by hselasky at 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;
More information about the p4-projects
mailing list