cleaned up
This commit is contained in:
@@ -30,6 +30,7 @@ static int cc_to_error[16] = {
|
||||
/* Not Access */ -1
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
static const char *cc_to_string[16] = {
|
||||
"No 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" \
|
||||
"on a list to be processed by the HC.(2)",
|
||||
};
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* ED States */
|
||||
|
||||
|
||||
@@ -34,10 +34,11 @@
|
||||
#undef DEBUG
|
||||
#undef SHOW_INFO
|
||||
|
||||
char ehci_inited;
|
||||
static char ehci_inited;
|
||||
static int rootdev;
|
||||
|
||||
static uint16_t portreset, companion;
|
||||
static uint16_t portreset;
|
||||
static uint16_t companion;
|
||||
|
||||
struct descriptor {
|
||||
struct usb_hub_descriptor hub;
|
||||
@@ -143,7 +144,8 @@ struct pci_device_id ehci_usb_pci_table[] =
|
||||
}
|
||||
};
|
||||
|
||||
static struct ehci {
|
||||
static struct ehci
|
||||
{
|
||||
/* ------- common part -------- */
|
||||
long handle; /* PCI BIOS */
|
||||
const struct pci_device_id *ent;
|
||||
@@ -195,6 +197,7 @@ static void cache_qh(struct QH *qh, int flush)
|
||||
struct qTD *qtd;
|
||||
struct qTD *next;
|
||||
static struct qTD *first_qtd;
|
||||
|
||||
/* Walk the QH list and flush/invalidate all entries */
|
||||
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 = qh_addr(qh);
|
||||
|
||||
/* Save first qTD pointer, needed for invalidating pass on this QH */
|
||||
if (flush)
|
||||
{
|
||||
@@ -215,6 +219,7 @@ static void cache_qh(struct QH *qh, int flush)
|
||||
}
|
||||
else
|
||||
qtd = first_qtd;
|
||||
|
||||
/* Walk the qTD list and flush/invalidate all entries */
|
||||
while(1)
|
||||
{
|
||||
@@ -255,7 +260,7 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec)
|
||||
wait(1);
|
||||
usec--;
|
||||
}
|
||||
while(usec > 0);
|
||||
while (usec > 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -269,22 +274,24 @@ static int ehci_reset(void)
|
||||
uint32_t tmp;
|
||||
uint32_t *reg_ptr;
|
||||
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");
|
||||
pci_write_config_longword(gehci.handle, 0xE4, 0x20); // oscillator
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
err("EHCI fail to reset");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ehci_is_TDI())
|
||||
{
|
||||
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;
|
||||
ntds = 0;
|
||||
break;
|
||||
|
||||
case sizeof(struct qTD):
|
||||
if (ntds == 3)
|
||||
{
|
||||
@@ -316,6 +324,7 @@ static void *ehci_alloc(size_t sz, size_t align)
|
||||
p = gehci.td[ntds];
|
||||
ntds++;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown allocation size\r\n");
|
||||
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)
|
||||
{
|
||||
uint32_t addr, delta, next;
|
||||
uint32_t addr;
|
||||
uint32_t delta;
|
||||
uint32_t next;
|
||||
int idx;
|
||||
|
||||
addr = (uint32_t)buf;
|
||||
idx = 0;
|
||||
while(idx < 5)
|
||||
|
||||
while (idx < 5)
|
||||
{
|
||||
td->qt_buffer[idx] = swpl(addr - gehci.dma_offset);
|
||||
next = (addr + 4096) & ~4095;
|
||||
@@ -341,6 +354,7 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz)
|
||||
addr = next;
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == 5)
|
||||
{
|
||||
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 cmd;
|
||||
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)
|
||||
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);
|
||||
if (qh == NULL)
|
||||
{
|
||||
debug("unable to allocate QH\r\n");
|
||||
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;
|
||||
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);
|
||||
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_overlay.qt_next = swpl(QT_NEXT_TERMINATE);
|
||||
qh->qh_overlay.qt_altnext = swpl(QT_NEXT_TERMINATE);
|
||||
td = NULL;
|
||||
tdp = &qh->qh_overlay.qt_next;
|
||||
toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
|
||||
|
||||
if (req != NULL)
|
||||
{
|
||||
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;
|
||||
toggle = 1;
|
||||
}
|
||||
|
||||
if (length > 0 || req == NULL)
|
||||
{
|
||||
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 = &td->qt_next;
|
||||
}
|
||||
|
||||
if (req != NULL)
|
||||
{
|
||||
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 = &td->qt_next;
|
||||
}
|
||||
|
||||
gehci.qh_list->qh_link = swpl(((uint32_t)qh - gehci.dma_offset) | QH_LINK_TYPE_QH);
|
||||
/* Flush dcache */
|
||||
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 |= CMD_ASE;
|
||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||
|
||||
ret = handshake((uint32_t *)&gehci.hcor->or_usbsts, STD_ASS, STD_ASS, 100 * 1000);
|
||||
if (ret < 0)
|
||||
{
|
||||
@@ -479,6 +516,7 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
goto fail;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
dev->status = 0;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->status = USB_ST_STALLED;
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
case 0x20:
|
||||
dev->status = USB_ST_BUF_ERR;
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
case 0x10:
|
||||
dev->status = USB_ST_BABBLE_DET;
|
||||
break;
|
||||
|
||||
default:
|
||||
dev->status = USB_ST_CRC_ERR;
|
||||
break;
|
||||
@@ -511,11 +553,12 @@ static int ehci_submit_async(struct usb_device *dev, uint32_t pipe, void *buffer
|
||||
{
|
||||
dev->act_len = 0;
|
||||
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;
|
||||
fail:
|
||||
td = (void *)swpl(qh->qh_overlay.qt_next);
|
||||
td = (void *) swpl(qh->qh_overlay.qt_next);
|
||||
if (td != (void *)QT_NEXT_TERMINATE)
|
||||
td = (struct qTD *)(gehci.dma_offset + (uint32_t)td);
|
||||
while(td != (void *)QT_NEXT_TERMINATE)
|
||||
@@ -530,9 +573,13 @@ fail:
|
||||
if (ehci_readl(&gehci.hcor->or_usbsts) & STS_HSE) /* Host System Error */
|
||||
{
|
||||
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,
|
||||
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" : "");
|
||||
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, 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" : "");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -574,11 +621,13 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
srcptr = &gehci.descriptor->device;
|
||||
srclen = 0x12;
|
||||
break;
|
||||
|
||||
case USB_DT_CONFIG:
|
||||
debug("USB_DT_CONFIG config\r\n");
|
||||
srcptr = &gehci.descriptor->config;
|
||||
srclen = 0x19;
|
||||
break;
|
||||
|
||||
case USB_DT_STRING:
|
||||
debug("USB_DT_STRING config\r\n");
|
||||
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";
|
||||
srclen = 4;
|
||||
break;
|
||||
|
||||
case 1: /* Vendor */
|
||||
srcptr = "\2\3";
|
||||
srclen = 2;
|
||||
break;
|
||||
|
||||
case 2: /* Product */
|
||||
srcptr = "\34\3E\0H\0C\0I\0 \0R\0o\0o\0t\0 \0H\0u\0b\0";
|
||||
srclen = 28;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown value DT_STRING %x\r\n",
|
||||
swpw(req->value));
|
||||
@@ -606,6 +658,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_DESCRIPTOR | ((USB_DIR_IN | USB_RT_HUB) << 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;
|
||||
srclen = 0x8;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown value %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_ADDRESS | (USB_RECIP_DEVICE << 8):
|
||||
debug("USB_REQ_SET_ADDRESS\r\n");
|
||||
rootdev = swpw(req->value);
|
||||
break;
|
||||
|
||||
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
|
||||
debug("USB_REQ_SET_CONFIGURATION\r\n");
|
||||
/* Nothing to do */
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS | ((USB_DIR_IN | USB_RT_HUB) << 8):
|
||||
tmpbuf[0] = 1; /* USB_STATUS_SELFPOWERED */
|
||||
tmpbuf[1] = 0;
|
||||
srcptr = tmpbuf;
|
||||
srclen = 2;
|
||||
break;
|
||||
|
||||
case USB_REQ_GET_STATUS | ((USB_RT_PORT | USB_DIR_IN) << 8):
|
||||
memset(tmpbuf, 0, 4);
|
||||
reg = ehci_readl(status_reg);
|
||||
|
||||
if ((reg & EHCI_PS_PR) && (portreset & (1 << swpw(req->index))))
|
||||
{
|
||||
int ret;
|
||||
@@ -651,6 +710,7 @@ static int ehci_submit_root(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
else
|
||||
err("port(%d) reset error", swpw(req->index) - 1);
|
||||
}
|
||||
|
||||
if (reg & EHCI_PS_CS)
|
||||
tmpbuf[0] |= USB_PORT_STAT_CONNECTION;
|
||||
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)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; break;
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
default: tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; break;
|
||||
default:
|
||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8;
|
||||
|
||||
if (reg & EHCI_PS_CSC)
|
||||
tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION;
|
||||
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;
|
||||
if (portreset & (1 << swpw(req->index)))
|
||||
tmpbuf[2] |= USB_PORT_STAT_C_RESET;
|
||||
|
||||
srcptr = tmpbuf;
|
||||
srclen = 4;
|
||||
break;
|
||||
|
||||
case USB_REQ_SET_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
||||
reg = ehci_readl(status_reg);
|
||||
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;
|
||||
ehci_writel(status_reg, reg);
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_POWER:
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_RESET:
|
||||
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));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown feature %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
/* unblock posted writes */
|
||||
(void)ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
(void) ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
break;
|
||||
|
||||
case USB_REQ_CLEAR_FEATURE | ((USB_DIR_OUT | USB_RT_PORT) << 8):
|
||||
reg = ehci_readl(status_reg);
|
||||
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:
|
||||
reg &= ~EHCI_PS_PE;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_C_ENABLE:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_PE;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_POWER:
|
||||
if (HCS_PPC(ehci_readl(&gehci.hccr->cr_hcsparams)))
|
||||
reg = reg & ~(EHCI_PS_CLEAR | EHCI_PS_PP);
|
||||
case USB_PORT_FEAT_C_CONNECTION:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_CSC;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_OVER_CURRENT:
|
||||
reg = (reg & ~EHCI_PS_CLEAR) | EHCI_PS_OCC;
|
||||
break;
|
||||
|
||||
case USB_PORT_FEAT_C_RESET:
|
||||
portreset &= ~(1 << swpw(req->index));
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("unknown feature %x\r\n", swpw(req->value));
|
||||
goto unknown;
|
||||
}
|
||||
ehci_writel(status_reg, reg);
|
||||
/* unblock posted write */
|
||||
(void)ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
(void) ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
debug("Unknown request\r\n");
|
||||
goto unknown;
|
||||
@@ -797,6 +877,7 @@ static int hc_interrupt(struct ehci *ehci)
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (companion & (1 << i))
|
||||
{
|
||||
/* Low speed device, give up ownership. */
|
||||
@@ -807,6 +888,7 @@ static int hc_interrupt(struct ehci *ehci)
|
||||
}
|
||||
}
|
||||
ehci_writel(&ehci->hcor->or_usbsts, status);
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ehci->descriptor != NULL)
|
||||
{
|
||||
usb_free(ehci->descriptor);
|
||||
ehci->descriptor = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (ehci->td_unaligned[i] != NULL)
|
||||
@@ -836,11 +920,13 @@ static void hc_free_buffers(struct ehci *ehci)
|
||||
ehci->td_unaligned[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ehci->qh_unaligned != NULL)
|
||||
{
|
||||
usb_free(ehci->qh_unaligned);
|
||||
ehci->qh_unaligned = NULL;
|
||||
}
|
||||
|
||||
if (ehci->qh_list_unaligned != NULL)
|
||||
{
|
||||
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 usb_base_addr = 0xFFFFFFFF;
|
||||
struct pci_rd *pci_rsc_desc;
|
||||
|
||||
pci_rsc_desc = pci_get_resource(handle); /* USB EHCI */
|
||||
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 */
|
||||
return(-1);
|
||||
|
||||
gehci.qh_list_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
|
||||
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);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
gehci.qh_list = (struct QH *)(((uint32_t)gehci.qh_list_unaligned + 31) & ~31);
|
||||
memset(gehci.qh_list, 0, sizeof(struct QH));
|
||||
gehci.qh_unaligned = (struct QH *)usb_malloc(sizeof(struct QH) + 32);
|
||||
|
||||
if (gehci.qh_unaligned == NULL)
|
||||
{
|
||||
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);
|
||||
memset(gehci.qh, 0, sizeof(struct QH));
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
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);
|
||||
memset(gehci.td[i], 0, sizeof(struct qTD));
|
||||
}
|
||||
|
||||
gehci.descriptor = (struct descriptor *)usb_malloc(sizeof(struct descriptor));
|
||||
if (gehci.descriptor == NULL)
|
||||
{
|
||||
@@ -902,6 +994,7 @@ int ehci_usb_lowlevel_init(long handle, const struct pci_device_id *ent, void **
|
||||
return(-1);
|
||||
}
|
||||
memcpy(gehci.descriptor, &rom_descriptor, sizeof(struct descriptor));
|
||||
|
||||
if ((long) pci_rsc_desc >= 0)
|
||||
{
|
||||
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;
|
||||
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
|
||||
{
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1); /* get_resource error */
|
||||
}
|
||||
|
||||
if (usb_base_addr == 0xFFFFFFFF)
|
||||
{
|
||||
hc_free_buffers(&gehci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (handle && (ent != NULL))
|
||||
{
|
||||
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);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* 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_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);
|
||||
gehci.descriptor->hub.bNbrPorts = HCS_N_PORTS(reg);
|
||||
info("Register %x NbrPorts %d", reg, gehci.descriptor->hub.bNbrPorts);
|
||||
|
||||
/* Port Indicators */
|
||||
if (HCS_INDICATOR(reg))
|
||||
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)
|
||||
{
|
||||
uint32_t cmd;
|
||||
|
||||
if (priv);
|
||||
if (!ehci_inited)
|
||||
return(0);
|
||||
|
||||
/* turn off interrupts */
|
||||
ehci_writel(&gehci.hcor->or_usbintr, 0);
|
||||
pci_unhook_interrupt(gehci.handle);
|
||||
|
||||
/* stop the controller */
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
cmd &= ~CMD_RUN;
|
||||
ehci_writel(&gehci.hcor->or_usbcmd, cmd);
|
||||
|
||||
/* turn off all ports => todo */
|
||||
/* use the companions */
|
||||
ehci_writel(&gehci.hcor->or_configflag, 0);
|
||||
|
||||
/* unblock posted write */
|
||||
cmd = ehci_readl(&gehci.hcor->or_usbcmd);
|
||||
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));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (usb_pipedevice(pipe) == rootdev)
|
||||
{
|
||||
if (rootdev == 0)
|
||||
|
||||
@@ -187,7 +187,9 @@ static struct td *td_alloc(struct usb_device *usb_dev)
|
||||
{
|
||||
int i;
|
||||
struct td *td;
|
||||
|
||||
td = NULL;
|
||||
|
||||
for (i = 0; i < NUM_TD; i++)
|
||||
{
|
||||
if (ptd[i].usb_dev == NULL)
|
||||
@@ -211,6 +213,7 @@ static void urb_free_priv(urb_priv_t *urb)
|
||||
int i;
|
||||
struct td *td;
|
||||
int last = urb->length - 1;
|
||||
|
||||
if (last >= 0)
|
||||
{
|
||||
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
|
||||
if (!small)
|
||||
{
|
||||
int i, len;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if (usb_pipecontrol(pipe))
|
||||
{
|
||||
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("\r\n");
|
||||
}
|
||||
|
||||
if (transfer_len > 0 && buffer)
|
||||
{
|
||||
debug_printf(__FILE__ ": data(%d/%d):", (purb ? purb->actual_length : 0), transfer_len);
|
||||
len = usb_pipeout(pipe)? transfer_len : (purb ? purb->actual_length : 0);
|
||||
|
||||
for (i = 0; i < 16 && i < len; i++)
|
||||
debug_printf(" %02x", ((uint8_t *)buffer)[i]);
|
||||
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;
|
||||
uint32_t *ed_p;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
j = 5;
|
||||
ed_p = &(ohci->hcca->int_table[i]);
|
||||
if (*ed_p == 0)
|
||||
continue;
|
||||
|
||||
debug_printf(__FILE__ ": %s branch int %2d(%2x):", str, i, i);
|
||||
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)
|
||||
{
|
||||
ed_t *edp;
|
||||
|
||||
value += controller->dma_offset;
|
||||
edp = (ed_t *)value;
|
||||
edp = (ed_t *) value;
|
||||
(void) edp;
|
||||
|
||||
if (value && (value < 0xDFFFF0)) /* STRAM */
|
||||
{
|
||||
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)
|
||||
{
|
||||
switch (state)
|
||||
@@ -338,6 +351,7 @@ static char *hcfs2string(int state)
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
#endif
|
||||
|
||||
/* dump control and status registers */
|
||||
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)
|
||||
{
|
||||
uint32_t temp, ndp, i;
|
||||
uint32_t temp;
|
||||
uint32_t ndp;
|
||||
uint32_t i;
|
||||
|
||||
temp = roothub_a(controller);
|
||||
(void) temp;
|
||||
|
||||
// ndp = (temp & RH_A_NDP);
|
||||
ndp = controller->ndp;
|
||||
if (verbose)
|
||||
@@ -410,6 +429,7 @@ static void ohci_dump_roothub(ohci_t *controller, int verbose)
|
||||
(temp & RH_HS_LPS) ? " LPS" : ""
|
||||
);
|
||||
}
|
||||
|
||||
for (i = 0; i < ndp; 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;
|
||||
urb_priv_t *purb_priv = urb;
|
||||
int i, size = 0;
|
||||
int i;
|
||||
int size = 0;
|
||||
struct usb_device *dev = urb->dev;
|
||||
uint32_t pipe = urb->pipe;
|
||||
void *buffer = urb->transfer_buffer;
|
||||
int transfer_len = urb->transfer_buffer_length;
|
||||
int interval = urb->interval;
|
||||
|
||||
/* when controller's hung, permit only roothub cleanup attempts
|
||||
* such as powering down ports */
|
||||
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
|
||||
* URB unfinished */
|
||||
urb->finished = 0;
|
||||
|
||||
/* every endpoint has a ed, locate and fill it */
|
||||
ed = ep_add_ed(ohci, dev, pipe, interval, 1);
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* for the private part of the URB we need the number of TDs (size) */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (ed->state == ED_NEW || (ed->state & ED_DEL))
|
||||
{
|
||||
urb_free_priv(purb_priv);
|
||||
err("sohci_submit_job: EINVAL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* link the ed into a chain if is not already */
|
||||
if (ed->state != ED_OPER)
|
||||
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)
|
||||
{
|
||||
struct ohci_regs *regs = ohci->regs;
|
||||
|
||||
switch (usb_pipetype(urb->pipe))
|
||||
{
|
||||
case PIPE_INTERRUPT:
|
||||
@@ -556,9 +583,11 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb)
|
||||
urb->actual_length = 0;
|
||||
td_submit_job(ohci, urb->dev, urb->pipe, urb->transfer_buffer, urb->transfer_buffer_length, NULL, urb, urb->interval);
|
||||
break;
|
||||
|
||||
case PIPE_CONTROL:
|
||||
case PIPE_BULK:
|
||||
break;
|
||||
|
||||
default:
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; ((inter >> i) > 1) && (i < 5); 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 */
|
||||
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++)
|
||||
wout |= (((word >> i) & 1) << (num_bits - i - 1));
|
||||
return wout;
|
||||
@@ -641,6 +673,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
|
||||
int interval;
|
||||
int load;
|
||||
uint32_t *ed_p;
|
||||
|
||||
ed->state = ED_OPER;
|
||||
ed->int_interval = 0;
|
||||
switch (ed->type)
|
||||
@@ -660,6 +693,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
|
||||
}
|
||||
ohci->ed_controltail = edi;
|
||||
break;
|
||||
|
||||
case PIPE_BULK:
|
||||
ed->hwNextED = 0;
|
||||
if (ohci->ed_bulktail == NULL)
|
||||
@@ -674,6 +708,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
|
||||
}
|
||||
ohci->ed_bulktail = edi;
|
||||
break;
|
||||
|
||||
case PIPE_INTERRUPT:
|
||||
load = ed->int_load;
|
||||
interval = ep_2_n_interval(ed->int_period);
|
||||
@@ -703,6 +738,7 @@ static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, unsigned
|
||||
for ( ;index < NUM_INTS; index += period)
|
||||
{
|
||||
uint32_t *ed_p = &ohci->hcca->int_table[index];
|
||||
|
||||
/* ED might have been unlinked through another path */
|
||||
while (*ed_p != 0)
|
||||
{
|
||||
@@ -725,6 +761,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
|
||||
{
|
||||
volatile ed_t *ed = edi;
|
||||
int i;
|
||||
|
||||
ed->hwINFO |= swpl(OHCI_ED_SKIP);
|
||||
switch (ed->type)
|
||||
{
|
||||
@@ -745,6 +782,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
|
||||
else
|
||||
((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev;
|
||||
break;
|
||||
|
||||
case PIPE_BULK:
|
||||
if (ed->ed_prev == NULL)
|
||||
{
|
||||
@@ -762,6 +800,7 @@ static int ep_unlink(ohci_t *ohci, ed_t *edi)
|
||||
else
|
||||
((ed_t *)(swpl(*((uint32_t *)&ed->hwNextED)) + ohci->dma_offset))->ed_prev = ed->ed_prev;
|
||||
break;
|
||||
|
||||
case PIPE_INTERRUPT:
|
||||
periodic_unlink(ohci, ed, 0, 1);
|
||||
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;
|
||||
volatile ed_t *ed;
|
||||
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))];
|
||||
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 */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ed->state == ED_NEW)
|
||||
{
|
||||
/* 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);
|
||||
ohci_dev->ed_cnt++;
|
||||
}
|
||||
|
||||
ed->hwINFO = swpl(usb_pipedevice(pipe)
|
||||
| usb_pipeendpoint(pipe) << 7
|
||||
| (usb_pipeisoc(pipe)? 0x8000: 0)
|
||||
| (usb_pipecontrol(pipe)? 0: (usb_pipeout(pipe)? 0x800: 0x1000))
|
||||
| usb_pipeslow(pipe) << 13
|
||||
| usb_maxpacket(usb_dev, pipe) << 16);
|
||||
|
||||
if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK)
|
||||
{
|
||||
ed->int_period = interval;
|
||||
@@ -828,7 +871,9 @@ static ed_t *ep_add_ed(ohci_t *ohci, struct usb_device *usb_dev, uint32_t pipe,
|
||||
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)
|
||||
{
|
||||
volatile td_t *td, *td_pt;
|
||||
volatile td_t *td;
|
||||
volatile td_t *td_pt;
|
||||
|
||||
#ifdef OHCI_FILL_TRACE
|
||||
int i;
|
||||
#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 */
|
||||
td_pt = urb_priv->td[index];
|
||||
td_pt->hwNextTD = 0;
|
||||
|
||||
/* fill the old dummy TD */
|
||||
td = urb_priv->td[index] = (td_t *)((swpl(urb_priv->ed->hwTailP) & ~0xf) + ohci->dma_offset);
|
||||
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);
|
||||
/* append to queue */
|
||||
td->ed->hwTailP = td->hwNextTD;
|
||||
|
||||
#if 0
|
||||
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 */
|
||||
|
||||
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;
|
||||
void *data;
|
||||
int cnt = 0;
|
||||
uint32_t info = 0;
|
||||
unsigned int toggle = 0;
|
||||
|
||||
/* OHCI handles the DATA-toggles itself, we just use the USB-toggle
|
||||
* bits for reseting */
|
||||
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;
|
||||
usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1);
|
||||
}
|
||||
|
||||
urb->td_cnt = 0;
|
||||
if (data_len)
|
||||
data = buffer;
|
||||
else
|
||||
data = NULL;
|
||||
|
||||
switch (usb_pipetype(pipe))
|
||||
{
|
||||
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 */
|
||||
writel(OHCI_BLF, &ohci->regs->cmdstatus);
|
||||
break;
|
||||
|
||||
case PIPE_CONTROL:
|
||||
/* Setup phase */
|
||||
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 */
|
||||
writel(OHCI_CLF, &ohci->regs->cmdstatus);
|
||||
break;
|
||||
|
||||
case PIPE_INTERRUPT:
|
||||
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);
|
||||
@@ -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)
|
||||
{
|
||||
uint32_t tdBE, tdCBP;
|
||||
uint32_t tdBE;
|
||||
uint32_t tdCBP;
|
||||
|
||||
urb_priv_t *lurb_priv = td->ed->purb;
|
||||
|
||||
tdBE = swpl(td->hwBE);
|
||||
tdCBP = swpl(td->hwCBP);
|
||||
|
||||
if (tdBE)
|
||||
tdBE += ohci->dma_offset;
|
||||
if (tdCBP)
|
||||
tdCBP += ohci->dma_offset;
|
||||
|
||||
if (!(usb_pipecontrol(lurb_priv->pipe) && ((td->index == 0) || (td->index == lurb_priv->length - 1))))
|
||||
{
|
||||
if (tdBE != 0)
|
||||
@@ -989,6 +1046,7 @@ static void check_status(ohci_t *ohci, td_t *td_list)
|
||||
int urb_len = lurb_priv->length;
|
||||
uint32_t *phwHeadP = &td_list->ed->hwHeadP;
|
||||
int cc = TD_CC_GET(swpl(td_list->hwINFO));
|
||||
|
||||
if (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;
|
||||
td_t *td_rev = NULL;
|
||||
td_t *td_list = NULL;
|
||||
|
||||
td_list_hc = swpl(ohci->hcca->done_head) & ~0xf;
|
||||
if (td_list_hc)
|
||||
td_list_hc += ohci->dma_offset;
|
||||
@@ -1032,7 +1091,6 @@ static td_t *dl_reverse_done_list(ohci_t *ohci)
|
||||
return td_list;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
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;
|
||||
dl_transfer_length(ohci, td_list);
|
||||
lurb_priv->td_cnt++;
|
||||
|
||||
/* error code of transfer */
|
||||
cc = TD_CC_GET(tdINFO);
|
||||
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);
|
||||
stat = cc_to_error[cc];
|
||||
}
|
||||
|
||||
/* see if this done list makes for all TD's of current URB,
|
||||
* and mark the URB finished if so */
|
||||
if (lurb_priv->td_cnt == lurb_priv->length)
|
||||
@@ -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 wIndex;
|
||||
uint16_t wLength;
|
||||
|
||||
#ifdef DEBUG
|
||||
pkt_print(ohci, NULL, dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe));
|
||||
#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);
|
||||
wLength = swpw(cmd->length);
|
||||
info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
|
||||
|
||||
switch (bmRType_bReq)
|
||||
{
|
||||
/* Request Destination:
|
||||
@@ -1448,6 +1510,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
|
||||
int maxsize = usb_maxpacket(dev, pipe);
|
||||
int timeout;
|
||||
urb_priv_t *urb = (urb_priv_t *) usb_malloc(sizeof(urb_priv_t));
|
||||
|
||||
if (urb == NULL)
|
||||
{
|
||||
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)
|
||||
wait(1 * 1000);
|
||||
#endif
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
err("submit_common_message: pipesize for pipe %lx is zero", pipe);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sohci_submit_job(ohci, urb, setup) < 0)
|
||||
{
|
||||
err("sohci_submit_job failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
wait(10 * 1000);
|
||||
/* ohci_dump_status(ohci); */
|
||||
#endif
|
||||
/* allow more time for a BULK device to react - some are slow */
|
||||
#define BULK_TO 5000 /* timeout in milliseconds */
|
||||
|
||||
if (usb_pipebulk(pipe))
|
||||
timeout = BULK_TO;
|
||||
else
|
||||
timeout = 1000;
|
||||
|
||||
/* wait for it to complete */
|
||||
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 */
|
||||
break;
|
||||
}
|
||||
|
||||
if (--timeout)
|
||||
{
|
||||
wait(1 * 1000);
|
||||
@@ -1570,11 +1639,13 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
|
||||
if (ohci->irq)
|
||||
wait(1 * 1000);
|
||||
#endif
|
||||
|
||||
if (!maxsize)
|
||||
{
|
||||
err("submit_control_message: pipesize for pipe %lx is zero", pipe);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((pipe >> 8) & 0x7f) == ohci->rh.devnum)
|
||||
{
|
||||
ohci->rh.dev = dev;
|
||||
@@ -1600,6 +1671,7 @@ static int hc_reset(ohci_t *ohci)
|
||||
{
|
||||
int timeout = 30;
|
||||
int smm_timeout = 50; /* 0,5 sec */
|
||||
|
||||
dbg("%s\r\n", __FUNCTION__);
|
||||
|
||||
if ((ohci->ent->vendor == PCI_VENDOR_ID_PHILIPS)
|
||||
@@ -1611,6 +1683,7 @@ static int hc_reset(ohci_t *ohci)
|
||||
resetting via EHCI registers only. */
|
||||
short index = 0;
|
||||
long handle;
|
||||
|
||||
do
|
||||
{
|
||||
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);
|
||||
#endif /* OHCI_USE_NPS */
|
||||
/* 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;
|
||||
/* connect the virtual root hub */
|
||||
ohci->rh.devnum = 0;
|
||||
@@ -1801,6 +1874,7 @@ static int hc_interrupt(ohci_t *ohci)
|
||||
{
|
||||
struct ohci_regs *regs = ohci->regs;
|
||||
int ints, stat = -1;
|
||||
|
||||
if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01))
|
||||
ints = OHCI_INTR_WDH;
|
||||
else
|
||||
@@ -1822,8 +1896,10 @@ static int hc_interrupt(ohci_t *ohci)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ohci->irq)
|
||||
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 */
|
||||
{
|
||||
#ifdef USB_POLL_HUB
|
||||
@@ -1840,10 +1916,13 @@ static int hc_interrupt(ohci_t *ohci)
|
||||
#endif /* USB_POLL_HUB */
|
||||
stat = 0xff;
|
||||
}
|
||||
|
||||
if (ints & OHCI_INTR_UE) /* e.g. due to PCI Master/Target Abort */
|
||||
{
|
||||
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,
|
||||
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" : "");
|
||||
@@ -1852,29 +1931,32 @@ static int hc_interrupt(ohci_t *ohci)
|
||||
ohci_dump(ohci, 1);
|
||||
#else
|
||||
if (ohci->irq)
|
||||
wait(1 * 1000);
|
||||
wait(1);
|
||||
#endif
|
||||
/* HC Reset */
|
||||
ohci->hc_control = 0;
|
||||
writel(ohci->hc_control, &ohci->regs->control);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ints & OHCI_INTR_WDH)
|
||||
{
|
||||
if (ohci->irq)
|
||||
wait(1 * 1000);
|
||||
wait(1);
|
||||
writel(OHCI_INTR_WDH, ®s->intrdisable);
|
||||
(void)readl(®s->intrdisable); /* flush */
|
||||
stat = dl_done_list(ohci);
|
||||
writel(OHCI_INTR_WDH, ®s->intrenable);
|
||||
(void)readl(®s->intrdisable); /* flush */
|
||||
}
|
||||
|
||||
if (ints & OHCI_INTR_SO)
|
||||
{
|
||||
dbg("USB Schedule overrun\r\n");
|
||||
writel(OHCI_INTR_SO, ®s->intrenable);
|
||||
stat = -1;
|
||||
}
|
||||
|
||||
/* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */
|
||||
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__);
|
||||
return(-1); /* get_resource error */
|
||||
}
|
||||
|
||||
if (usb_base_addr == 0xFFFFFFFF)
|
||||
{
|
||||
hc_free_buffers(ohci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (handle && (ent != NULL))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -2076,6 +2161,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
|
||||
hc_free_buffers(ohci);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (hc_start(ohci) < 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 */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ohci_dump(ohci, 1);
|
||||
#endif
|
||||
@@ -2099,10 +2186,13 @@ int ohci_usb_lowlevel_stop(void *priv)
|
||||
/* this gets called really early - before the controller has */
|
||||
/* even been initialized! */
|
||||
ohci_t *ohci = (ohci_t *)priv;
|
||||
|
||||
if (!ohci_inited)
|
||||
return(0);
|
||||
|
||||
if (ohci == NULL)
|
||||
ohci = &gohci[0];
|
||||
|
||||
pci_unhook_interrupt(ohci->handle);
|
||||
|
||||
hc_reset(ohci);
|
||||
|
||||
@@ -698,6 +698,7 @@ void init_pci(void)
|
||||
|
||||
xprintf("initializing PCI bridge:\r\n");
|
||||
|
||||
(void) res; /* for now */
|
||||
res = register_interrupt_handler(0, INT_SOURCE_PCIARB, pci_arb_interrupt);
|
||||
debug_printf("registered interrupt handler for PCI arbiter: %s\r\n",
|
||||
(res < 0 ? "failed" : "succeeded"));
|
||||
|
||||
Reference in New Issue
Block a user