cleaned up

This commit is contained in:
Markus Fröschle
2013-12-15 07:04:54 +00:00
parent 060dcbfed3
commit 0cf42dbbf9
4 changed files with 255 additions and 59 deletions

View File

@@ -30,6 +30,7 @@ static int cc_to_error[16] = {
/* Not Access */ -1 /* Not Access */ -1
}; };
#ifdef DEBUG
static const char *cc_to_string[16] = { static const char *cc_to_string[16] = {
"No Error", "No Error",
"CRC: Last data packet from endpoint contained a CRC error.", "CRC: Last data packet from endpoint contained a CRC error.",
@@ -61,6 +62,7 @@ static const char *cc_to_string[16] = {
"NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \ "NOT ACCESSED:\r\nThis code is set by software before the TD is placed\r\n" \
"on a list to be processed by the HC.(2)", "on a list to be processed by the HC.(2)",
}; };
#endif /* DEBUG */
/* ED States */ /* ED States */

View File

@@ -34,10 +34,11 @@
#undef DEBUG #undef DEBUG
#undef SHOW_INFO #undef SHOW_INFO
char ehci_inited; static char ehci_inited;
static int rootdev; static int rootdev;
static uint16_t portreset, companion; static uint16_t portreset;
static uint16_t companion;
struct descriptor { struct descriptor {
struct usb_hub_descriptor hub; struct usb_hub_descriptor hub;
@@ -49,26 +50,26 @@ struct descriptor {
static struct descriptor rom_descriptor = { static struct descriptor rom_descriptor = {
{ {
0x8, /* bDescLength */ 0x8, /* bDescLength */
0x29, /* bDescriptorType: hub descriptor */ 0x29, /* bDescriptorType: hub descriptor */
2, /* bNrPorts -- runtime modified */ 2, /* bNrPorts -- runtime modified */
0, /* wHubCharacteristics */ 0, /* wHubCharacteristics */
0xff, /* bPwrOn2PwrGood */ 0xff, /* bPwrOn2PwrGood */
0, /* bHubCntrCurrent */ 0, /* bHubCntrCurrent */
{}, /* Device removable */ {}, /* Device removable */
{} /* at most 7 ports! XXX */ {} /* at most 7 ports! XXX */
}, },
{ {
0x12, /* bLength */ 0x12, /* bLength */
1, /* bDescriptorType: UDESC_DEVICE */ 1, /* bDescriptorType: UDESC_DEVICE */
0x0002, /* bcdUSB: v2.0 */ 0x0002, /* bcdUSB: v2.0 */
9, /* bDeviceClass: UDCLASS_HUB */ 9, /* bDeviceClass: UDCLASS_HUB */
0, /* bDeviceSubClass: UDSUBCLASS_HUB */ 0, /* bDeviceSubClass: UDSUBCLASS_HUB */
1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */ 1, /* bDeviceProtocol: UDPROTO_HSHUBSTT */
64, /* bMaxPacketSize: 64 bytes */ 64, /* bMaxPacketSize: 64 bytes */
0x0000, /* idVendor */ 0x0000, /* idVendor */
0x0000, /* idProduct */ 0x0000, /* idProduct */
0x0001, /* bcdDevice */ 0x0001, /* bcdDevice */
1, /* iManufacturer */ 1, /* iManufacturer */
2, /* iProduct */ 2, /* iProduct */
0, /* iSerialNumber */ 0, /* iSerialNumber */
@@ -81,11 +82,11 @@ static struct descriptor rom_descriptor = {
1, /* bNumInterface */ 1, /* bNumInterface */
1, /* bConfigurationValue */ 1, /* bConfigurationValue */
0, /* iConfiguration */ 0, /* iConfiguration */
0x40, /* bmAttributes: UC_SELF_POWER */ 0x40, /* bmAttributes: UC_SELF_POWER */
0 /* bMaxPower */ 0 /* bMaxPower */
}, },
{ {
0x9, /* bLength */ 0x9, /* bLength */
4, /* bDescriptorType: UDESC_INTERFACE */ 4, /* bDescriptorType: UDESC_INTERFACE */
0, /* bInterfaceNumber */ 0, /* bInterfaceNumber */
0, /* bAlternateSetting */ 0, /* bAlternateSetting */
@@ -96,11 +97,11 @@ static struct descriptor rom_descriptor = {
0 /* iInterface */ 0 /* iInterface */
}, },
{ {
0x7, /* bLength */ 0x7, /* bLength */
5, /* bDescriptorType: UDESC_ENDPOINT */ 5, /* bDescriptorType: UDESC_ENDPOINT */
0x81, /* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */ 0x81, /* bEndpointAddress: UE_DIR_IN | EHCI_INTR_ENDPT */
3, /* bmAttributes: UE_INTERRUPT */ 3, /* bmAttributes: UE_INTERRUPT */
8, 0, /* wMaxPacketSize */ 8, 0, /* wMaxPacketSize */
255 /* bInterval */ 255 /* bInterval */
}, },
}; };
@@ -143,7 +144,8 @@ struct pci_device_id ehci_usb_pci_table[] =
} }
}; };
static struct ehci { static struct ehci
{
/* ------- common part -------- */ /* ------- common part -------- */
long handle; /* PCI BIOS */ long handle; /* PCI BIOS */
const struct pci_device_id *ent; const struct pci_device_id *ent;
@@ -195,6 +197,7 @@ static void cache_qh(struct QH *qh, int flush)
struct qTD *qtd; struct qTD *qtd;
struct qTD *next; struct qTD *next;
static struct qTD *first_qtd; static struct qTD *first_qtd;
/* Walk the QH list and flush/invalidate all entries */ /* Walk the QH list and flush/invalidate all entries */
while(1) while(1)
{ {
@@ -205,6 +208,7 @@ static void cache_qh(struct QH *qh, int flush)
qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset); qh = (struct QH *)(swpl(qh->qh_link) + gehci.dma_offset);
} }
qh = qh_addr(qh); qh = qh_addr(qh);
/* Save first qTD pointer, needed for invalidating pass on this QH */ /* Save first qTD pointer, needed for invalidating pass on this QH */
if (flush) if (flush)
{ {
@@ -215,6 +219,7 @@ static void cache_qh(struct QH *qh, int flush)
} }
else else
qtd = first_qtd; qtd = first_qtd;
/* Walk the qTD list and flush/invalidate all entries */ /* Walk the qTD list and flush/invalidate all entries */
while(1) while(1)
{ {
@@ -255,7 +260,7 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
wait(1); wait(1);
usec--; usec--;
} }
while(usec > 0); while (usec > 0);
return -1; return -1;
} }
@@ -269,22 +274,24 @@ static int ehci_reset(void)
uint32_t tmp; uint32_t tmp;
uint32_t *reg_ptr; uint32_t *reg_ptr;
int ret = 0; int ret = 0;
if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC)
&& (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2)) if ((gehci.ent->vendor == PCI_VENDOR_ID_NEC) && (gehci.ent->device == PCI_DEVICE_ID_NEC_USB_2))
{ {
debug("ehci_reset set 48MHz clock\r\n"); debug("ehci_reset set 48MHz clock\r\n");
pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator
} }
cmd = ehci_readl(&gehci.hcor->or_usbcmd); cmd = ehci_readl(&gehci.hcor->or_usbcmd);
debug("cmd: 0x%08x\r\n", cmd); debug("%s cmd: 0x%08x\r\n", __FUNCTION__, cmd);
cmd |= CMD_RESET; cmd |= CMD_RESET;
ehci_writel(&gehci.hcor->or_usbcmd, cmd); ehci_writel(&gehci.hcor->or_usbcmd, cmd);
ret = handshake((uint32_t *)&gehci.hcor->or_usbcmd, CMD_RESET, 0, 250 * 1000); ret = handshake((uint32_t *) &gehci.hcor->or_usbcmd, CMD_RESET, 0, 250);
if (ret < 0) if (ret < 0)
{ {
err("EHCI fail to reset"); err("EHCI fail to reset");
goto out; goto out;
} }
if (ehci_is_TDI()) if (ehci_is_TDI())
{ {
reg_ptr = (uint32_t *)((u8 *)gehci.hcor + USBMODE); reg_ptr = (uint32_t *)((u8 *)gehci.hcor + USBMODE);
@@ -307,6 +314,7 @@ static void *ehci_alloc(size_t sz, size_t align)
p = gehci.qh; p = gehci.qh;
ntds = 0; ntds = 0;
break; break;
case sizeof(struct qTD): case sizeof(struct qTD):
if (ntds == 3) if (ntds == 3)
{ {
@@ -316,6 +324,7 @@ static void *ehci_alloc(size_t sz, size_t align)
p = gehci.td[ntds]; p = gehci.td[ntds];
ntds++; ntds++;
break; break;
default: default:
debug("unknown allocation size\r\n"); debug("unknown allocation size\r\n");
return NULL; return NULL;
@@ -326,11 +335,15 @@ static void *ehci_alloc(size_t sz, size_t align)
static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
{ {
uint32_t addr, delta, next; uint32_t addr;
uint32_t delta;
uint32_t next;
int idx; int idx;
addr = (uint32_t)buf; addr = (uint32_t)buf;
idx = 0; idx = 0;
while(idx < 5)
while (idx < 5)
{ {
td->qt_buffer[idx] = swpl(addr - gehci.dma_offset); td->qt_buffer[idx] = swpl(addr - gehci.dma_offset);
next = (addr + 4096) & ~4095; next = (addr + 4096) & ~4095;
@@ -341,6 +354,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
addr = next; addr = next;
idx++; idx++;
} }
if (idx == 5) if (idx == 5)
{ {
debug("out of buffer pointers (%u bytes left)\r\n", sz); debug("out of buffer pointers (%u bytes left)\r\n", sz);
@@ -360,27 +374,46 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
uint32_t c, toggle; uint32_t c, toggle;
uint32_t cmd; uint32_t cmd;
int ret = 0; int ret = 0;
debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", dev, pipe, buffer, length, req);
debug("%s: dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\r\n", __FUNCTION__, dev, pipe, buffer, length, req);
if (req != NULL) if (req != NULL)
debug("ehci_submit_async req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\r\n", debug("ehci_submit_async req=%u (%#x), type=%u (%#x), value=%u (%#x), index=%u\r\n",
req->request, req->request, req->requesttype, req->requesttype, swpw(req->value), swpw(req->value), swpw(req->index)); req->request, req->request,
req->requesttype, req->requesttype,
swpw(req->value), swpw(req->value), swpw(req->index));
qh = ehci_alloc(sizeof(struct QH), 32); qh = ehci_alloc(sizeof(struct QH), 32);
if (qh == NULL) if (qh == NULL)
{ {
debug("unable to allocate QH\r\n"); debug("unable to allocate QH\r\n");
return -1; return -1;
} }
qh->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH); qh->qh_link = swpl(((uint32_t) gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0; c = (usb_pipespeed(pipe) != USB_SPEED_HIGH && usb_pipeendpoint(pipe) == 0) ? 1 : 0;
endpt = (8 << 28) | (c << 27) | (usb_maxpacket(dev, pipe) << 16) | (0 << 15) | (1 << 14) | (usb_pipespeed(pipe) << 12) | (usb_pipeendpoint(pipe) << 8) | (0 << 7) | (usb_pipedevice(pipe) << 0); endpt = (8 << 28) |
(c << 27) |
(usb_maxpacket(dev, pipe) << 16) |
(0 << 15) |
(1 << 14) |
(usb_pipespeed(pipe) << 12) |
(usb_pipeendpoint(pipe) << 8) |
(0 << 7) |
(usb_pipedevice(pipe) << 0);
qh->qh_endpt1 = swpl(endpt); qh->qh_endpt1 = swpl(endpt);
endpt = (1 << 30) | (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); endpt = (1 << 30) |
(dev->portnr << 23) |
(dev->parent->devnum << 16) |
(0 << 8) |
(0 << 0);
qh->qh_endpt2 = swpl(endpt); qh->qh_endpt2 = swpl(endpt);
qh->qh_overlay.qt_next = swpl(QT_NEXT_TERMINATE); qh->qh_overlay.qt_next = swpl(QT_NEXT_TERMINATE);
qh->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE); qh->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE);
td = NULL; td = NULL;
tdp = &qh->qh_overlay.qt_next; tdp = &qh->qh_overlay.qt_next;
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
if (req != NULL) if (req != NULL)
{ {
td = ehci_alloc(sizeof(struct qTD), 32); td = ehci_alloc(sizeof(struct qTD), 32);
@@ -403,6 +436,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
tdp = &td->qt_next; tdp = &td->qt_next;
toggle = 1; toggle = 1;
} }
if (length > 0 || req == NULL) if (length > 0 || req == NULL)
{ {
td = ehci_alloc(sizeof(struct qTD), 32); td = ehci_alloc(sizeof(struct qTD), 32);
@@ -424,6 +458,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
*tdp = swpl((uint32_t)td - gehci.dma_offset); *tdp = swpl((uint32_t)td - gehci.dma_offset);
tdp = &td->qt_next; tdp = &td->qt_next;
} }
if (req != NULL) if (req != NULL)
{ {
td = ehci_alloc(sizeof(struct qTD), 32); td = ehci_alloc(sizeof(struct qTD), 32);
@@ -439,6 +474,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
*tdp = swpl((uint32_t)td - gehci.dma_offset); *tdp = swpl((uint32_t)td - gehci.dma_offset);
tdp = &td->qt_next; tdp = &td->qt_next;
} }
gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH); gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH);
/* Flush dcache */ /* Flush dcache */
ehci_flush_dcache(gehci.qh_list); ehci_flush_dcache(gehci.qh_list);
@@ -448,6 +484,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
cmd = ehci_readl(&gehci.hcor->or_usbcmd); cmd = ehci_readl(&gehci.hcor->or_usbcmd);
cmd |= CMD_ASE; cmd |= CMD_ASE;
ehci_writel(&gehci.hcor->or_usbcmd, cmd); ehci_writel(&gehci.hcor->or_usbcmd, cmd);
ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000); ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
if (ret < 0) if (ret < 0)
{ {
@@ -479,6 +516,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
goto fail; goto fail;
} }
gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH); gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
token = swpl(qh->qh_overlay.qt_token); token = swpl(qh->qh_overlay.qt_token);
if (!(token & 0x80)) if (!(token & 0x80))
{ {
@@ -490,17 +528,21 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), toggle);
dev->status = 0; dev->status = 0;
break; break;
case 0x40: case 0x40:
dev->status = USB_ST_STALLED; dev->status = USB_ST_STALLED;
break; break;
case 0xa0: case 0xa0:
case 0x20: case 0x20:
dev->status = USB_ST_BUF_ERR; dev->status = USB_ST_BUF_ERR;
break; break;
case 0x50: case 0x50:
case 0x10: case 0x10:
dev->status = USB_ST_BABBLE_DET; dev->status = USB_ST_BABBLE_DET;
break; break;
default: default:
dev->status = USB_ST_CRC_ERR; dev->status = USB_ST_CRC_ERR;
break; break;
@@ -511,11 +553,12 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
{ {
dev->act_len = 0; dev->act_len = 0;
debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\r\n", debug("dev=%u, usbsts=%#x, p[1]=%#x, p[2]=%#x\r\n",
dev->devnum, ehci_readl(&gehci.hcor->or_usbsts), ehci_readl(&gehci.hcor->or_portsc[0]), ehci_readl(&gehci.hcor->or_portsc[1])); dev->devnum, ehci_readl(&gehci.hcor->or_usbsts),
ehci_readl(&gehci.hcor->or_portsc[0]), ehci_readl(&gehci.hcor->or_portsc[1]));
} }
return (dev->status != USB_ST_NOT_PROC) ? 0 : -1; return (dev->status != USB_ST_NOT_PROC) ? 0 : -1;
fail: fail:
td = (void *)swpl(qh->qh_overlay.qt_next); td = (void *) swpl(qh->qh_overlay.qt_next);
if (td != (void *)QT_NEXT_TERMINATE) if (td != (void *)QT_NEXT_TERMINATE)
td = (struct qTD *)(gehci.dma_offset + (uint32_t)td); td = (struct qTD *)(gehci.dma_offset + (uint32_t)td);
while(td != (void *)QT_NEXT_TERMINATE) while(td != (void *)QT_NEXT_TERMINATE)
@@ -530,9 +573,13 @@ fail:
if (ehci_readl(&gehci.hcor->or_usbsts) & STS_HSE) /* Host System Error */ if (ehci_readl(&gehci.hcor->or_usbsts) & STS_HSE) /* Host System Error */
{ {
unsigned short status = pci_read_config_word(gehci.handle, PCISR); unsigned short status = pci_read_config_word(gehci.handle, PCISR);
err("EHCI Host System Error, controller usb-%s disabled\r\n(SR:0x%04X%s%s%s%s%s%s)", gehci.slot_name, status & 0xFFFF, err("EHCI Host System Error, controller usb-%s disabled\r\n(SR:0x%04X%s%s%s%s%s%s)",
status & 0x8000 ? ", Parity error" : "", status & 0x4000 ? ", Signaled system error" : "", status & 0x2000 ? ", Received master abort" : "", gehci.slot_name, status & 0xFFFF, status & 0x8000 ? ", Parity error" : "",
status & 0x1000 ? ", Received target abort" : "", status & 0x800 ? ", Signaled target abort" : "", status & 0x100 ? ", Data parity error" : ""); status & 0x4000 ? ", Signaled system error" : "",
status & 0x2000 ? ", Received master abort" : "",
status & 0x1000 ? ", Received target abort" : "",
status & 0x800 ? ", Signaled target abort" : "",
status & 0x100 ? ", Data parity error" : "");
} }
return -1; return -1;
} }
@@ -574,11 +621,13 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
srcptr = &gehci.descriptor->device; srcptr = &gehci.descriptor->device;
srclen = 0x12; srclen = 0x12;
break; break;
case USB_DT_CONFIG: case USB_DT_CONFIG:
debug("USB_DT_CONFIG config\r\n"); debug("USB_DT_CONFIG config\r\n");
srcptr = &gehci.descriptor->config; srcptr = &gehci.descriptor->config;
srclen = 0x19; srclen = 0x19;
break; break;
case USB_DT_STRING: case USB_DT_STRING:
debug("USB_DT_STRING config\r\n"); debug("USB_DT_STRING config\r\n");
switch(swpw(req->value) & 0xff) switch(swpw(req->value) & 0xff)
@@ -587,14 +636,17 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
srcptr = "\4\3\1\0"; srcptr = "\4\3\1\0";
srclen = 4; srclen = 4;
break; break;
case 1: /* Vendor */ case 1: /* Vendor */
srcptr = "\2\3"; srcptr = "\2\3";
srclen = 2; srclen = 2;
break; break;
case 2: /* Product */ case 2: /* Product */
srcptr = "\34\3E\0H\0C\0I\0 \0R\0o\0o\0t\0 \0H\0u\0b\0"; srcptr = "\34\3E\0H\0C\0I\0 \0R\0o\0o\0t\0 \0H\0u\0b\0";
srclen = 28; srclen = 28;
break; break;
default: default:
debug("unknown value DT_STRING %x\r\n", debug("unknown value DT_STRING %x\r\n",
swpw(req->value)); swpw(req->value));
@@ -606,6 +658,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
goto unknown; goto unknown;
} }
break; break;
case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8): case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 8):
switch(swpw(req->value) >> 8) switch(swpw(req->value) >> 8)
{ {
@@ -614,28 +667,34 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
srcptr = &gehci.descriptor->hub; srcptr = &gehci.descriptor->hub;
srclen = 0x8; srclen = 0x8;
break; break;
default: default:
debug("unknown value %x\r\n", swpw(req->value)); debug("unknown value %x\r\n", swpw(req->value));
goto unknown; goto unknown;
} }
break; break;
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8): case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
debug("USB_REQ_SET_ADDRESS\r\n"); debug("USB_REQ_SET_ADDRESS\r\n");
rootdev = swpw(req->value); rootdev = swpw(req->value);
break; break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
debug("USB_REQ_SET_CONFIGURATION\r\n"); debug("USB_REQ_SET_CONFIGURATION\r\n");
/* Nothing to do */ /* Nothing to do */
break; break;
case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8): case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */ tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */
tmpbuf[1] = 0; tmpbuf[1] = 0;
srcptr = tmpbuf; srcptr = tmpbuf;
srclen = 2; srclen = 2;
break; break;
case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8): case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
memset(tmpbuf, 0, 4); memset(tmpbuf, 0, 4);
reg = ehci_readl(status_reg); reg = ehci_readl(status_reg);
if ((reg & EHCI_PS_PR) && (portreset & (1 << swpw(req->index)))) if ((reg & EHCI_PS_PR) && (portreset & (1 << swpw(req->index))))
{ {
int ret; int ret;
@@ -646,11 +705,12 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
if (!ret) if (!ret)
{ {
tmpbuf[0] |= USB_PORT_STAT_RESET; tmpbuf[0] |= USB_PORT_STAT_RESET;
reg = ehci_readl(status_reg); reg = ehci_readl(status_reg);
} }
else else
err("port(%d) reset error", swpw(req->index) - 1); err("port(%d) reset error", swpw(req->index) - 1);
} }
if (reg & EHCI_PS_CS) if (reg & EHCI_PS_CS)
tmpbuf[0] |= USB_PORT_STAT_CONNECTION; tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
if (reg & EHCI_PS_PE) if (reg & EHCI_PS_PE)
@@ -665,14 +725,22 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
{ {
switch((reg >> 26) & 3) switch((reg >> 26) & 3)
{ {
case 0: break; case 0:
case 1: tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; break; break;
case 1:
tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
break;
case 2: case 2:
default: tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; break; default:
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
break;
} }
} }
else else
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
if (reg & EHCI_PS_CSC) if (reg & EHCI_PS_CSC)
tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
if (reg & EHCI_PS_PEC) if (reg & EHCI_PS_PEC)
@@ -681,9 +749,11 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT; tmpbuf[2] |= USB_PORT_STAT_C_OVERCURRENT;
if (portreset & (1 << swpw(req->index))) if (portreset & (1 << swpw(req->index)))
tmpbuf[2] |= USB_PORT_STAT_C_RESET; tmpbuf[2] |= USB_PORT_STAT_C_RESET;
srcptr = tmpbuf; srcptr = tmpbuf;
srclen = 4; srclen = 4;
break; break;
case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
reg = ehci_readl(status_reg); reg = ehci_readl(status_reg);
reg &= ~EHCI_PS_CLEAR; reg &= ~EHCI_PS_CLEAR;
@@ -693,6 +763,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
reg |= EHCI_PS_PE; reg |= EHCI_PS_PE;
ehci_writel(status_reg, reg); ehci_writel(status_reg, reg);
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams))) if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams)))
{ {
@@ -700,6 +771,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
ehci_writel(status_reg, reg); ehci_writel(status_reg, reg);
} }
break; break;
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && !ehci_is_TDI() && EHCI_PS_IS_LOWSPEED(reg)) if ((reg & (EHCI_PS_PE | EHCI_PS_CS)) == EHCI_PS_CS && !ehci_is_TDI() && EHCI_PS_IS_LOWSPEED(reg))
{ {
@@ -723,13 +795,15 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
portreset |= (1 << swpw(req->index)); portreset |= (1 << swpw(req->index));
} }
break; break;
default: default:
debug("unknown feature %x\r\n", swpw(req->value)); debug("unknown feature %x\r\n", swpw(req->value));
goto unknown; goto unknown;
} }
/* unblock posted writes */ /* unblock posted writes */
(void)ehci_readl(&gehci.hcor->or_usbcmd); (void) ehci_readl(&gehci.hcor->or_usbcmd);
break; break;
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8): case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
reg = ehci_readl(status_reg); reg = ehci_readl(status_reg);
switch(swpw(req->value)) switch(swpw(req->value))
@@ -737,29 +811,35 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
case USB_PORT_FEAT_ENABLE: case USB_PORT_FEAT_ENABLE:
reg &= ~EHCI_PS_PE; reg &= ~EHCI_PS_PE;
break; break;
case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_ENABLE:
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE; reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
break; break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams))) if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams)))
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP); reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_CONNECTION:
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC; reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
break; break;
case USB_PORT_FEAT_OVER_CURRENT: case USB_PORT_FEAT_OVER_CURRENT:
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC; reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
break; break;
case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_RESET:
portreset &= ~(1 << swpw(req->index)); portreset &= ~(1 << swpw(req->index));
break; break;
default: default:
debug("unknown feature %x\r\n", swpw(req->value)); debug("unknown feature %x\r\n", swpw(req->value));
goto unknown; goto unknown;
} }
ehci_writel(status_reg, reg); ehci_writel(status_reg, reg);
/* unblock posted write */ /* unblock posted write */
(void)ehci_readl(&gehci.hcor->or_usbcmd); (void) ehci_readl(&gehci.hcor->or_usbcmd);
break; break;
default: default:
debug("Unknown request\r\n"); debug("Unknown request\r\n");
goto unknown; goto unknown;
@@ -775,7 +855,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
return 0; return 0;
unknown: unknown:
debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\r\n", debug("requesttype=%x, request=%x, value=%x, index=%x, length=%x\r\n",
req->requesttype, req->request, swpw(req->value), swpw(req->index), swpw(req->length)); req->requesttype, req->request, swpw(req->value), swpw(req->index), swpw(req->length));
dev->act_len = 0; dev->act_len = 0;
dev->status = USB_ST_STALLED; dev->status = USB_ST_STALLED;
return -1; return -1;
@@ -797,6 +877,7 @@ static int hc_interrupt(struct ehci *ehci)
i--; i--;
continue; continue;
} }
if (companion & (1 << i)) if (companion & (1 << i))
{ {
/* Low speed device, give up ownership. */ /* Low speed device, give up ownership. */
@@ -806,7 +887,8 @@ static int hc_interrupt(struct ehci *ehci)
i--; i--;
} }
} }
ehci_writel(&ehci->hcor->or_usbsts, status); ehci_writel(&ehci->hcor->or_usbsts, status);
return(1); /* interrupt was from this card */ return(1); /* interrupt was from this card */
} }
@@ -823,11 +905,13 @@ static int handle_usb_interrupt(struct ehci *ehci)
static void hc_free_buffers(struct ehci *ehci) static void hc_free_buffers(struct ehci *ehci)
{ {
int i; int i;
if (ehci->descriptor != NULL) if (ehci->descriptor != NULL)
{ {
usb_free(ehci->descriptor); usb_free(ehci->descriptor);
ehci->descriptor = NULL; ehci->descriptor = NULL;
} }
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
if (ehci->td_unaligned[i] != NULL) if (ehci->td_unaligned[i] != NULL)
@@ -836,11 +920,13 @@ static void hc_free_buffers(struct ehci *ehci)
ehci->td_unaligned[i] = NULL; ehci->td_unaligned[i] = NULL;
} }
} }
if (ehci->qh_unaligned != NULL) if (ehci->qh_unaligned != NULL)
{ {
usb_free(ehci->qh_unaligned); usb_free(ehci->qh_unaligned);
ehci->qh_unaligned = NULL; ehci->qh_unaligned = NULL;
} }
if (ehci->qh_list_unaligned != NULL) if (ehci->qh_list_unaligned != NULL)
{ {
usb_free(ehci->qh_list_unaligned); usb_free(ehci->qh_list_unaligned);
@@ -855,6 +941,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
uint32_t cmd; uint32_t cmd;
uint32_t usb_base_addr = 0xFFFFFFFF; uint32_t usb_base_addr = 0xFFFFFFFF;
struct pci_rd *pci_rsc_desc; struct pci_rd *pci_rsc_desc;
pci_rsc_desc = pci_get_resource(handle); /* USB EHCI */ pci_rsc_desc = pci_get_resource(handle); /* USB EHCI */
if (handle && (ent != NULL)) if (handle && (ent != NULL))
{ {
@@ -864,6 +951,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
} }
else if (!gehci.handle) /* for restart USB cmd */ else if (!gehci.handle) /* for restart USB cmd */
return(-1); return(-1);
gehci.qh_list_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32); gehci.qh_list_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
if (gehci.qh_list_unaligned == NULL) if (gehci.qh_list_unaligned == NULL)
{ {
@@ -871,9 +959,11 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
hc_free_buffers(&gehci); hc_free_buffers(&gehci);
return(-1); return(-1);
} }
gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31); gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31);
memset(gehci.qh_list, 0, sizeof(struct QH)); memset(gehci.qh_list, 0, sizeof(struct QH));
gehci.qh_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32); gehci.qh_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
if (gehci.qh_unaligned == NULL) if (gehci.qh_unaligned == NULL)
{ {
debug("QHs malloc failed"); debug("QHs malloc failed");
@@ -882,6 +972,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
} }
gehci.qh = (struct QH *)(((uint32_t)gehci.qh_unaligned + 31) & ~31); gehci.qh = (struct QH *)(((uint32_t)gehci.qh_unaligned + 31) & ~31);
memset(gehci.qh, 0, sizeof(struct QH)); memset(gehci.qh, 0, sizeof(struct QH));
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
{ {
gehci.td_unaligned[i] = (struct qTD *)usb_malloc(sizeof(struct qTD) + 32); gehci.td_unaligned[i] = (struct qTD *)usb_malloc(sizeof(struct qTD) + 32);
@@ -894,6 +985,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
gehci.td[i] = (struct qTD *)(((uint32_t)gehci.td_unaligned[i] + 31) & ~31); gehci.td[i] = (struct qTD *)(((uint32_t)gehci.td_unaligned[i] + 31) & ~31);
memset(gehci.td[i], 0, sizeof(struct qTD)); memset(gehci.td[i], 0, sizeof(struct qTD));
} }
gehci.descriptor = (struct descriptor *)usb_malloc(sizeof(struct descriptor)); gehci.descriptor = (struct descriptor *)usb_malloc(sizeof(struct descriptor));
if (gehci.descriptor == NULL) if (gehci.descriptor == NULL)
{ {
@@ -902,6 +994,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
return(-1); return(-1);
} }
memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor)); memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor));
if ((long) pci_rsc_desc >= 0) if ((long) pci_rsc_desc >= 0)
{ {
unsigned short flags; unsigned short flags;
@@ -925,18 +1018,20 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
flags = pci_rsc_desc->flags; flags = pci_rsc_desc->flags;
pci_rsc_desc = (struct pci_rd *)((uint32_t)pci_rsc_desc->next + (uint32_t)pci_rsc_desc); pci_rsc_desc = (struct pci_rd *)((uint32_t)pci_rsc_desc->next + (uint32_t)pci_rsc_desc);
} }
while(!(flags & FLG_LAST)); while (!(flags & FLG_LAST));
} }
else else
{ {
hc_free_buffers(&gehci); hc_free_buffers(&gehci);
return(-1); /* get_resource error */ return(-1); /* get_resource error */
} }
if (usb_base_addr == 0xFFFFFFFF) if (usb_base_addr == 0xFFFFFFFF)
{ {
hc_free_buffers(&gehci); hc_free_buffers(&gehci);
return(-1); return(-1);
} }
if (handle && (ent != NULL)) if (handle && (ent != NULL))
{ {
switch(ent->vendor) switch(ent->vendor)
@@ -955,6 +1050,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
hc_free_buffers(&gehci); hc_free_buffers(&gehci);
return(-1); return(-1);
} }
/* Set head of reclaim list */ /* Set head of reclaim list */
gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH); gehci.qh_list->qh_link = swpl(((uint32_t)gehci.qh_list - gehci.dma_offset) | QH_LINK_TYPE_QH);
gehci.qh_list->qh_endpt1 = swpl((1 << 15) | (USB_SPEED_HIGH << 12)); gehci.qh_list->qh_endpt1 = swpl((1 << 15) | (USB_SPEED_HIGH << 12));
@@ -967,6 +1063,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
reg = ehci_readl(&gehci.hccr->cr_hcsparams); reg = ehci_readl(&gehci.hccr->cr_hcsparams);
gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg); gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg);
info("Register %x NbrPorts %d", reg, gehci.descriptor->hub.bNbrPorts); info("Register %x NbrPorts %d", reg, gehci.descriptor->hub.bNbrPorts);
/* Port Indicators */ /* Port Indicators */
if (HCS_INDICATOR(reg)) if (HCS_INDICATOR(reg))
gehci.descriptor->hub.wHubCharacteristics |= 0x80; gehci.descriptor->hub.wHubCharacteristics |= 0x80;
@@ -1002,19 +1099,24 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
int ehci_usb_lowlevel_stop(void *priv) int ehci_usb_lowlevel_stop(void *priv)
{ {
uint32_t cmd; uint32_t cmd;
if (priv); if (priv);
if (!ehci_inited) if (!ehci_inited)
return(0); return(0);
/* turn off interrupts */
/* turn off interrupts */
ehci_writel(&gehci.hcor->or_usbintr, 0); ehci_writel(&gehci.hcor->or_usbintr, 0);
pci_unhook_interrupt(gehci.handle); pci_unhook_interrupt(gehci.handle);
/* stop the controller */ /* stop the controller */
cmd = ehci_readl(&gehci.hcor->or_usbcmd); cmd = ehci_readl(&gehci.hcor->or_usbcmd);
cmd &= ~CMD_RUN; cmd &= ~CMD_RUN;
ehci_writel(&gehci.hcor->or_usbcmd, cmd); ehci_writel(&gehci.hcor->or_usbcmd, cmd);
/* turn off all ports => todo */ /* turn off all ports => todo */
/* use the companions */ /* use the companions */
ehci_writel(&gehci.hcor->or_configflag, 0); ehci_writel(&gehci.hcor->or_configflag, 0);
/* unblock posted write */ /* unblock posted write */
cmd = ehci_readl(&gehci.hcor->or_usbcmd); cmd = ehci_readl(&gehci.hcor->or_usbcmd);
ehci_reset(); ehci_reset();
@@ -1040,6 +1142,7 @@ int ehci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
debug("non-control pipe (type=%lu)", usb_pipetype(pipe)); debug("non-control pipe (type=%lu)", usb_pipetype(pipe));
return -1; return -1;
} }
if (usb_pipedevice(pipe) == rootdev) if (usb_pipedevice(pipe) == rootdev)
{ {
if (rootdev == 0) if (rootdev == 0)

View File

@@ -187,7 +187,9 @@ static struct td *td_alloc(struct usb_device *usb_dev)
{ {
int i; int i;
struct td *td; struct td *td;
td = NULL; td = NULL;
for (i = 0; i < NUM_TD; i++) for (i = 0; i < NUM_TD; i++)
{ {
if (ptd[i].usb_dev == NULL) if (ptd[i].usb_dev == NULL)
@@ -211,6 +213,7 @@ static void urb_free_priv(urb_priv_t *urb)
int i; int i;
struct td *td; struct td *td;
int last = urb->length - 1; int last = urb->length - 1;
if (last >= 0) if (last >= 0)
{ {
for (i = 0; i <= last; i++) for (i = 0; i <= last; i++)
@@ -252,7 +255,9 @@ static void pkt_print(ohci_t *ohci, urb_priv_t *purb, struct usb_device *dev,
#ifdef OHCI_VERBOSE_DEBUG #ifdef OHCI_VERBOSE_DEBUG
if (!small) if (!small)
{ {
int i, len; int i;
int len;
if (usb_pipecontrol(pipe)) if (usb_pipecontrol(pipe))
{ {
debug_printf(__FILE__ ": cmd(8):"); debug_printf(__FILE__ ": cmd(8):");
@@ -260,10 +265,12 @@ static void pkt_print(ohci_t *ohci, urb_priv_t *purb, struct usb_device *dev,
debug_printf(" %02x", ((uint8_t *)setup)[i]); debug_printf(" %02x", ((uint8_t *)setup)[i]);
debug_printf("\r\n"); debug_printf("\r\n");
} }
if (transfer_len > 0 && buffer) if (transfer_len > 0 && buffer)
{ {
debug_printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len); debug_printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len);
len = usb_pipeout(pipe)? transfer_len : (purb ? purb->actual_length : 0); len = usb_pipeout(pipe)? transfer_len : (purb ? purb->actual_length : 0);
for (i = 0; i < 16 && i < len; i++) for (i = 0; i < 16 && i < len; i++)
debug_printf(" %02x", ((uint8_t *)buffer)[i]); debug_printf(" %02x", ((uint8_t *)buffer)[i]);
debug_printf("%s\r\n", i < len? "...": ""); debug_printf("%s\r\n", i < len? "...": "");
@@ -278,12 +285,14 @@ static void ep_print_int_eds(ohci_t *ohci, char *str)
{ {
int i, j; int i, j;
uint32_t *ed_p; uint32_t *ed_p;
for (i = 0; i < 32; i++) for (i = 0; i < 32; i++)
{ {
j = 5; j = 5;
ed_p = &(ohci->hcca->int_table[i]); ed_p = &(ohci->hcca->int_table[i]);
if (*ed_p == 0) if (*ed_p == 0)
continue; continue;
debug_printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i); debug_printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i);
while (*ed_p != 0 && j--) while (*ed_p != 0 && j--)
{ {
@@ -315,8 +324,11 @@ static void ohci_dump_intr_mask(char *label, uint32_t mask)
static void maybe_print_eds(ohci_t *controller, char *label, uint32_t value) static void maybe_print_eds(ohci_t *controller, char *label, uint32_t value)
{ {
ed_t *edp; ed_t *edp;
value += controller->dma_offset; value += controller->dma_offset;
edp = (ed_t *)value; edp = (ed_t *) value;
(void) edp;
if (value && (value < 0xDFFFF0)) /* STRAM */ if (value && (value < 0xDFFFF0)) /* STRAM */
{ {
dbg("%s %08x", label, value); dbg("%s %08x", label, value);
@@ -327,6 +339,7 @@ static void maybe_print_eds(ohci_t *controller, char *label, uint32_t value)
} }
} }
#ifdef DEBUG
static char *hcfs2string(int state) static char *hcfs2string(int state)
{ {
switch (state) switch (state)
@@ -338,6 +351,7 @@ static char *hcfs2string(int state)
} }
return "?"; return "?";
} }
#endif
/* dump control and status registers */ /* dump control and status registers */
static void ohci_dump_status(ohci_t *controller) static void ohci_dump_status(ohci_t *controller)
@@ -378,8 +392,13 @@ static void ohci_dump_status(ohci_t *controller)
static void ohci_dump_roothub(ohci_t *controller, int verbose) static void ohci_dump_roothub(ohci_t *controller, int verbose)
{ {
uint32_t temp, ndp, i; uint32_t temp;
uint32_t ndp;
uint32_t i;
temp = roothub_a(controller); temp = roothub_a(controller);
(void) temp;
// ndp = (temp & RH_A_NDP); // ndp = (temp & RH_A_NDP);
ndp = controller->ndp; ndp = controller->ndp;
if (verbose) if (verbose)
@@ -410,6 +429,7 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose)
(temp & RH_HS_LPS) ? " LPS" : "" (temp & RH_HS_LPS) ? " LPS" : ""
); );
} }
for (i = 0; i < ndp; i++) for (i = 0; i < ndp; i++)
{ {
temp = roothub_portstatus(controller, i); temp = roothub_portstatus(controller, i);
@@ -456,12 +476,14 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
{ {
ed_t *ed; ed_t *ed;
urb_priv_t *purb_priv = urb; urb_priv_t *purb_priv = urb;
int i, size = 0; int i;
int size = 0;
struct usb_device *dev = urb->dev; struct usb_device *dev = urb->dev;
uint32_t pipe = urb->pipe; uint32_t pipe = urb->pipe;
void *buffer = urb->transfer_buffer; void *buffer = urb->transfer_buffer;
int transfer_len = urb->transfer_buffer_length; int transfer_len = urb->transfer_buffer_length;
int interval = urb->interval; int interval = urb->interval;
/* when controller's hung, permit only roothub cleanup attempts /* when controller's hung, permit only roothub cleanup attempts
* such as powering down ports */ * such as powering down ports */
if (ohci->disabled) if (ohci->disabled)
@@ -473,6 +495,7 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
/* we're about to begin a new transaction here so mark the /* we're about to begin a new transaction here so mark the
* URB unfinished */ * URB unfinished */
urb->finished = 0; urb->finished = 0;
/* every endpoint has a ed, locate and fill it */ /* every endpoint has a ed, locate and fill it */
ed = ep_add_ed(ohci, dev, pipe, interval, 1); ed = ep_add_ed(ohci, dev, pipe, interval, 1);
if (!ed) if (!ed)
@@ -481,6 +504,7 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
err("sohci_submit_job: ENOMEM"); err("sohci_submit_job: ENOMEM");
return -1; return -1;
} }
/* for the private part of the URB we need the number of TDs (size) */ /* for the private part of the URB we need the number of TDs (size) */
switch (usb_pipetype(pipe)) switch (usb_pipetype(pipe))
{ {
@@ -521,12 +545,14 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
return -1; return -1;
} }
} }
if (ed->state == ED_NEW || (ed->state & ED_DEL)) if (ed->state == ED_NEW || (ed->state & ED_DEL))
{ {
urb_free_priv(purb_priv); urb_free_priv(purb_priv);
err("sohci_submit_job: EINVAL"); err("sohci_submit_job: EINVAL");
return -1; return -1;
} }
/* link the ed into a chain if is not already */ /* link the ed into a chain if is not already */
if (ed->state != ED_OPER) if (ed->state != ED_OPER)
ep_link(ohci, ed); ep_link(ohci, ed);
@@ -539,6 +565,7 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb) static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb)
{ {
struct ohci_regs *regs = ohci->regs; struct ohci_regs *regs = ohci->regs;
switch (usb_pipetype(urb->pipe)) switch (usb_pipetype(urb->pipe))
{ {
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
@@ -556,9 +583,11 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb)
urb->actual_length = 0; urb->actual_length = 0;
td_submit_job(ohci, urb->dev, urb->pipe, urb->transfer_buffer, urb->transfer_buffer_length, NULL, urb, urb->interval); td_submit_job(ohci, urb->dev, urb->pipe, urb->transfer_buffer, urb->transfer_buffer_length, NULL, urb, urb->interval);
break; break;
case PIPE_CONTROL: case PIPE_CONTROL:
case PIPE_BULK: case PIPE_BULK:
break; break;
default: default:
return 0; return 0;
} }
@@ -609,6 +638,7 @@ static int ep_int_ballance(ohci_t *ohci, int interval, int load)
static int ep_2_n_interval(int inter) static int ep_2_n_interval(int inter)
{ {
int i; int i;
for (i = 0; ((inter >> i) > 1) && (i < 5); i++); for (i = 0; ((inter >> i) > 1) && (i < 5); i++);
return 1 << i; return 1 << i;
} }
@@ -620,7 +650,9 @@ static int ep_2_n_interval(int inter)
* be mapped the mapping reverses the bits of a word of num_bits length */ * be mapped the mapping reverses the bits of a word of num_bits length */
static int ep_rev(int num_bits, int word) static int ep_rev(int num_bits, int word)
{ {
int i, wout = 0; int i;
int wout = 0;
for (i = 0; i < num_bits; i++) for (i = 0; i < num_bits; i++)
wout |= (((word >> i) & 1) << (num_bits - i - 1)); wout |= (((word >> i) & 1) << (num_bits - i - 1));
return wout; return wout;
@@ -641,6 +673,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
int interval; int interval;
int load; int load;
uint32_t *ed_p; uint32_t *ed_p;
ed->state = ED_OPER; ed->state = ED_OPER;
ed->int_interval = 0; ed->int_interval = 0;
switch (ed->type) switch (ed->type)
@@ -660,6 +693,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
} }
ohci->ed_controltail = edi; ohci->ed_controltail = edi;
break; break;
case PIPE_BULK: case PIPE_BULK:
ed->hwNextED = 0; ed->hwNextED = 0;
if (ohci->ed_bulktail == NULL) if (ohci->ed_bulktail == NULL)
@@ -674,6 +708,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
} }
ohci->ed_bulktail = edi; ohci->ed_bulktail = edi;
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
load = ed->int_load; load = ed->int_load;
interval = ep_2_n_interval(ed->int_period); interval = ep_2_n_interval(ed->int_period);
@@ -702,7 +737,8 @@ static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, unsigned
{ {
for ( ;index < NUM_INTS; index += period) for ( ;index < NUM_INTS; index += period)
{ {
uint32_t *ed_p = &ohci->hcca->int_table[index]; uint32_t *ed_p = &ohci->hcca->int_table[index];
/* ED might have been unlinked through another path */ /* ED might have been unlinked through another path */
while (*ed_p != 0) while (*ed_p != 0)
{ {
@@ -725,6 +761,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
{ {
volatile ed_t *ed = edi; volatile ed_t *ed = edi;
int i; int i;
ed->hwINFO |= swpl(OHCI_ED_SKIP); ed->hwINFO |= swpl(OHCI_ED_SKIP);
switch (ed->type) switch (ed->type)
{ {
@@ -745,6 +782,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
else else
((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev; ((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev;
break; break;
case PIPE_BULK: case PIPE_BULK:
if (ed->ed_prev == NULL) if (ed->ed_prev == NULL)
{ {
@@ -762,6 +800,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
else else
((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev; ((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev;
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
periodic_unlink(ohci, ed, 0, 1); periodic_unlink(ohci, ed, 0, 1);
for (i = ed->int_branch; i < 32; i += ed->int_interval) for (i = ed->int_branch; i < 32; i += ed->int_interval)
@@ -788,6 +827,7 @@ static ed_t *ep_add_ed(ohci_t *ohci, struct usb_device *usb_dev, uint32_t pipe,
ed_t *ed_ret; ed_t *ed_ret;
volatile ed_t *ed; volatile ed_t *ed;
struct ohci_device *ohci_dev = ohci->ohci_dev; struct ohci_device *ohci_dev = ohci->ohci_dev;
ed = ed_ret = &ohci_dev->ed[(usb_pipeendpoint(pipe) << 1) | (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))]; ed = ed_ret = &ohci_dev->ed[(usb_pipeendpoint(pipe) << 1) | (usb_pipecontrol(pipe)? 0: usb_pipeout(pipe))];
if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL))
{ {
@@ -795,6 +835,7 @@ static ed_t *ep_add_ed(ohci_t *ohci, struct usb_device *usb_dev, uint32_t pipe,
/* pending delete request */ /* pending delete request */
return NULL; return NULL;
} }
if (ed->state == ED_NEW) if (ed->state == ED_NEW)
{ {
/* dummy td; end of td list for ed */ /* dummy td; end of td list for ed */
@@ -805,12 +846,14 @@ static ed_t *ep_add_ed(ohci_t *ohci, struct usb_device *usb_dev, uint32_t pipe,
ed->type = usb_pipetype(pipe); ed->type = usb_pipetype(pipe);
ohci_dev->ed_cnt++; ohci_dev->ed_cnt++;
} }
ed->hwINFO = swpl(usb_pipedevice(pipe) ed->hwINFO = swpl(usb_pipedevice(pipe)
| usb_pipeendpoint(pipe) << 7 | usb_pipeendpoint(pipe) << 7
| (usb_pipeisoc(pipe)? 0x8000: 0) | (usb_pipeisoc(pipe)? 0x8000: 0)
| (usb_pipecontrol(pipe)? 0: (usb_pipeout(pipe)? 0x800: 0x1000)) | (usb_pipecontrol(pipe)? 0: (usb_pipeout(pipe)? 0x800: 0x1000))
| usb_pipeslow(pipe) << 13 | usb_pipeslow(pipe) << 13
| usb_maxpacket(usb_dev, pipe) << 16); | usb_maxpacket(usb_dev, pipe) << 16);
if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK)
{ {
ed->int_period = interval; ed->int_period = interval;
@@ -826,9 +869,11 @@ static ed_t *ep_add_ed(ohci_t *ohci, struct usb_device *usb_dev, uint32_t pipe,
/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ /* enqueue next TD for this URB (OHCI spec 5.2.8.2) */
static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len, static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len,
struct usb_device *dev, int index, urb_priv_t *urb_priv) struct usb_device *dev, int index, urb_priv_t *urb_priv)
{ {
volatile td_t *td, *td_pt; volatile td_t *td;
volatile td_t *td_pt;
#ifdef OHCI_FILL_TRACE #ifdef OHCI_FILL_TRACE
int i; int i;
#endif #endif
@@ -840,6 +885,7 @@ static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len,
/* use this td as the next dummy */ /* use this td as the next dummy */
td_pt = urb_priv->td[index]; td_pt = urb_priv->td[index];
td_pt->hwNextTD = 0; td_pt->hwNextTD = 0;
/* fill the old dummy TD */ /* fill the old dummy TD */
td = urb_priv->td[index] = (td_t *)((swpl(urb_priv->ed->hwTailP) & ~0xf) + ohci->dma_offset); td = urb_priv->td[index] = (td_t *)((swpl(urb_priv->ed->hwTailP) & ~0xf) + ohci->dma_offset);
td->ed = urb_priv->ed; td->ed = urb_priv->ed;
@@ -870,6 +916,7 @@ static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len,
td->hwNextTD = swpl((uint32_t)td_pt - ohci->dma_offset); td->hwNextTD = swpl((uint32_t)td_pt - ohci->dma_offset);
/* append to queue */ /* append to queue */
td->ed->hwTailP = td->hwNextTD; td->ed->hwTailP = td->hwNextTD;
#if 0 #if 0
if (data) if (data)
{ {
@@ -891,13 +938,15 @@ static void td_fill(ohci_t *ohci, unsigned int info, void *data, int len,
/* prepare all TDs of a transfer */ /* prepare all TDs of a transfer */
static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
void *buffer, int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) void *buffer, int transfer_len, struct devrequest *setup,
urb_priv_t *urb, int interval)
{ {
int data_len = transfer_len; int data_len = transfer_len;
void *data; void *data;
int cnt = 0; int cnt = 0;
uint32_t info = 0; uint32_t info = 0;
unsigned int toggle = 0; unsigned int toggle = 0;
/* OHCI handles the DATA-toggles itself, we just use the USB-toggle /* OHCI handles the DATA-toggles itself, we just use the USB-toggle
* bits for reseting */ * bits for reseting */
if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)))
@@ -907,11 +956,13 @@ static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
toggle = TD_T_DATA0; toggle = TD_T_DATA0;
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
} }
urb->td_cnt = 0; urb->td_cnt = 0;
if (data_len) if (data_len)
data = buffer; data = buffer;
else else
data = NULL; data = NULL;
switch (usb_pipetype(pipe)) switch (usb_pipetype(pipe))
{ {
case PIPE_BULK: case PIPE_BULK:
@@ -927,6 +978,7 @@ static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
if (!ohci->sleeping) /* start bulk list */ if (!ohci->sleeping) /* start bulk list */
writel(OHCI_BLF, &ohci->regs->cmdstatus); writel(OHCI_BLF, &ohci->regs->cmdstatus);
break; break;
case PIPE_CONTROL: case PIPE_CONTROL:
/* Setup phase */ /* Setup phase */
info = TD_CC | TD_DP_SETUP | TD_T_DATA0; info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
@@ -944,6 +996,7 @@ static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
if (!ohci->sleeping) /* start Control list */ if (!ohci->sleeping) /* start Control list */
writel(OHCI_CLF, &ohci->regs->cmdstatus); writel(OHCI_CLF, &ohci->regs->cmdstatus);
break; break;
case PIPE_INTERRUPT: case PIPE_INTERRUPT:
info = usb_pipeout(urb->pipe) ? TD_CC | TD_DP_OUT | toggle : TD_CC | TD_R | TD_DP_IN | toggle; info = usb_pipeout(urb->pipe) ? TD_CC | TD_DP_OUT | toggle : TD_CC | TD_R | TD_DP_IN | toggle;
td_fill(ohci, info, data, data_len, dev, cnt++, urb); td_fill(ohci, info, data, data_len, dev, cnt++, urb);
@@ -961,15 +1014,19 @@ static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
static void dl_transfer_length(ohci_t *ohci, td_t *td) static void dl_transfer_length(ohci_t *ohci, td_t *td)
{ {
uint32_t tdBE, tdCBP; uint32_t tdBE;
uint32_t tdCBP;
urb_priv_t *lurb_priv = td->ed->purb; urb_priv_t *lurb_priv = td->ed->purb;
tdBE = swpl(td->hwBE); tdBE = swpl(td->hwBE);
tdCBP = swpl(td->hwCBP); tdCBP = swpl(td->hwCBP);
if (tdBE) if (tdBE)
tdBE += ohci->dma_offset; tdBE += ohci->dma_offset;
if (tdCBP) if (tdCBP)
tdCBP += ohci->dma_offset; tdCBP += ohci->dma_offset;
if (!(usb_pipecontrol(lurb_priv->pipe) && ((td->index == 0) || (td->index == lurb_priv->length - 1)))) if (!(usb_pipecontrol(lurb_priv->pipe) && ((td->index == 0) || (td->index == lurb_priv->length - 1))))
{ {
if (tdBE != 0) if (tdBE != 0)
@@ -989,6 +1046,7 @@ static void check_status(ohci_t *ohci, td_t *td_list)
int urb_len = lurb_priv->length; int urb_len = lurb_priv->length;
uint32_t *phwHeadP = &td_list->ed->hwHeadP; uint32_t *phwHeadP = &td_list->ed->hwHeadP;
int cc = TD_CC_GET(swpl(td_list->hwINFO)); int cc = TD_CC_GET(swpl(td_list->hwINFO));
if (cc) if (cc)
{ {
err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc);
@@ -1015,6 +1073,7 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
uint32_t td_list_hc; uint32_t td_list_hc;
td_t *td_rev = NULL; td_t *td_rev = NULL;
td_t *td_list = NULL; td_t *td_list = NULL;
td_list_hc = swpl(ohci->hcca->done_head) & ~0xf; td_list_hc = swpl(ohci->hcca->done_head) & ~0xf;
if (td_list_hc) if (td_list_hc)
td_list_hc += ohci->dma_offset; td_list_hc += ohci->dma_offset;
@@ -1032,7 +1091,6 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
return td_list; return td_list;
} }
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status) static void finish_urb(ohci_t *ohci, urb_priv_t *urb, int status)
@@ -1067,6 +1125,7 @@ static int takeback_td(ohci_t *ohci, td_t *td_list)
lurb_priv = ed->purb; lurb_priv = ed->purb;
dl_transfer_length(ohci, td_list); dl_transfer_length(ohci, td_list);
lurb_priv->td_cnt++; lurb_priv->td_cnt++;
/* error code of transfer */ /* error code of transfer */
cc = TD_CC_GET(tdINFO); cc = TD_CC_GET(tdINFO);
if (cc) if (cc)
@@ -1074,6 +1133,7 @@ static int takeback_td(ohci_t *ohci, td_t *td_list)
err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc); err("OHCI usb-%s-%c error: %s (%x)", ohci->slot_name, (char)ohci->controller + '0', cc_to_string[cc], cc);
stat = cc_to_error[cc]; stat = cc_to_error[cc];
} }
/* see if this done list makes for all TD's of current URB, /* see if this done list makes for all TD's of current URB,
* and mark the URB finished if so */ * and mark the URB finished if so */
if (lurb_priv->td_cnt == lurb_priv->length) if (lurb_priv->td_cnt == lurb_priv->length)
@@ -1252,7 +1312,7 @@ int rh_check_port_status(ohci_t *controller)
} }
static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
void *buffer, int transfer_len, struct devrequest *cmd) void *buffer, int transfer_len, struct devrequest *cmd)
{ {
void *data = buffer; void *data = buffer;
int leni = transfer_len; int leni = transfer_len;
@@ -1264,6 +1324,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
uint16_t wValue; uint16_t wValue;
uint16_t wIndex; uint16_t wIndex;
uint16_t wLength; uint16_t wLength;
#ifdef DEBUG #ifdef DEBUG
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
#else #else
@@ -1280,6 +1341,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
wIndex = swpw(cmd->index); wIndex = swpw(cmd->index);
wLength = swpw(cmd->length); wLength = swpw(cmd->length);
info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
switch (bmRType_bReq) switch (bmRType_bReq)
{ {
/* Request Destination: /* Request Destination:
@@ -1442,12 +1504,13 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
/* common code for handling submit messages - used for all but root hub accesses. */ /* common code for handling submit messages - used for all but root hub accesses. */
static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, void *buffer, static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe, void *buffer,
int transfer_len, struct devrequest *setup, int interval) int transfer_len, struct devrequest *setup, int interval)
{ {
int stat = 0; int stat = 0;
int maxsize = usb_maxpacket(dev, pipe); int maxsize = usb_maxpacket(dev, pipe);
int timeout; int timeout;
urb_priv_t *urb = (urb_priv_t *) usb_malloc(sizeof(urb_priv_t)); urb_priv_t *urb = (urb_priv_t *) usb_malloc(sizeof(urb_priv_t));
if (urb == NULL) if (urb == NULL)
{ {
err("submit_common_msg malloc failed"); err("submit_common_msg malloc failed");
@@ -1473,26 +1536,31 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
if (ohci->irq) if (ohci->irq)
wait(1 * 1000); wait(1 * 1000);
#endif #endif
if (!maxsize) if (!maxsize)
{ {
err("submit_common_message: pipesize for pipe %lx is zero", pipe); err("submit_common_message: pipesize for pipe %lx is zero", pipe);
return -1; return -1;
} }
if (sohci_submit_job(ohci, urb, setup) < 0) if (sohci_submit_job(ohci, urb, setup) < 0)
{ {
err("sohci_submit_job failed"); err("sohci_submit_job failed");
return -1; return -1;
} }
#if 0 #if 0
wait(10 * 1000); wait(10 * 1000);
/* ohci_dump_status(ohci); */ /* ohci_dump_status(ohci); */
#endif #endif
/* allow more time for a BULK device to react - some are slow */ /* allow more time for a BULK device to react - some are slow */
#define BULK_TO 5000 /* timeout in milliseconds */ #define BULK_TO 5000 /* timeout in milliseconds */
if (usb_pipebulk(pipe)) if (usb_pipebulk(pipe))
timeout = BULK_TO; timeout = BULK_TO;
else else
timeout = 1000; timeout = 1000;
/* wait for it to complete */ /* wait for it to complete */
while (ohci->irq) while (ohci->irq)
{ {
@@ -1523,6 +1591,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
/* 0xff is returned for an SF-interrupt */ /* 0xff is returned for an SF-interrupt */
break; break;
} }
if (--timeout) if (--timeout)
{ {
wait(1 * 1000); wait(1 * 1000);
@@ -1570,11 +1639,13 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
if (ohci->irq) if (ohci->irq)
wait(1 * 1000); wait(1 * 1000);
#endif #endif
if (!maxsize) if (!maxsize)
{ {
err("submit_control_message: pipesize for pipe %lx is zero", pipe); err("submit_control_message: pipesize for pipe %lx is zero", pipe);
return -1; return -1;
} }
if (((pipe >> 8) & 0x7f) == ohci->rh.devnum) if (((pipe >> 8) & 0x7f) == ohci->rh.devnum)
{ {
ohci->rh.dev = dev; ohci->rh.dev = dev;
@@ -1600,6 +1671,7 @@ static int hc_reset(ohci_t *ohci)
{ {
int timeout = 30; int timeout = 30;
int smm_timeout = 50; /* 0,5 sec */ int smm_timeout = 50; /* 0,5 sec */
dbg("%s\r\n", __FUNCTION__); dbg("%s\r\n", __FUNCTION__);
if ((ohci->ent->vendor == PCI_VENDOR_ID_PHILIPS) if ((ohci->ent->vendor == PCI_VENDOR_ID_PHILIPS)
@@ -1611,6 +1683,7 @@ static int hc_reset(ohci_t *ohci)
resetting via EHCI registers only. */ resetting via EHCI registers only. */
short index = 0; short index = 0;
long handle; long handle;
do do
{ {
handle = pci_find_device(0x0, 0xffff, index++); handle = pci_find_device(0x0, 0xffff, index++);
@@ -1754,7 +1827,7 @@ static int hc_start(ohci_t *ohci)
writel(RH_HS_LPSC, &ohci->regs->roothub.status); writel(RH_HS_LPSC, &ohci->regs->roothub.status);
#endif /* OHCI_USE_NPS */ #endif /* OHCI_USE_NPS */
/* POTPGT delay is bits 24-31, in 2 ms units. */ /* POTPGT delay is bits 24-31, in 2 ms units. */
wait((ohci->ndp >> 23) & 0x1fe * 1000); wait((ohci->ndp >> 23) & 0x1fe);
ohci->ndp &= RH_A_NDP; ohci->ndp &= RH_A_NDP;
/* connect the virtual root hub */ /* connect the virtual root hub */
ohci->rh.devnum = 0; ohci->rh.devnum = 0;
@@ -1801,6 +1874,7 @@ static int hc_interrupt(ohci_t *ohci)
{ {
struct ohci_regs *regs = ohci->regs; struct ohci_regs *regs = ohci->regs;
int ints, stat = -1; int ints, stat = -1;
if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01)) if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01))
ints = OHCI_INTR_WDH; ints = OHCI_INTR_WDH;
else else
@@ -1822,8 +1896,10 @@ static int hc_interrupt(ohci_t *ohci)
} }
} }
} }
if (ohci->irq) if (ohci->irq)
dbg("Interrupt: 0x%x frame: 0x%x bus: %d", ints, swpw(ohci->hcca->frame_no), ohci->controller); dbg("Interrupt: 0x%x frame: 0x%x bus: %d", ints, swpw(ohci->hcca->frame_no), ohci->controller);
if (ints & OHCI_INTR_RHSC) /* root hub status change */ if (ints & OHCI_INTR_RHSC) /* root hub status change */
{ {
#ifdef USB_POLL_HUB #ifdef USB_POLL_HUB
@@ -1840,10 +1916,13 @@ static int hc_interrupt(ohci_t *ohci)
#endif /* USB_POLL_HUB */ #endif /* USB_POLL_HUB */
stat = 0xff; stat = 0xff;
} }
if (ints & OHCI_INTR_UE) /* e.g. due to PCI Master/Target Abort */ if (ints & OHCI_INTR_UE) /* e.g. due to PCI Master/Target Abort */
{ {
unsigned short status = pci_read_config_word(ohci->handle, PCISR); unsigned short status = pci_read_config_word(ohci->handle, PCISR);
(void) status;
err("OHCI Unrecoverable Error, controller usb-%s-%c disabled\r\n(SR:0x%04X%s%s%s%s%s%s)", ohci->slot_name, (char)ohci->controller + '0', status & 0xFFFF, err("OHCI Unrecoverable Error, controller usb-%s-%c disabled\r\n(SR:0x%04X%s%s%s%s%s%s)", ohci->slot_name, (char)ohci->controller + '0', status & 0xFFFF,
status & 0x8000 ? ", Parity error" : "", status & 0x4000 ? ", Signaled system error" : "", status & 0x2000 ? ", Received master abort" : "", status & 0x8000 ? ", Parity error" : "", status & 0x4000 ? ", Signaled system error" : "", status & 0x2000 ? ", Received master abort" : "",
status & 0x1000 ? ", Received target abort" : "", status & 0x800 ? ", Signaled target abort" : "", status & 0x100 ? ", Data parity error" : ""); status & 0x1000 ? ", Received target abort" : "", status & 0x800 ? ", Signaled target abort" : "", status & 0x100 ? ", Data parity error" : "");
@@ -1852,29 +1931,32 @@ static int hc_interrupt(ohci_t *ohci)
ohci_dump(ohci, 1); ohci_dump(ohci, 1);
#else #else
if (ohci->irq) if (ohci->irq)
wait(1 * 1000); wait(1);
#endif #endif
/* HC Reset */ /* HC Reset */
ohci->hc_control = 0; ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control); writel(ohci->hc_control, &ohci->regs->control);
return -1; return -1;
} }
if (ints & OHCI_INTR_WDH) if (ints & OHCI_INTR_WDH)
{ {
if (ohci->irq) if (ohci->irq)
wait(1 * 1000); wait(1);
writel(OHCI_INTR_WDH, &regs->intrdisable); writel(OHCI_INTR_WDH, &regs->intrdisable);
(void)readl(&regs->intrdisable); /* flush */ (void)readl(&regs->intrdisable); /* flush */
stat = dl_done_list(ohci); stat = dl_done_list(ohci);
writel(OHCI_INTR_WDH, &regs->intrenable); writel(OHCI_INTR_WDH, &regs->intrenable);
(void)readl(&regs->intrdisable); /* flush */ (void)readl(&regs->intrdisable); /* flush */
} }
if (ints & OHCI_INTR_SO) if (ints & OHCI_INTR_SO)
{ {
dbg("USB Schedule overrun\r\n"); dbg("USB Schedule overrun\r\n");
writel(OHCI_INTR_SO, &regs->intrenable); writel(OHCI_INTR_SO, &regs->intrenable);
stat = -1; stat = -1;
} }
/* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
if (ints & OHCI_INTR_SF) if (ints & OHCI_INTR_SF)
{ {
@@ -2052,11 +2134,13 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
debug_printf("pci_get_resource() failed in %s %s\r\n", __FILE__, __LINE__); debug_printf("pci_get_resource() failed in %s %s\r\n", __FILE__, __LINE__);
return(-1); /* get_resource error */ return(-1); /* get_resource error */
} }
if (usb_base_addr == 0xFFFFFFFF) if (usb_base_addr == 0xFFFFFFFF)
{ {
hc_free_buffers(ohci); hc_free_buffers(ohci);
return(-1); return(-1);
} }
if (handle && (ent != NULL)) if (handle && (ent != NULL))
{ {
ohci->flags = 0; ohci->flags = 0;
@@ -2068,6 +2152,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
default: ohci->slot_name = "generic"; break; default: ohci->slot_name = "generic"; break;
} }
} }
debug_printf("OHCI usb-%s-%c, regs address 0x%08X, PCI handle 0x%X\r\n", ohci->slot_name, (char)ohci->controller + '0', ohci->regs, handle); debug_printf("OHCI usb-%s-%c, regs address 0x%08X, PCI handle 0x%X\r\n", ohci->slot_name, (char)ohci->controller + '0', ohci->regs, handle);
if (hc_reset(ohci) < 0) if (hc_reset(ohci) < 0)
{ {
@@ -2076,6 +2161,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
hc_free_buffers(ohci); hc_free_buffers(ohci);
return(-1); return(-1);
} }
if (hc_start(ohci) < 0) if (hc_start(ohci) < 0)
{ {
err("Can't start OHCI usb-%s-%c", ohci->slot_name, (char)ohci->controller + '0'); err("Can't start OHCI usb-%s-%c", ohci->slot_name, (char)ohci->controller + '0');
@@ -2084,6 +2170,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
/* Initialization failed */ /* Initialization failed */
return(-1); return(-1);
} }
#ifdef DEBUG #ifdef DEBUG
ohci_dump(ohci, 1); ohci_dump(ohci, 1);
#endif #endif
@@ -2099,10 +2186,13 @@ int ohci_usb_lowlevel_stop(void *priv)
/* this gets called really early - before the controller has */ /* this gets called really early - before the controller has */
/* even been initialized! */ /* even been initialized! */
ohci_t *ohci = (ohci_t *)priv; ohci_t *ohci = (ohci_t *)priv;
if (!ohci_inited) if (!ohci_inited)
return(0); return(0);
if (ohci == NULL) if (ohci == NULL)
ohci = &gohci[0]; ohci = &gohci[0];
pci_unhook_interrupt(ohci->handle); pci_unhook_interrupt(ohci->handle);
hc_reset(ohci); hc_reset(ohci);

View File

@@ -698,6 +698,7 @@ void init_pci(void)
xprintf("initializing PCI bridge:\r\n"); xprintf("initializing PCI bridge:\r\n");
(void) res; /* for now */
res = register_interrupt_handler(0, INT_SOURCE_PCIARB, pci_arb_interrupt); res = register_interrupt_handler(0, INT_SOURCE_PCIARB, pci_arb_interrupt);
debug_printf("registered interrupt handler for PCI arbiter: %s\r\n", debug_printf("registered interrupt handler for PCI arbiter: %s\r\n",
(res < 0 ? "failed" : "succeeded")); (res < 0 ? "failed" : "succeeded"));