diff options
Diffstat (limited to 'payloads/libpayload/drivers/usb/uhci.c')
-rw-r--r-- | payloads/libpayload/drivers/usb/uhci.c | 81 |
1 files changed, 16 insertions, 65 deletions
diff --git a/payloads/libpayload/drivers/usb/uhci.c b/payloads/libpayload/drivers/usb/uhci.c index def6b45084..b6ed994e93 100644 --- a/payloads/libpayload/drivers/usb/uhci.c +++ b/payloads/libpayload/drivers/usb/uhci.c @@ -1,7 +1,7 @@ /* * This file is part of the libpayload project. * - * Copyright (C) 2008 coresystems GmbH + * Copyright (C) 2008-2010 coresystems GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,8 @@ * SUCH DAMAGE. */ +//#define USB_DEBUG + #include <usb/usb.h> #include "uhci.h" #include <arch/virtual.h> @@ -35,8 +37,6 @@ static void uhci_start (hci_t *controller); static void uhci_stop (hci_t *controller); static void uhci_reset (hci_t *controller); static void uhci_shutdown (hci_t *controller); -static int uhci_packet (usbdev_t *dev, int endp, int pid, int toggle, - int length, u8 *data); static int uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize); static int uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen, u8 *data); @@ -128,6 +128,8 @@ hci_t * uhci_init (pcidev_t addr) { int i; + u16 reg16; + hci_t *controller = new_controller (); if (!controller) @@ -141,7 +143,6 @@ uhci_init (pcidev_t addr) controller->stop = uhci_stop; controller->reset = uhci_reset; controller->shutdown = uhci_shutdown; - controller->packet = uhci_packet; controller->bulk = uhci_bulk; controller->control = uhci_control; controller->create_intr_queue = uhci_create_intr_queue; @@ -160,7 +161,9 @@ uhci_init (pcidev_t addr) uhci_stop (controller); mdelay (1); uhci_reg_write16 (controller, USBSTS, 0x3f); - pci_write_config32 (controller->bus_address, 0xc0, 0x8f00); + reg16 = pci_read_config16(controller->bus_address, 0xc0); + reg16 &= 0xdf80; + pci_write_config16 (controller->bus_address, 0xc0, reg16); UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t *)); /* 4kb aligned to 4kb */ if (! UHCI_INST (controller)->framelistptr) @@ -277,18 +280,6 @@ wait_for_completed_qh (hci_t *controller, qh_t *qh) 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr.ptr)); } -static void -wait_for_completed_td (hci_t *controller, td_t *td) -{ - int timeout = 10000; - while ((td->status_active == 1) - && ((uhci_reg_read16 (controller, USBSTS) & 2) == 0) - && (timeout-- > 0)) { - uhci_reg_mask16 (controller, USBSTS, ~0, 0); // clear resettable registers - udelay (10); - } -} - static int maxlen (int size) { @@ -331,7 +322,7 @@ uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen, tds[0].maxlen = maxlen (drlen); tds[0].counter = 3; tds[0].data_toggle = 0; - tds[0].lowspeed = dev->lowspeed; + tds[0].lowspeed = dev->speed; tds[0].bufptr = virt_to_phys (devreq); tds[0].status_active = 1; @@ -343,7 +334,7 @@ uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen, tds[i].maxlen = maxlen (min (mlen, dalen)); tds[i].counter = 3; tds[i].data_toggle = toggle; - tds[i].lowspeed = dev->lowspeed; + tds[i].lowspeed = dev->speed; tds[i].bufptr = virt_to_phys (data); tds[i].status_active = 1; toggle ^= 1; @@ -357,7 +348,8 @@ uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen, tds[count].maxlen = maxlen (0); tds[count].counter = 0; /* as per linux 2.4.10 */ tds[count].data_toggle = 1; - tds[count].lowspeed = dev->lowspeed, tds[count].bufptr = 0; + tds[count].lowspeed = dev->speed; + tds[count].bufptr = 0; tds[count].status_active = 1; UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr = virt_to_phys (tds); @@ -378,48 +370,6 @@ uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen, return result; } -static int -uhci_packet (usbdev_t *dev, int endp, int pid, int toggle, int length, - unsigned char *data) -{ - static td_t *td = 0; - if (td == 0) - td = memalign (16, sizeof (td_t)); - - memset (td, 0, sizeof (td_t)); - td->ptr = 0; - td->terminate = 1; - td->queue_head = 0; - - td->pid = pid; - td->dev_addr = dev->address; - td->endp = endp & 0xf; - td->maxlen = maxlen (length); - if (pid == SETUP) - td->counter = 3; - else - td->counter = 0; - td->data_toggle = toggle & 1; - td->lowspeed = dev->lowspeed; - td->bufptr = virt_to_phys (data); - - td->status_active = 1; - - UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr = - virt_to_phys (td); - UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0; - UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0; - wait_for_completed_td (dev->controller, td); - if ((td->status & 0x7f) == 0) { - //printf("successfully sent a %x packet to %x.%x\n",pid, dev->address,endp); - // success - return 0; - } else { - td_dump (td); - return 1; - } -} - static td_t * create_schedule (int numpackets) { @@ -454,7 +404,7 @@ fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data, else td->counter = 0; td->data_toggle = *toggle & 1; - td->lowspeed = ep->dev->lowspeed; + td->lowspeed = ep->dev->speed; td->bufptr = virt_to_phys (data); td->status_active = 1; @@ -484,7 +434,7 @@ uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) { int maxpsize = ep->maxpacketsize; if (maxpsize == 0) - fatal ("MaxPacketSize == 0!!!"); + usb_fatal ("MaxPacketSize == 0!!!"); int numpackets = (size + maxpsize - 1 + finalize) / maxpsize; if (numpackets == 0) return 0; @@ -498,6 +448,7 @@ uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize) size -= maxpsize; } if (run_schedule (ep->dev, tds) == 1) { + debug("Stalled. Trying to clean up.\n"); clear_stall (ep); free (tds); return 1; @@ -557,7 +508,7 @@ uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming tds[i].maxlen = maxlen (reqsize); tds[i].counter = 0; tds[i].data_toggle = ep->toggle & 1; - tds[i].lowspeed = ep->dev->lowspeed; + tds[i].lowspeed = ep->dev->speed; tds[i].bufptr = virt_to_phys (data); tds[i].status_active = 1; ep->toggle ^= 1; |