libpayload: Remove bitfield use from UHCI data structures
We agreed that bitfields are a Bad Idea[tm]. Change-Id: I1b2bcda28c52ad10bbe9429e04d126b555f7828a Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com> Reviewed-on: http://review.coreboot.org/478 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-by: Peter Stuge <peter@stuge.se>
This commit is contained in:
committed by
Peter Stuge
parent
c4348d0a44
commit
b0b4a52b70
@@ -66,7 +66,7 @@ td_dump (td_t *td)
|
|||||||
{
|
{
|
||||||
char td_value[3];
|
char td_value[3];
|
||||||
const char *td_type;
|
const char *td_type;
|
||||||
switch (td->pid) {
|
switch (td->token & TD_PID_MASK) {
|
||||||
case UHCI_SETUP:
|
case UHCI_SETUP:
|
||||||
td_type="SETUP";
|
td_type="SETUP";
|
||||||
break;
|
break;
|
||||||
@@ -77,23 +77,24 @@ td_dump (td_t *td)
|
|||||||
td_type="OUT";
|
td_type="OUT";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(td_value, "%x", td->pid);
|
sprintf(td_value, "%x", td->token & TD_PID_MASK);
|
||||||
td_type=td_value;
|
td_type=td_value;
|
||||||
}
|
}
|
||||||
debug ("%s packet (at %lx) to %x.%x failed\n", td_type,
|
debug ("%s packet (at %lx) to %x.%x failed\n", td_type,
|
||||||
virt_to_phys (td), td->dev_addr, td->endp);
|
virt_to_phys (td), (td->token & TD_DEVADDR_MASK) >> TD_DEVADDR_SHIFT,
|
||||||
debug ("td (counter at %x) returns: ", td->counter);
|
(td->token & TD_EP_MASK) >> TD_EP_SHIFT);
|
||||||
debug (" bitstuff err: %x, ", td->status_bitstuff_err);
|
debug ("td (counter at %x) returns: ", td->ctrlsts >> TD_COUNTER_SHIFT);
|
||||||
debug (" CRC err: %x, ", td->status_crc_err);
|
debug (" bitstuff err: %x, ", !!(td->ctrlsts & TD_STATUS_BITSTUFF_ERR));
|
||||||
debug (" NAK rcvd: %x, ", td->status_nakrcvd);
|
debug (" CRC err: %x, ", !!(td->ctrlsts & TD_STATUS_CRC_ERR));
|
||||||
debug (" Babble: %x, ", td->status_babble);
|
debug (" NAK rcvd: %x, ", !!(td->ctrlsts & TD_STATUS_NAK_RCVD));
|
||||||
debug (" Data Buffer err: %x, ", td->status_databuf_err);
|
debug (" Babble: %x, ", !!(td->ctrlsts & TD_STATUS_BABBLE));
|
||||||
debug (" Stalled: %x, ", td->status_stalled);
|
debug (" Data Buffer err: %x, ", !!(td->ctrlsts & TD_STATUS_DATABUF_ERR));
|
||||||
debug (" Active: %x\n", td->status_active);
|
debug (" Stalled: %x, ", !!(td->ctrlsts & TD_STATUS_STALLED));
|
||||||
if (td->status_babble)
|
debug (" Active: %x\n", !!(td->ctrlsts & TD_STATUS_ACTIVE));
|
||||||
|
if (td->ctrlsts & TD_STATUS_BABBLE)
|
||||||
debug (" Babble because of %s\n",
|
debug (" Babble because of %s\n",
|
||||||
td->status_bitstuff_err ? "host" : "device");
|
(td->ctrlsts & TD_STATUS_BITSTUFF_ERR) ? "host" : "device");
|
||||||
if (td->status_active)
|
if (td->ctrlsts & TD_STATUS_ACTIVE)
|
||||||
debug (" still active - timeout?\n");
|
debug (" still active - timeout?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,34 +198,24 @@ uhci_init (pcidev_t addr)
|
|||||||
! UHCI_INST (controller)->qh_last)
|
! UHCI_INST (controller)->qh_last)
|
||||||
fatal("Not enough memory for USB controller queues.\n");
|
fatal("Not enough memory for USB controller queues.\n");
|
||||||
|
|
||||||
UHCI_INST (controller)->qh_prei->headlinkptr.ptr =
|
UHCI_INST (controller)->qh_prei->headlinkptr =
|
||||||
virt_to_phys (UHCI_INST (controller)->qh_intr);
|
virt_to_phys (UHCI_INST (controller)->qh_intr) | FLISTP_QH;
|
||||||
UHCI_INST (controller)->qh_prei->headlinkptr.queue_head = 1;
|
UHCI_INST (controller)->qh_prei->elementlinkptr = 0 | FLISTP_TERMINATE;
|
||||||
UHCI_INST (controller)->qh_prei->elementlinkptr.ptr = 0;
|
|
||||||
UHCI_INST (controller)->qh_prei->elementlinkptr.terminate = 1;
|
|
||||||
|
|
||||||
UHCI_INST (controller)->qh_intr->headlinkptr.ptr =
|
UHCI_INST (controller)->qh_intr->headlinkptr =
|
||||||
virt_to_phys (UHCI_INST (controller)->qh_data);
|
virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_QH;
|
||||||
UHCI_INST (controller)->qh_intr->headlinkptr.queue_head = 1;
|
UHCI_INST (controller)->qh_intr->elementlinkptr = 0 | FLISTP_TERMINATE;
|
||||||
UHCI_INST (controller)->qh_intr->elementlinkptr.ptr = 0;
|
|
||||||
UHCI_INST (controller)->qh_intr->elementlinkptr.terminate = 1;
|
|
||||||
|
|
||||||
UHCI_INST (controller)->qh_data->headlinkptr.ptr =
|
UHCI_INST (controller)->qh_data->headlinkptr =
|
||||||
virt_to_phys (UHCI_INST (controller)->qh_last);
|
virt_to_phys (UHCI_INST (controller)->qh_last) | FLISTP_QH;
|
||||||
UHCI_INST (controller)->qh_data->headlinkptr.queue_head = 1;
|
UHCI_INST (controller)->qh_data->elementlinkptr = 0 | FLISTP_TERMINATE;
|
||||||
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 = virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_TERMINATE;
|
||||||
UHCI_INST (controller)->qh_last->headlinkptr.terminate = 1;
|
UHCI_INST (controller)->qh_last->elementlinkptr = virt_to_phys (antiberserk) | FLISTP_TERMINATE;
|
||||||
UHCI_INST (controller)->qh_last->elementlinkptr.ptr = virt_to_phys (antiberserk);
|
|
||||||
UHCI_INST (controller)->qh_last->elementlinkptr.terminate = 1;
|
|
||||||
|
|
||||||
for (i = 0; i < 1024; i++) {
|
for (i = 0; i < 1024; i++) {
|
||||||
UHCI_INST (controller)->framelistptr[i].ptr =
|
UHCI_INST (controller)->framelistptr[i] =
|
||||||
virt_to_phys (UHCI_INST (controller)->qh_prei);
|
virt_to_phys (UHCI_INST (controller)->qh_prei) | FLISTP_QH;
|
||||||
UHCI_INST (controller)->framelistptr[i].terminate = 0;
|
|
||||||
UHCI_INST (controller)->framelistptr[i].queue_head = 1;
|
|
||||||
}
|
}
|
||||||
controller->devices[0]->controller = controller;
|
controller->devices[0]->controller = controller;
|
||||||
controller->devices[0]->init = uhci_rh_init;
|
controller->devices[0]->init = uhci_rh_init;
|
||||||
@@ -272,18 +263,18 @@ static td_t *
|
|||||||
wait_for_completed_qh (hci_t *controller, qh_t *qh)
|
wait_for_completed_qh (hci_t *controller, qh_t *qh)
|
||||||
{
|
{
|
||||||
int timeout = 1000000; /* max 30 ms. */
|
int timeout = 1000000; /* max 30 ms. */
|
||||||
void *current = GET_TD (qh->elementlinkptr.ptr);
|
void *current = GET_TD (qh->elementlinkptr);
|
||||||
while ((qh->elementlinkptr.terminate == 0) && (timeout-- > 0)) {
|
while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) {
|
||||||
if (current != GET_TD (qh->elementlinkptr.ptr)) {
|
if (current != GET_TD (qh->elementlinkptr)) {
|
||||||
current = GET_TD (qh->elementlinkptr.ptr);
|
current = GET_TD (qh->elementlinkptr);
|
||||||
timeout = 1000000;
|
timeout = 1000000;
|
||||||
}
|
}
|
||||||
uhci_reg_write16(controller, USBSTS,
|
uhci_reg_write16(controller, USBSTS,
|
||||||
uhci_reg_read16(controller, USBSTS) | 0); // clear resettable registers
|
uhci_reg_read16(controller, USBSTS) | 0); // clear resettable registers
|
||||||
udelay (30);
|
udelay (30);
|
||||||
}
|
}
|
||||||
return (GET_TD (qh->elementlinkptr.ptr) ==
|
return (GET_TD (qh->elementlinkptr) ==
|
||||||
0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr.ptr));
|
0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -314,57 +305,51 @@ uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen
|
|||||||
memset (tds, 0, sizeof (td_t) * count);
|
memset (tds, 0, sizeof (td_t) * count);
|
||||||
count--; /* to compensate for 0-indexed array */
|
count--; /* to compensate for 0-indexed array */
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
tds[i].ptr = virt_to_phys (&tds[i + 1]);
|
tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
|
||||||
tds[i].depth_first = 1;
|
|
||||||
tds[i].terminate = 0;
|
|
||||||
}
|
}
|
||||||
tds[count].ptr = 0;
|
tds[count].ptr = 0 | TD_DEPTH_FIRST | TD_TERMINATE;
|
||||||
tds[count].depth_first = 1;
|
|
||||||
tds[count].terminate = 1;
|
|
||||||
|
|
||||||
tds[0].pid = UHCI_SETUP;
|
tds[0].token = UHCI_SETUP |
|
||||||
tds[0].dev_addr = dev->address;
|
dev->address << TD_DEVADDR_SHIFT |
|
||||||
tds[0].endp = endp;
|
endp << TD_EP_SHIFT |
|
||||||
tds[0].maxlen = maxlen (drlen);
|
TD_TOGGLE_DATA0 |
|
||||||
tds[0].counter = 3;
|
maxlen(drlen) << TD_MAXLEN_SHIFT;
|
||||||
tds[0].data_toggle = 0;
|
|
||||||
tds[0].lowspeed = dev->speed;
|
|
||||||
tds[0].bufptr = virt_to_phys (devreq);
|
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;
|
int toggle = 1;
|
||||||
for (i = 1; i < count; i++) {
|
for (i = 1; i < count; i++) {
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case SETUP: tds[i].pid = UHCI_SETUP; break;
|
case SETUP: tds[i].token = UHCI_SETUP; break;
|
||||||
case IN: tds[i].pid = UHCI_IN; break;
|
case IN: tds[i].token = UHCI_IN; break;
|
||||||
case OUT: tds[i].pid = UHCI_OUT; break;
|
case OUT: tds[i].token = UHCI_OUT; break;
|
||||||
}
|
}
|
||||||
tds[i].dev_addr = dev->address;
|
tds[i].token |= dev->address << TD_DEVADDR_SHIFT |
|
||||||
tds[i].endp = endp;
|
endp << TD_EP_SHIFT |
|
||||||
tds[i].maxlen = maxlen (min (mlen, dalen));
|
maxlen (min (mlen, dalen)) << TD_MAXLEN_SHIFT |
|
||||||
tds[i].counter = 3;
|
toggle << TD_TOGGLE_SHIFT;
|
||||||
tds[i].data_toggle = toggle;
|
|
||||||
tds[i].lowspeed = dev->speed;
|
|
||||||
tds[i].bufptr = virt_to_phys (data);
|
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;
|
toggle ^= 1;
|
||||||
dalen -= mlen;
|
dalen -= mlen;
|
||||||
data += mlen;
|
data += mlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
tds[count].pid = (dir == OUT) ? UHCI_IN : UHCI_OUT;
|
tds[count].token = (dir == OUT) ? UHCI_IN : UHCI_OUT |
|
||||||
tds[count].dev_addr = dev->address;
|
dev->address << TD_DEVADDR_SHIFT |
|
||||||
tds[count].endp = endp;
|
endp << TD_EP_SHIFT |
|
||||||
tds[count].maxlen = maxlen (0);
|
maxlen(0) << TD_MAXLEN_SHIFT |
|
||||||
tds[count].counter = 0; /* as per linux 2.4.10 */
|
TD_TOGGLE_DATA1;
|
||||||
tds[count].data_toggle = 1;
|
|
||||||
tds[count].lowspeed = dev->speed;
|
|
||||||
tds[count].bufptr = 0;
|
tds[count].bufptr = 0;
|
||||||
tds[count].status_active = 1;
|
tds[0].ctrlsts = (0 << TD_COUNTER_SHIFT) | /* as Linux 2.4.10 does */
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
|
(dev->speed?TD_LOWSPEED:0) |
|
||||||
virt_to_phys (tds);
|
TD_STATUS_ACTIVE;
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
|
UHCI_INST (dev->controller)->qh_data->elementlinkptr =
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
|
virt_to_phys (tds) & ~(FLISTP_QH | FLISTP_TERMINATE);
|
||||||
td_t *td = wait_for_completed_qh (dev->controller,
|
td_t *td = wait_for_completed_qh (dev->controller,
|
||||||
UHCI_INST (dev->controller)->
|
UHCI_INST (dev->controller)->
|
||||||
qh_data);
|
qh_data);
|
||||||
@@ -389,15 +374,9 @@ create_schedule (int numpackets)
|
|||||||
memset (tds, 0, sizeof (td_t) * numpackets);
|
memset (tds, 0, sizeof (td_t) * numpackets);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < numpackets; i++) {
|
for (i = 0; i < numpackets; i++) {
|
||||||
tds[i].ptr = virt_to_phys (&tds[i + 1]);
|
tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
|
||||||
tds[i].terminate = 0;
|
|
||||||
tds[i].queue_head = 0;
|
|
||||||
tds[i].depth_first = 1;
|
|
||||||
}
|
}
|
||||||
tds[numpackets - 1].ptr = 0;
|
tds[numpackets - 1].ptr = 0 | TD_TERMINATE;
|
||||||
tds[numpackets - 1].terminate = 1;
|
|
||||||
tds[numpackets - 1].queue_head = 0;
|
|
||||||
tds[numpackets - 1].depth_first = 0;
|
|
||||||
return tds;
|
return tds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,32 +385,26 @@ fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data,
|
|||||||
int *toggle)
|
int *toggle)
|
||||||
{
|
{
|
||||||
switch (ep->direction) {
|
switch (ep->direction) {
|
||||||
case IN: td->pid = UHCI_IN; break;
|
case IN: td->token = UHCI_IN; break;
|
||||||
case OUT: td->pid = UHCI_OUT; break;
|
case OUT: td->token = UHCI_OUT; break;
|
||||||
case SETUP: td->pid = UHCI_SETUP; break;
|
case SETUP: td->token = UHCI_SETUP; break;
|
||||||
}
|
}
|
||||||
td->dev_addr = ep->dev->address;
|
td->token |= ep->dev->address << TD_DEVADDR_SHIFT |
|
||||||
td->endp = ep->endpoint & 0xf;
|
(ep->endpoint & 0xf) << TD_EP_SHIFT |
|
||||||
td->maxlen = maxlen (length);
|
maxlen (length) << TD_MAXLEN_SHIFT |
|
||||||
if (ep->direction == SETUP)
|
(*toggle & 1) << TD_TOGGLE_SHIFT;
|
||||||
td->counter = 3;
|
|
||||||
else
|
|
||||||
td->counter = 0;
|
|
||||||
td->data_toggle = *toggle & 1;
|
|
||||||
td->lowspeed = ep->dev->speed;
|
|
||||||
td->bufptr = virt_to_phys (data);
|
td->bufptr = virt_to_phys (data);
|
||||||
|
td->ctrlsts = ((ep->direction == SETUP?3:0) << TD_COUNTER_SHIFT) |
|
||||||
td->status_active = 1;
|
ep->dev->speed?TD_LOWSPEED:0 |
|
||||||
|
TD_STATUS_ACTIVE;
|
||||||
*toggle ^= 1;
|
*toggle ^= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
run_schedule (usbdev_t *dev, td_t *td)
|
run_schedule (usbdev_t *dev, td_t *td)
|
||||||
{
|
{
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
|
UHCI_INST (dev->controller)->qh_data->elementlinkptr =
|
||||||
virt_to_phys (td);
|
virt_to_phys (td) | ~(FLISTP_QH | FLISTP_TERMINATE);
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
|
|
||||||
UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
|
|
||||||
td = wait_for_completed_qh (dev->controller,
|
td = wait_for_completed_qh (dev->controller,
|
||||||
UHCI_INST (dev->controller)->qh_data);
|
UHCI_INST (dev->controller)->qh_data);
|
||||||
if (td == 0) {
|
if (td == 0) {
|
||||||
@@ -493,9 +466,7 @@ uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming
|
|||||||
if (!data || !tds || !qh)
|
if (!data || !tds || !qh)
|
||||||
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 = virt_to_phys(tds);
|
||||||
qh->elementlinkptr.queue_head = 0;
|
|
||||||
qh->elementlinkptr.terminate = 0;
|
|
||||||
|
|
||||||
intr_q *q = malloc(sizeof(intr_q));
|
intr_q *q = malloc(sizeof(intr_q));
|
||||||
if (!q)
|
if (!q)
|
||||||
@@ -512,37 +483,28 @@ uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming
|
|||||||
int i;
|
int i;
|
||||||
for (i = 0; i < reqcount; i++) {
|
for (i = 0; i < reqcount; i++) {
|
||||||
tds[i].ptr = virt_to_phys (&tds[i + 1]);
|
tds[i].ptr = virt_to_phys (&tds[i + 1]);
|
||||||
tds[i].terminate = 0;
|
|
||||||
tds[i].queue_head = 0;
|
|
||||||
tds[i].depth_first = 0;
|
|
||||||
|
|
||||||
switch (ep->direction) {
|
switch (ep->direction) {
|
||||||
case IN: tds[i].pid = UHCI_IN; break;
|
case IN: tds[i].token = UHCI_IN; break;
|
||||||
case OUT: tds[i].pid = UHCI_OUT; break;
|
case OUT: tds[i].token = UHCI_OUT; break;
|
||||||
case SETUP: tds[i].pid = UHCI_SETUP; break;
|
case SETUP: tds[i].token = UHCI_SETUP; break;
|
||||||
}
|
}
|
||||||
tds[i].dev_addr = ep->dev->address;
|
tds[i].token |= ep->dev->address << TD_DEVADDR_SHIFT |
|
||||||
tds[i].endp = ep->endpoint & 0xf;
|
(ep->endpoint & 0xf) << TD_EP_SHIFT |
|
||||||
tds[i].maxlen = maxlen (reqsize);
|
maxlen (reqsize) << TD_MAXLEN_SHIFT |
|
||||||
tds[i].counter = 0;
|
(ep->toggle & 1) << TD_TOGGLE_SHIFT;
|
||||||
tds[i].data_toggle = ep->toggle & 1;
|
|
||||||
tds[i].lowspeed = ep->dev->speed;
|
|
||||||
tds[i].bufptr = virt_to_phys (data);
|
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;
|
ep->toggle ^= 1;
|
||||||
data += reqsize;
|
data += reqsize;
|
||||||
}
|
}
|
||||||
tds[reqcount - 1].ptr = 0;
|
tds[reqcount - 1].ptr = 0 | TD_TERMINATE;
|
||||||
tds[reqcount - 1].terminate = 1;
|
|
||||||
tds[reqcount - 1].queue_head = 0;
|
|
||||||
tds[reqcount - 1].depth_first = 0;
|
|
||||||
for (i = reqtiming; i < 1024; i += reqtiming) {
|
for (i = reqtiming; i < 1024; i += reqtiming) {
|
||||||
/* FIXME: wrap in another qh, one for each occurance of the qh in the framelist */
|
/* 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 = UHCI_INST (ep->dev->controller)->framelistptr[i] & ~FLISTP_TERMINATE;
|
||||||
qh->headlinkptr.terminate = 0;
|
UHCI_INST (ep->dev->controller)->framelistptr[i] = virt_to_phys(qh) | FLISTP_QH;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
@@ -557,15 +519,15 @@ uhci_destroy_intr_queue (endpoint_t *ep, void *q_)
|
|||||||
int i;
|
int i;
|
||||||
for (i=0; i<1024; i++) {
|
for (i=0; i<1024; i++) {
|
||||||
u32 oldptr = 0;
|
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) {
|
while (ptr != end) {
|
||||||
if (((qh_t*)phys_to_virt(ptr))->elementlinkptr.ptr == val) {
|
if (((qh_t*)phys_to_virt(ptr))->elementlinkptr == val) {
|
||||||
((qh_t*)phys_to_virt(oldptr))->headlinkptr.ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
|
((qh_t*)phys_to_virt(oldptr))->headlinkptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
|
||||||
free(phys_to_virt(ptr));
|
free(phys_to_virt(ptr));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
oldptr = ptr;
|
oldptr = ptr;
|
||||||
ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
|
ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(q->data);
|
free(q->data);
|
||||||
@@ -582,7 +544,7 @@ static u8*
|
|||||||
uhci_poll_intr_queue (void *q_)
|
uhci_poll_intr_queue (void *q_)
|
||||||
{
|
{
|
||||||
intr_q *q = (intr_q*)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 */
|
/* FIXME: handle errors */
|
||||||
int current = q->lastread;
|
int current = q->lastread;
|
||||||
int previous;
|
int previous;
|
||||||
@@ -591,15 +553,13 @@ uhci_poll_intr_queue (void *q_)
|
|||||||
} else {
|
} else {
|
||||||
previous = q->lastread - 1;
|
previous = q->lastread - 1;
|
||||||
}
|
}
|
||||||
q->tds[previous].status = 0;
|
q->tds[previous].ctrlsts &= ~TD_STATUS_MASK;
|
||||||
q->tds[previous].ptr = 0;
|
q->tds[previous].ptr = 0 | TD_TERMINATE;
|
||||||
q->tds[previous].terminate = 1;
|
|
||||||
if (q->last_td != &q->tds[previous]) {
|
if (q->last_td != &q->tds[previous]) {
|
||||||
q->last_td->ptr = virt_to_phys(&q->tds[previous]);
|
q->last_td->ptr = virt_to_phys(&q->tds[previous]) & ~TD_TERMINATE;
|
||||||
q->last_td->terminate = 0;
|
|
||||||
q->last_td = &q->tds[previous];
|
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;
|
q->lastread = (q->lastread + 1) % q->total;
|
||||||
return &q->data[current*q->reqsize];
|
return &q->data[current*q->reqsize];
|
||||||
}
|
}
|
||||||
|
@@ -32,55 +32,38 @@
|
|||||||
|
|
||||||
typedef enum { UHCI_SETUP = 0x2d, UHCI_IN = 0x69, UHCI_OUT = 0xe1 } uhci_pid_t;
|
typedef enum { UHCI_SETUP = 0x2d, UHCI_IN = 0x69, UHCI_OUT = 0xe1 } uhci_pid_t;
|
||||||
|
|
||||||
typedef union {
|
typedef u32 flistp_t;
|
||||||
struct {
|
#define FLISTP_TERMINATE 1
|
||||||
unsigned long terminate:1;
|
#define FLISTP_QH 2
|
||||||
unsigned long queue_head:1;
|
|
||||||
unsigned long:2;
|
|
||||||
unsigned long ptr_part:28;
|
|
||||||
};
|
|
||||||
u32 ptr;
|
|
||||||
} __attribute__ ((packed)) flistp_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
unsigned long terminate:1;
|
|
||||||
unsigned long queue_head:1;
|
|
||||||
unsigned long depth_first:1;
|
|
||||||
unsigned long:29;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
u32 ptr;
|
u32 ptr;
|
||||||
} __attribute__ ((packed));
|
#define TD_TERMINATE 1
|
||||||
|
#define TD_QH 2
|
||||||
|
#define TD_DEPTH_FIRST 4
|
||||||
|
|
||||||
volatile unsigned long actlen:11;
|
u32 ctrlsts;
|
||||||
volatile unsigned long:5;
|
#define TD_STATUS_MASK (0xff << 16)
|
||||||
union {
|
#define TD_STATUS_BITSTUFF_ERR (1 << 17)
|
||||||
struct {
|
#define TD_STATUS_CRC_ERR (1 << 18)
|
||||||
unsigned long:1; // bit 0
|
#define TD_STATUS_NAK_RCVD (1 << 19)
|
||||||
unsigned long status_bitstuff_err:1;
|
#define TD_STATUS_BABBLE (1 << 20)
|
||||||
unsigned long status_crc_err:1;
|
#define TD_STATUS_DATABUF_ERR (1 << 21)
|
||||||
unsigned long status_nakrcvd:1;
|
#define TD_STATUS_STALLED (1 << 22)
|
||||||
unsigned long status_babble:1;
|
#define TD_STATUS_ACTIVE (1 << 23)
|
||||||
unsigned long status_databuf_err:1;
|
#define TD_LOWSPEED (1 << 26)
|
||||||
unsigned long status_stalled:1;
|
#define TD_COUNTER_SHIFT 27
|
||||||
unsigned long status_active:1; // bit 7
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
unsigned char status;
|
|
||||||
} __attribute__ ((packed));
|
|
||||||
volatile unsigned long ioc:1; /* interrupt on complete */
|
|
||||||
volatile unsigned long isochronous:1;
|
|
||||||
volatile unsigned long lowspeed:1;
|
|
||||||
volatile unsigned long counter:2;
|
|
||||||
volatile unsigned long shortpck:1;
|
|
||||||
volatile unsigned long:2;
|
|
||||||
|
|
||||||
unsigned long pid:8;
|
u32 token;
|
||||||
unsigned long dev_addr:7;
|
#define TD_PID_MASK 0xff
|
||||||
unsigned long endp:4;
|
#define TD_DEVADDR_SHIFT 8
|
||||||
unsigned long data_toggle:1;
|
#define TD_DEVADDR_MASK (((1<<7)-1) << TD_DEVADDR_SHIFT)
|
||||||
unsigned long:1;
|
#define TD_EP_SHIFT 15
|
||||||
unsigned long maxlen:11;
|
#define TD_EP_MASK (0xf << TD_EP_SHIFT)
|
||||||
|
#define TD_TOGGLE_SHIFT 19
|
||||||
|
#define TD_MAXLEN_SHIFT 21
|
||||||
|
#define TD_TOGGLE_DATA0 0
|
||||||
|
#define TD_TOGGLE_DATA1 (1 << TD_TOGGLE_SHIFT)
|
||||||
|
|
||||||
u32 bufptr;
|
u32 bufptr;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user