/*
* 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
* SUCH DAMAGE.
*/
+//#define USB_DEBUG
+
+#include <arch/virtual.h>
#include <usb/usb.h>
#include "uhci.h"
-#include <arch/virtual.h>
+#include "uhci_private.h"
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,
+static int uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq,
int dalen, u8 *data);
static void* uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
static void uhci_destroy_intr_queue (endpoint_t *ep, void *queue);
static void
uhci_dump (hci_t *controller)
{
- printf ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD));
- printf ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS));
- printf ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR));
- printf ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM));
- printf ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD));
- printf ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD));
- printf ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1));
- printf ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2));
+ debug ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD));
+ debug ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS));
+ debug ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR));
+ debug ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM));
+ debug ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD));
+ debug ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD));
+ debug ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1));
+ debug ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2));
}
#endif
td_dump (td_t *td)
{
char td_value[3];
- char *td_type;
- switch (td->pid) {
- case SETUP:
+ const char *td_type;
+ switch (td->token & TD_PID_MASK) {
+ case UHCI_SETUP:
td_type="SETUP";
break;
- case IN:
+ case UHCI_IN:
td_type="IN";
break;
- case OUT:
+ case UHCI_OUT:
td_type="OUT";
break;
default:
- sprintf(td_value, "%x", td->pid);
+ sprintf(td_value, "%x", td->token & TD_PID_MASK);
td_type=td_value;
}
- printf ("%s packet (at %lx) to %x.%x failed\n", td_type,
- virt_to_phys (td), td->dev_addr, td->endp);
- printf ("td (counter at %x) returns: ", td->counter);
- printf (" bitstuff err: %x, ", td->status_bitstuff_err);
- printf (" CRC err: %x, ", td->status_crc_err);
- printf (" NAK rcvd: %x, ", td->status_nakrcvd);
- printf (" Babble: %x, ", td->status_babble);
- printf (" Data Buffer err: %x, ", td->status_databuf_err);
- printf (" Stalled: %x, ", td->status_stalled);
- printf (" Active: %x\n", td->status_active);
- if (td->status_babble)
- printf (" Babble because of %s\n",
- td->status_bitstuff_err ? "host" : "device");
- if (td->status_active)
- printf (" still active - timeout?\n");
+ debug ("%s packet (at %lx) to %x.%x failed\n", td_type,
+ virt_to_phys (td), (td->token & TD_DEVADDR_MASK) >> TD_DEVADDR_SHIFT,
+ (td->token & TD_EP_MASK) >> TD_EP_SHIFT);
+ debug ("td (counter at %x) returns: ", td->ctrlsts >> TD_COUNTER_SHIFT);
+ debug (" bitstuff err: %x, ", !!(td->ctrlsts & TD_STATUS_BITSTUFF_ERR));
+ debug (" CRC err: %x, ", !!(td->ctrlsts & TD_STATUS_CRC_ERR));
+ debug (" NAK rcvd: %x, ", !!(td->ctrlsts & TD_STATUS_NAK_RCVD));
+ debug (" Babble: %x, ", !!(td->ctrlsts & TD_STATUS_BABBLE));
+ debug (" Data Buffer err: %x, ", !!(td->ctrlsts & TD_STATUS_DATABUF_ERR));
+ debug (" Stalled: %x, ", !!(td->ctrlsts & TD_STATUS_STALLED));
+ debug (" Active: %x\n", !!(td->ctrlsts & TD_STATUS_ACTIVE));
+ if (td->ctrlsts & TD_STATUS_BABBLE)
+ debug (" Babble because of %s\n",
+ (td->ctrlsts & TD_STATUS_BITSTUFF_ERR) ? "host" : "device");
+ if (td->ctrlsts & TD_STATUS_ACTIVE)
+ debug (" still active - timeout?\n");
}
static void
uhci_reg_write32 (controller, FLBASEADD,
(u32) virt_to_phys (UHCI_INST (controller)->
framelistptr));
- //printf ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
+ //debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
/* disable irqs */
uhci_reg_write16 (controller, USBINTR, 0);
/* reset framelist index */
uhci_reg_write16 (controller, FRNUM, 0);
- uhci_reg_mask16 (controller, USBCMD, ~0, 0xc0); // max packets, configure flag
+ uhci_reg_write16(controller, USBCMD,
+ uhci_reg_read16(controller, USBCMD) | 0xc0); // max packets, configure flag
uhci_start (controller);
}
uhci_init (pcidev_t addr)
{
int i;
+ u16 reg16;
+
hci_t *controller = new_controller ();
if (!controller)
- usb_fatal("Could not create USB controller instance.\n");
+ fatal("Could not create USB controller instance.\n");
controller->instance = malloc (sizeof (uhci_t));
if(!controller->instance)
- usb_fatal("Not enough memory creating USB controller instance.\n");
+ fatal("Not enough memory creating USB controller instance.\n");
controller->start = uhci_start;
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;
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)
- usb_fatal("Not enough memory for USB frame list pointer.\n");
+ fatal("Not enough memory for USB frame list pointer.\n");
memset (UHCI_INST (controller)->framelistptr, 0,
1024 * sizeof (flistp_t));
*/
td_t *antiberserk = memalign(16, sizeof(td_t));
if (!antiberserk)
- usb_fatal("Not enough memory for chipset workaround.\n");
+ fatal("Not enough memory for chipset workaround.\n");
memset(antiberserk, 0, sizeof(td_t));
UHCI_INST (controller)->qh_prei = memalign (16, sizeof (qh_t));
! UHCI_INST (controller)->qh_intr ||
! UHCI_INST (controller)->qh_data ||
! UHCI_INST (controller)->qh_last)
- usb_fatal ("Not enough memory for USB controller queues.\n");
-
- UHCI_INST (controller)->qh_prei->headlinkptr.ptr =
- virt_to_phys (UHCI_INST (controller)->qh_intr);
- UHCI_INST (controller)->qh_prei->headlinkptr.queue_head = 1;
- UHCI_INST (controller)->qh_prei->elementlinkptr.ptr = 0;
- UHCI_INST (controller)->qh_prei->elementlinkptr.terminate = 1;
-
- UHCI_INST (controller)->qh_intr->headlinkptr.ptr =
- virt_to_phys (UHCI_INST (controller)->qh_data);
- UHCI_INST (controller)->qh_intr->headlinkptr.queue_head = 1;
- UHCI_INST (controller)->qh_intr->elementlinkptr.ptr = 0;
- UHCI_INST (controller)->qh_intr->elementlinkptr.terminate = 1;
-
- UHCI_INST (controller)->qh_data->headlinkptr.ptr =
- virt_to_phys (UHCI_INST (controller)->qh_last);
- UHCI_INST (controller)->qh_data->headlinkptr.queue_head = 1;
- UHCI_INST (controller)->qh_data->elementlinkptr.ptr = 0;
- UHCI_INST (controller)->qh_data->elementlinkptr.terminate = 1;
-
- UHCI_INST (controller)->qh_last->headlinkptr.ptr = virt_to_phys (UHCI_INST (controller)->qh_data);
- UHCI_INST (controller)->qh_last->headlinkptr.terminate = 1;
- UHCI_INST (controller)->qh_last->elementlinkptr.ptr = virt_to_phys (antiberserk);
- UHCI_INST (controller)->qh_last->elementlinkptr.terminate = 1;
+ fatal("Not enough memory for USB controller queues.\n");
+
+ UHCI_INST (controller)->qh_prei->headlinkptr =
+ virt_to_phys (UHCI_INST (controller)->qh_intr) | FLISTP_QH;
+ UHCI_INST (controller)->qh_prei->elementlinkptr = 0 | FLISTP_TERMINATE;
+
+ UHCI_INST (controller)->qh_intr->headlinkptr =
+ virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_QH;
+ UHCI_INST (controller)->qh_intr->elementlinkptr = 0 | FLISTP_TERMINATE;
+
+ UHCI_INST (controller)->qh_data->headlinkptr =
+ virt_to_phys (UHCI_INST (controller)->qh_last) | FLISTP_QH;
+ UHCI_INST (controller)->qh_data->elementlinkptr = 0 | FLISTP_TERMINATE;
+
+ UHCI_INST (controller)->qh_last->headlinkptr = virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_TERMINATE;
+ UHCI_INST (controller)->qh_last->elementlinkptr = virt_to_phys (antiberserk) | FLISTP_TERMINATE;
for (i = 0; i < 1024; i++) {
- UHCI_INST (controller)->framelistptr[i].ptr =
- virt_to_phys (UHCI_INST (controller)->qh_prei);
- UHCI_INST (controller)->framelistptr[i].terminate = 0;
- UHCI_INST (controller)->framelistptr[i].queue_head = 1;
+ UHCI_INST (controller)->framelistptr[i] =
+ virt_to_phys (UHCI_INST (controller)->qh_prei) | FLISTP_QH;
}
controller->devices[0]->controller = controller;
controller->devices[0]->init = uhci_rh_init;
detach_controller (controller);
UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)->
roothub);
- uhci_reg_mask16 (controller, USBCMD, 0, 0); // stop work
+ uhci_reg_write16(controller, USBCMD,
+ uhci_reg_read16(controller, USBCMD) & 0); // stop work
free (UHCI_INST (controller)->framelistptr);
free (UHCI_INST (controller)->qh_prei);
free (UHCI_INST (controller)->qh_intr);
static void
uhci_start (hci_t *controller)
{
- uhci_reg_mask16 (controller, USBCMD, ~0, 1); // start work on schedule
+ uhci_reg_write16(controller, USBCMD,
+ uhci_reg_read16(controller, USBCMD) | 1); // start work on schedule
}
static void
uhci_stop (hci_t *controller)
{
- uhci_reg_mask16 (controller, USBCMD, ~1, 0); // stop work on schedule
+ uhci_reg_write16(controller, USBCMD,
+ uhci_reg_read16(controller, USBCMD) & ~1); // stop work on schedule
}
#define GET_TD(x) ((void*)(((unsigned int)(x))&~0xf))
wait_for_completed_qh (hci_t *controller, qh_t *qh)
{
int timeout = 1000000; /* max 30 ms. */
- void *current = GET_TD (qh->elementlinkptr.ptr);
- while ((qh->elementlinkptr.terminate == 0) && (timeout-- > 0)) {
- if (current != GET_TD (qh->elementlinkptr.ptr)) {
- current = GET_TD (qh->elementlinkptr.ptr);
+ void *current = GET_TD (qh->elementlinkptr);
+ while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) {
+ if (current != GET_TD (qh->elementlinkptr)) {
+ current = GET_TD (qh->elementlinkptr);
timeout = 1000000;
}
- uhci_reg_mask16 (controller, USBSTS, ~0, 0); // clear resettable registers
+ uhci_reg_write16(controller, USBSTS,
+ uhci_reg_read16(controller, USBSTS) | 0); // clear resettable registers
udelay (30);
}
- return (GET_TD (qh->elementlinkptr.ptr) ==
- 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);
- }
+ return (GET_TD (qh->elementlinkptr) ==
+ 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr));
}
static int
}
static int
-uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen,
+uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen,
unsigned char *data)
{
int endp = 0; /* this is control: always 0 */
memset (tds, 0, sizeof (td_t) * count);
count--; /* to compensate for 0-indexed array */
for (i = 0; i < count; i++) {
- tds[i].ptr = virt_to_phys (&tds[i + 1]);
- tds[i].depth_first = 1;
- tds[i].terminate = 0;
+ tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
}
- tds[count].ptr = 0;
- tds[count].depth_first = 1;
- tds[count].terminate = 1;
-
- tds[0].pid = SETUP;
- tds[0].dev_addr = dev->address;
- tds[0].endp = endp;
- tds[0].maxlen = maxlen (drlen);
- tds[0].counter = 3;
- tds[0].data_toggle = 0;
- tds[0].lowspeed = dev->lowspeed;
+ tds[count].ptr = 0 | TD_DEPTH_FIRST | TD_TERMINATE;
+
+ tds[0].token = UHCI_SETUP |
+ dev->address << TD_DEVADDR_SHIFT |
+ endp << TD_EP_SHIFT |
+ TD_TOGGLE_DATA0 |
+ maxlen(drlen) << TD_MAXLEN_SHIFT;
tds[0].bufptr = virt_to_phys (devreq);
- tds[0].status_active = 1;
+ tds[0].ctrlsts = (3 << TD_COUNTER_SHIFT) |
+ (dev->speed?TD_LOWSPEED:0) |
+ TD_STATUS_ACTIVE;
int toggle = 1;
for (i = 1; i < count; i++) {
- tds[i].pid = dir;
- tds[i].dev_addr = dev->address;
- tds[i].endp = endp;
- tds[i].maxlen = maxlen (min (mlen, dalen));
- tds[i].counter = 3;
- tds[i].data_toggle = toggle;
- tds[i].lowspeed = dev->lowspeed;
+ switch (dir) {
+ case SETUP: tds[i].token = UHCI_SETUP; break;
+ case IN: tds[i].token = UHCI_IN; break;
+ case OUT: tds[i].token = UHCI_OUT; break;
+ }
+ tds[i].token |= dev->address << TD_DEVADDR_SHIFT |
+ endp << TD_EP_SHIFT |
+ maxlen (min (mlen, dalen)) << TD_MAXLEN_SHIFT |
+ toggle << TD_TOGGLE_SHIFT;
tds[i].bufptr = virt_to_phys (data);
- tds[i].status_active = 1;
+ tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) |
+ (dev->speed?TD_LOWSPEED:0) |
+ TD_STATUS_ACTIVE;
toggle ^= 1;
dalen -= mlen;
data += mlen;
}
- tds[count].pid = (dir == OUT) ? IN : OUT;
- tds[count].dev_addr = dev->address;
- tds[count].endp = endp;
- 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].status_active = 1;
- UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
- virt_to_phys (tds);
- UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
- UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
+ tds[count].token = (dir == OUT) ? UHCI_IN : UHCI_OUT |
+ dev->address << TD_DEVADDR_SHIFT |
+ endp << TD_EP_SHIFT |
+ maxlen(0) << TD_MAXLEN_SHIFT |
+ TD_TOGGLE_DATA1;
+ tds[count].bufptr = 0;
+ tds[0].ctrlsts = (0 << TD_COUNTER_SHIFT) | /* as Linux 2.4.10 does */
+ (dev->speed?TD_LOWSPEED:0) |
+ TD_STATUS_ACTIVE;
+ UHCI_INST (dev->controller)->qh_data->elementlinkptr =
+ virt_to_phys (tds) & ~(FLISTP_QH | FLISTP_TERMINATE);
td_t *td = wait_for_completed_qh (dev->controller,
UHCI_INST (dev->controller)->
qh_data);
if (td == 0) {
result = 0;
} else {
- printf ("control packet, req %x\n", req);
+ debug ("control packet, req %x\n", req);
td_dump (td);
result = 1;
}
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)
{
memset (tds, 0, sizeof (td_t) * numpackets);
int i;
for (i = 0; i < numpackets; i++) {
- tds[i].ptr = virt_to_phys (&tds[i + 1]);
- tds[i].terminate = 0;
- tds[i].queue_head = 0;
- tds[i].depth_first = 1;
+ tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
}
- tds[numpackets - 1].ptr = 0;
- tds[numpackets - 1].terminate = 1;
- tds[numpackets - 1].queue_head = 0;
- tds[numpackets - 1].depth_first = 0;
+ tds[numpackets - 1].ptr = 0 | TD_TERMINATE;
return tds;
}
fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data,
int *toggle)
{
- td->pid = ep->direction;
- td->dev_addr = ep->dev->address;
- td->endp = ep->endpoint & 0xf;
- td->maxlen = maxlen (length);
- if (ep->direction == SETUP)
- td->counter = 3;
- else
- td->counter = 0;
- td->data_toggle = *toggle & 1;
- td->lowspeed = ep->dev->lowspeed;
+ switch (ep->direction) {
+ case IN: td->token = UHCI_IN; break;
+ case OUT: td->token = UHCI_OUT; break;
+ case SETUP: td->token = UHCI_SETUP; break;
+ }
+ td->token |= ep->dev->address << TD_DEVADDR_SHIFT |
+ (ep->endpoint & 0xf) << TD_EP_SHIFT |
+ maxlen (length) << TD_MAXLEN_SHIFT |
+ (*toggle & 1) << TD_TOGGLE_SHIFT;
td->bufptr = virt_to_phys (data);
-
- td->status_active = 1;
+ td->ctrlsts = ((ep->direction == SETUP?3:0) << TD_COUNTER_SHIFT) |
+ ep->dev->speed?TD_LOWSPEED:0 |
+ TD_STATUS_ACTIVE;
*toggle ^= 1;
}
static int
run_schedule (usbdev_t *dev, td_t *td)
{
- 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;
+ UHCI_INST (dev->controller)->qh_data->elementlinkptr =
+ virt_to_phys (td) | ~(FLISTP_QH | FLISTP_TERMINATE);
td = wait_for_completed_qh (dev->controller,
UHCI_INST (dev->controller)->qh_data);
if (td == 0) {
{
int maxpsize = ep->maxpacketsize;
if (maxpsize == 0)
- fatal ("MaxPacketSize == 0!!!");
+ fatal("MaxPacketSize == 0!!!");
int numpackets = (size + maxpsize - 1 + finalize) / maxpsize;
if (numpackets == 0)
return 0;
size -= maxpsize;
}
if (run_schedule (ep->dev, tds) == 1) {
+ debug("Stalled. Trying to clean up.\n");
clear_stall (ep);
free (tds);
return 1;
qh_t *qh = memalign(16, sizeof(qh_t));
if (!data || !tds || !qh)
- usb_fatal ("Not enough memory to create USB intr queue prerequisites.\n");
+ fatal("Not enough memory to create USB intr queue prerequisites.\n");
- qh->elementlinkptr.ptr = virt_to_phys(tds);
- qh->elementlinkptr.queue_head = 0;
- qh->elementlinkptr.terminate = 0;
+ qh->elementlinkptr = virt_to_phys(tds);
intr_q *q = malloc(sizeof(intr_q));
if (!q)
- usb_fatal ("Not enough memory to create USB intr queue.\n");
+ fatal("Not enough memory to create USB intr queue.\n");
q->qh = qh;
q->tds = tds;
q->data = data;
int i;
for (i = 0; i < reqcount; i++) {
tds[i].ptr = virt_to_phys (&tds[i + 1]);
- tds[i].terminate = 0;
- tds[i].queue_head = 0;
- tds[i].depth_first = 0;
-
- tds[i].pid = ep->direction;
- tds[i].dev_addr = ep->dev->address;
- tds[i].endp = ep->endpoint & 0xf;
- tds[i].maxlen = maxlen (reqsize);
- tds[i].counter = 0;
- tds[i].data_toggle = ep->toggle & 1;
- tds[i].lowspeed = ep->dev->lowspeed;
+
+ switch (ep->direction) {
+ case IN: tds[i].token = UHCI_IN; break;
+ case OUT: tds[i].token = UHCI_OUT; break;
+ case SETUP: tds[i].token = UHCI_SETUP; break;
+ }
+ tds[i].token |= ep->dev->address << TD_DEVADDR_SHIFT |
+ (ep->endpoint & 0xf) << TD_EP_SHIFT |
+ maxlen (reqsize) << TD_MAXLEN_SHIFT |
+ (ep->toggle & 1) << TD_TOGGLE_SHIFT;
tds[i].bufptr = virt_to_phys (data);
- tds[i].status_active = 1;
+ tds[i].ctrlsts = (0 << TD_COUNTER_SHIFT) |
+ ep->dev->speed?TD_LOWSPEED:0 |
+ TD_STATUS_ACTIVE;
ep->toggle ^= 1;
data += reqsize;
}
- tds[reqcount - 1].ptr = 0;
- tds[reqcount - 1].terminate = 1;
- tds[reqcount - 1].queue_head = 0;
- tds[reqcount - 1].depth_first = 0;
+ tds[reqcount - 1].ptr = 0 | TD_TERMINATE;
for (i = reqtiming; i < 1024; i += reqtiming) {
/* FIXME: wrap in another qh, one for each occurance of the qh in the framelist */
- qh->headlinkptr.ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
- qh->headlinkptr.terminate = 0;
- UHCI_INST (ep->dev->controller)->framelistptr[i].ptr = virt_to_phys(qh);
- UHCI_INST (ep->dev->controller)->framelistptr[i].terminate = 0;
- UHCI_INST (ep->dev->controller)->framelistptr[i].queue_head = 1;
+ qh->headlinkptr = UHCI_INST (ep->dev->controller)->framelistptr[i] & ~FLISTP_TERMINATE;
+ UHCI_INST (ep->dev->controller)->framelistptr[i] = virt_to_phys(qh) | FLISTP_QH;
}
return q;
}
int i;
for (i=0; i<1024; i++) {
u32 oldptr = 0;
- u32 ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
+ u32 ptr = UHCI_INST (ep->dev->controller)->framelistptr[i];
while (ptr != end) {
- if (((qh_t*)phys_to_virt(ptr))->elementlinkptr.ptr == val) {
- ((qh_t*)phys_to_virt(oldptr))->headlinkptr.ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
+ if (((qh_t*)phys_to_virt(ptr))->elementlinkptr == val) {
+ ((qh_t*)phys_to_virt(oldptr))->headlinkptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
free(phys_to_virt(ptr));
break;
}
oldptr = ptr;
- ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
+ ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
}
}
free(q->data);
uhci_poll_intr_queue (void *q_)
{
intr_q *q = (intr_q*)q_;
- if (q->tds[q->lastread].status_active == 0) {
+ if ((q->tds[q->lastread].ctrlsts & TD_STATUS_ACTIVE) == 0) {
/* FIXME: handle errors */
int current = q->lastread;
int previous;
} else {
previous = q->lastread - 1;
}
- q->tds[previous].status = 0;
- q->tds[previous].ptr = 0;
- q->tds[previous].terminate = 1;
+ q->tds[previous].ctrlsts &= ~TD_STATUS_MASK;
+ q->tds[previous].ptr = 0 | TD_TERMINATE;
if (q->last_td != &q->tds[previous]) {
- q->last_td->ptr = virt_to_phys(&q->tds[previous]);
- q->last_td->terminate = 0;
+ q->last_td->ptr = virt_to_phys(&q->tds[previous]) & ~TD_TERMINATE;
q->last_td = &q->tds[previous];
}
- q->tds[previous].status_active = 1;
+ q->tds[previous].ctrlsts |= TD_STATUS_ACTIVE;
q->lastread = (q->lastread + 1) % q->total;
return &q->data[current*q->reqsize];
}
{
return inb (ctrl->reg_base + reg);
}
-
-void
-uhci_reg_mask32 (hci_t *ctrl, usbreg reg, u32 andmask, u32 ormask)
-{
- uhci_reg_write32 (ctrl, reg,
- (uhci_reg_read32 (ctrl, reg) & andmask) | ormask);
-}
-
-void
-uhci_reg_mask16 (hci_t *ctrl, usbreg reg, u16 andmask, u16 ormask)
-{
- uhci_reg_write16 (ctrl, reg,
- (uhci_reg_read16 (ctrl, reg) & andmask) | ormask);
-}
-
-void
-uhci_reg_mask8 (hci_t *ctrl, usbreg reg, u8 andmask, u8 ormask)
-{
- uhci_reg_write8 (ctrl, reg,
- (uhci_reg_read8 (ctrl, reg) & andmask) | ormask);
-}