cleaned up

This commit is contained in:
Markus Fröschle
2013-12-15 07:04:54 +00:00
parent 883a64da83
commit 324657ffbc
4 changed files with 255 additions and 59 deletions

View File

@@ -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 */

View File

@@ -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)

View File

@@ -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, &regs->intrdisable);
(void)readl(&regs->intrdisable); /* flush */
stat = dl_done_list(ohci);
writel(OHCI_INTR_WDH, &regs->intrenable);
(void)readl(&regs->intrdisable); /* flush */
}
if (ints & OHCI_INTR_SO)
{
dbg("USB Schedule overrun\r\n");
writel(OHCI_INTR_SO, &regs->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);

View File

@@ -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"));