[coreboot] [SeaBIOS] USB Problems geode lx800
Christian Gmeiner
christian.gmeiner at gmail.com
Tue Oct 16 16:11:08 CEST 2012
2012/10/15 Kevin O'Connor <kevin at 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 at gmail.com>
>> wrote:
>> > 2012/10/11 Christian Gmeiner <christian.gmeiner at gmail.com>:
>> > > 2012/10/11 Kevin O'Connor <kevin at koconnor.net>:
>> > >> On Tue, Oct 09, 2012 at 02:31:05PM +0200, Christian Gmeiner wrote:
>> > >>> 2012/10/9 Kevin O'Connor <kevin at 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
More information about the coreboot
mailing list