2012/10/15 Kevin O'Connor kevin@koconnor.net:
On Sun, Oct 14, 2012 at 07:48:00PM +0000, Christian Gmeiner wrote:
On 11 Oct 2012 16:42, "Christian Gmeiner" christian.gmeiner@gmail.com wrote:
2012/10/11 Christian Gmeiner christian.gmeiner@gmail.com:
2012/10/11 Kevin O'Connor kevin@koconnor.net:
On Tue, Oct 09, 2012 at 02:31:05PM +0200, Christian Gmeiner wrote:
2012/10/9 Kevin O'Connor kevin@koconnor.net: > On Mon, Oct 08, 2012 at 02:14:03PM +0200, Christian Gmeiner wrote: >> HI all >> >> I am running into some usb problems with coreboot & seabios: > Can you set the debug level to 8 and post the whole log? Also, for > timeout issues, having timestamps (via tools/readserial.py tool) > sometimes helps.
[...]
Kevin do you have an idea what could be wrong?
I haven't had a chance to take a look at it. Something odd is going on, as it appears the transfer that's failing isn't even being started. I'll see if I can take a look this week.
-Kevin
He Kevin,
I have made some success to get USB working - current SeaBios ehci driver does not support toggling between DATA0 and DATA1. Here is my current patch to get a little bit more running:
diff --git a/src/blockcmd.c b/src/blockcmd.c index 77c690f..a66d7ed 100644 --- a/src/blockcmd.c +++ b/src/blockcmd.c @@ -189,6 +189,7 @@ scsi_init_drive(struct drive_s *drive, const char *s, int prio) int cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) { + dprintf(1, "%s\n", __func__); struct cdb_request_sense cmd; memset(&cmd, 0, sizeof(cmd)); cmd.command = CDB_CMD_INQUIRY; @@ -202,6 +203,7 @@ cdb_get_inquiry(struct disk_op_s *op, struct cdbres_inquiry *data) int cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data) { + dprintf(1, "%s\n", __func__); struct cdb_request_sense cmd; memset(&cmd, 0, sizeof(cmd)); cmd.command = CDB_CMD_REQUEST_SENSE; @@ -215,6 +217,7 @@ cdb_get_sense(struct disk_op_s *op, struct cdbres_request_sense *data) int cdb_test_unit_ready(struct disk_op_s *op) { + dprintf(1, "%s\n", __func__); struct cdb_request_sense cmd; memset(&cmd, 0, sizeof(cmd)); cmd.command = CDB_CMD_TEST_UNIT_READY; @@ -227,6 +230,7 @@ cdb_test_unit_ready(struct disk_op_s *op) int cdb_read_capacity(struct disk_op_s *op, struct cdbres_read_capacity *data) { + dprintf(1, "%s\n", __func__); struct cdb_read_capacity cmd; memset(&cmd, 0, sizeof(cmd)); cmd.command = CDB_CMD_READ_CAPACITY; diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 2676615..02463c7 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -204,6 +204,7 @@ ehci_waittick(struct usb_ehci_s *cntl) yield(); } // Ring "doorbell" + dprintf(1, "ring 'doorbell'\n"); writel(&cntl->regs->usbcmd, cmd | CMD_IAAD); // Wait for completion for (;;) { @@ -217,6 +218,7 @@ ehci_waittick(struct usb_ehci_s *cntl) yield(); } // Ack completion + dprintf(1, "Ack completion\n"); writel(&cntl->regs->usbsts, STS_IAA); }
@@ -495,6 +497,9 @@ ehci_alloc_pipe(struct usbdevice_s *usbdev return usbpipe; }
+ /* initial value */ + usbpipe->toogle = 0; + // Allocate a new queue head. struct ehci_pipe *pipe; if (eptype == USB_ENDPOINT_XFER_CONTROL) @@ -641,6 +646,34 @@ ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize return ret; }
+static int ehci_set_async_schedule(struct usb_ehci_s *ehcic, int enable) +{ + dprintf(7, "%s: enable %d\n", __func__, enable); + + // Set async schedule status. + u32 cmd = readl(&ehcic->regs->usbcmd); + if (enable) + cmd |= CMD_ASE; + else + cmd &= ~CMD_ASE; + + writel(&ehcic->regs->usbcmd, cmd); + + /* Wait for the controller to accept async schedule status. + * This shouldn't take too long, but we should timeout nevertheless. + */ + enable = enable ? STS_ASS : 0; + int timeout = 100; /* time out after 100ms */ + while (((readl(&ehcic->regs->usbsts) & STS_ASS) != enable) + && timeout--) + mdelay(1); + if (timeout < 0) { + dprintf(7, "ehci async schedule status change timed out.\n"); + return 1; + } + return 0; +} + #define STACKQTDS 4
int @@ -652,6 +685,12 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" , &pipe->qh, dir, data, datasize);
+ struct usb_ehci_s *ehcic = container_of( + GET_LOWFLAT(pipe->pipe.cntl), struct usb_ehci_s, usb); + + // stop async schedule + ehci_set_async_schedule(ehcic, 0); + // Allocate 4 tds on stack (with required alignment) u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1]; struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN); @@ -661,12 +700,23 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); int tdpos = 0; + struct ehci_qtd *last = &tds[0]; + + int count = 0; while (datasize) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; +#if 0 int ret = ehci_wait_td(pipe, td, 5000); - if (ret) + if (ret) { + int i; + for(i=0; i<STACKQTDS; i++) + { + dprintf(1, "td%d: q=%x a=%x t=%xn", + i, tds[i].qtd_next, tds[i].alt_next, tds[i].token); + } return -1; - + } +#endif struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) , &tds[tdpos % STACKQTDS]);
@@ -679,15 +729,42 @@ ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
data += transfer; datasize -= transfer; + last = td; + count++; } + + dprintf(1, "added %d TDs\n", count); + dprintf(1, "ep%d toogle %d\n", pipe->pipe.ep, pipe->pipe.toogle); + + /* update based on endpoint toggle */ + tds[0].token |= (pipe->pipe.toogle?QTD_TOGGLE:0); + pipe->qh.token|= (pipe->pipe.toogle?QTD_TOGGLE:0); + + + ehci_set_async_schedule(ehcic, 1); + int i; for (i=0; i<STACKQTDS; i++) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; int ret = ehci_wait_td(pipe, td, 5000); - if (ret) - return -1; + + if (ret) { + int i; + for(i=0; i<STACKQTDS; i++) + { + dprintf(1, "b td%d: q=%x a=%x t=%x\n", + i, tds[i].qtd_next, tds[i].alt_next, tds[i].token); + } + } + }
+ /* update endpoint toggle based on device */ + pipe->pipe.toogle = (last->token & QTD_TOGGLE) >> 31; + + // stop async schedule + ehci_set_async_schedule(ehcic, 0); + return 0; }
diff --git a/src/usb-ehci.h b/src/usb-ehci.h index 32e4109..739dca8 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -163,6 +163,7 @@ struct ehci_qtd { #define QTD_STS_MMF (1 << 2) #define QTD_STS_STS (1 << 1) #define QTD_STS_PING (1 << 0) +#define QTD_STS_MASK 0xff
#define ehci_explen(len) (((len) << QTD_LENGTH_SHIFT) & QTD_LENGTH_MASK)
diff --git a/src/usb-msc.c b/src/usb-msc.c index 83c7397..002f54d 100644 --- a/src/usb-msc.c +++ b/src/usb-msc.c @@ -65,7 +65,7 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) if (!CONFIG_USB_MSC) return 0;
- dprintf(16, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" + dprintf(1, "usb_cmd_data id=%p write=%d count=%d bs=%d buf=%p\n" , op->drive_g, 0, op->count, blocksize, op->buf_fl); struct usbdrive_s *udrive_g = container_of( op->drive_g, struct usbdrive_s, drive); @@ -83,19 +83,29 @@ usb_cmd_data(struct disk_op_s *op, void *cdbcmd, u16 blocksize) cbw.bCBWCBLength = USB_CDB_SIZE;
// Transfer cbw to device. + dprintf(1, "cbw to device\n"); int ret = usb_msc_send(udrive_g, USB_DIR_OUT , MAKE_FLATPTR(GET_SEG(SS), &cbw), sizeof(cbw)); if (ret) goto fail;
// Transfer data to/from device. + if ((cbw.bmCBWFlags & 0x80) == 0) + { + dprintf(1, "Data-Out from host to the device - %d bytes\n", bytes); + } + else + { + dprintf(1, "Data-In from the device to the host - %d bytes\n", bytes); + } if (bytes) { ret = usb_msc_send(udrive_g, cbw.bmCBWFlags, op->buf_fl, bytes); if (ret) goto fail; }
- // Transfer csw info. + // Transfer csw info from device to host. + dprintf(1, "Transfer csw info.\n"); struct csw_s csw; ret = usb_msc_send(udrive_g, USB_DIR_IN , MAKE_FLATPTR(GET_SEG(SS), &csw), sizeof(csw)); diff --git a/src/usb.h b/src/usb.h index a43e829..d272306 100644 --- a/src/usb.h +++ b/src/usb.h @@ -14,6 +14,7 @@ struct usb_pipe { u8 ep; u8 devaddr; u8 speed; + u8 toogle; u16 maxpacket; u8 eptype; };
The log matching this patch to 99% can be found here: http://dpaste.com/814237/
cdb_get_inquiry() works but cdb_test_unit_ready() fails...
--- Christian Gmeiner, MSc