libpayload: Remove bitfield use from UHCI data structures
[coreboot.git] / payloads / libpayload / drivers / usb / uhci.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2008-2010 coresystems GmbH
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 //#define USB_DEBUG
31
32 #include <arch/virtual.h>
33 #include <usb/usb.h>
34 #include "uhci.h"
35 #include "uhci_private.h"
36
37 static void uhci_start (hci_t *controller);
38 static void uhci_stop (hci_t *controller);
39 static void uhci_reset (hci_t *controller);
40 static void uhci_shutdown (hci_t *controller);
41 static int uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
42 static int uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq,
43                          int dalen, u8 *data);
44 static void* uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
45 static void uhci_destroy_intr_queue (endpoint_t *ep, void *queue);
46 static u8* uhci_poll_intr_queue (void *queue);
47
48 #if 0
49 /* dump uhci */
50 static void
51 uhci_dump (hci_t *controller)
52 {
53         debug ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD));
54         debug ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS));
55         debug ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR));
56         debug ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM));
57         debug ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD));
58         debug ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD));
59         debug ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1));
60         debug ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2));
61 }
62 #endif
63
64 static void
65 td_dump (td_t *td)
66 {
67         char td_value[3];
68         const char *td_type;
69         switch (td->token & TD_PID_MASK) {
70                 case UHCI_SETUP:
71                         td_type="SETUP";
72                         break;
73                 case UHCI_IN:
74                         td_type="IN";
75                         break;
76                 case UHCI_OUT:
77                         td_type="OUT";
78                         break;
79                 default:
80                         sprintf(td_value, "%x", td->token & TD_PID_MASK);
81                         td_type=td_value;
82         }
83         debug ("%s packet (at %lx) to %x.%x failed\n", td_type,
84                 virt_to_phys (td), (td->token & TD_DEVADDR_MASK) >> TD_DEVADDR_SHIFT,
85                 (td->token & TD_EP_MASK) >> TD_EP_SHIFT);
86         debug ("td (counter at %x) returns: ", td->ctrlsts >> TD_COUNTER_SHIFT);
87         debug (" bitstuff err: %x, ", !!(td->ctrlsts & TD_STATUS_BITSTUFF_ERR));
88         debug (" CRC err: %x, ", !!(td->ctrlsts & TD_STATUS_CRC_ERR));
89         debug (" NAK rcvd: %x, ", !!(td->ctrlsts & TD_STATUS_NAK_RCVD));
90         debug (" Babble: %x, ", !!(td->ctrlsts & TD_STATUS_BABBLE));
91         debug (" Data Buffer err: %x, ", !!(td->ctrlsts & TD_STATUS_DATABUF_ERR));
92         debug (" Stalled: %x, ", !!(td->ctrlsts & TD_STATUS_STALLED));
93         debug (" Active: %x\n", !!(td->ctrlsts & TD_STATUS_ACTIVE));
94         if (td->ctrlsts & TD_STATUS_BABBLE)
95                 debug (" Babble because of %s\n",
96                         (td->ctrlsts & TD_STATUS_BITSTUFF_ERR) ? "host" : "device");
97         if (td->ctrlsts & TD_STATUS_ACTIVE)
98                 debug (" still active - timeout?\n");
99 }
100
101 static void
102 uhci_reset (hci_t *controller)
103 {
104         /* reset */
105         uhci_reg_write16 (controller, USBCMD, 4);
106         mdelay (50);
107         uhci_reg_write16 (controller, USBCMD, 0);
108         mdelay (10);
109         uhci_reg_write16 (controller, USBCMD, 2);
110         while ((uhci_reg_read16 (controller, USBCMD) & 2) != 0)
111                 mdelay (1);
112
113         uhci_reg_write32 (controller, FLBASEADD,
114                           (u32) virt_to_phys (UHCI_INST (controller)->
115                                               framelistptr));
116         //debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
117
118         /* disable irqs */
119         uhci_reg_write16 (controller, USBINTR, 0);
120
121         /* reset framelist index */
122         uhci_reg_write16 (controller, FRNUM, 0);
123
124         uhci_reg_write16(controller, USBCMD,
125                          uhci_reg_read16(controller, USBCMD) | 0xc0);   // max packets, configure flag
126
127         uhci_start (controller);
128 }
129
130 hci_t *
131 uhci_init (pcidev_t addr)
132 {
133         int i;
134         u16 reg16;
135
136         hci_t *controller = new_controller ();
137
138         if (!controller)
139                 fatal("Could not create USB controller instance.\n");
140
141         controller->instance = malloc (sizeof (uhci_t));
142         if(!controller->instance)
143                 fatal("Not enough memory creating USB controller instance.\n");
144
145         controller->start = uhci_start;
146         controller->stop = uhci_stop;
147         controller->reset = uhci_reset;
148         controller->shutdown = uhci_shutdown;
149         controller->bulk = uhci_bulk;
150         controller->control = uhci_control;
151         controller->create_intr_queue = uhci_create_intr_queue;
152         controller->destroy_intr_queue = uhci_destroy_intr_queue;
153         controller->poll_intr_queue = uhci_poll_intr_queue;
154         for (i = 0; i < 128; i++) {
155                 controller->devices[i] = 0;
156         }
157         init_device_entry (controller, 0);
158         UHCI_INST (controller)->roothub = controller->devices[0];
159
160         controller->bus_address = addr;
161         controller->reg_base = pci_read_config32 (controller->bus_address, 0x20) & ~1;  /* ~1 clears the register type indicator that is set to 1 for IO space */
162
163         /* kill legacy support handler */
164         uhci_stop (controller);
165         mdelay (1);
166         uhci_reg_write16 (controller, USBSTS, 0x3f);
167         reg16 = pci_read_config16(controller->bus_address, 0xc0);
168         reg16 &= 0xdf80;
169         pci_write_config16 (controller->bus_address, 0xc0, reg16);
170
171         UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t *));   /* 4kb aligned to 4kb */
172         if (! UHCI_INST (controller)->framelistptr)
173                 fatal("Not enough memory for USB frame list pointer.\n");
174
175         memset (UHCI_INST (controller)->framelistptr, 0,
176                 1024 * sizeof (flistp_t));
177
178         /* According to the *BSD UHCI code, this one is needed on some
179            PIIX chips, because otherwise they misbehave. It must be
180            added to the last chain.
181
182            FIXME: this leaks, if the driver should ever be reinited
183                   for some reason. Not a problem now.
184            */
185         td_t *antiberserk = memalign(16, sizeof(td_t));
186         if (!antiberserk)
187                 fatal("Not enough memory for chipset workaround.\n");
188         memset(antiberserk, 0, sizeof(td_t));
189
190         UHCI_INST (controller)->qh_prei = memalign (16, sizeof (qh_t));
191         UHCI_INST (controller)->qh_intr = memalign (16, sizeof (qh_t));
192         UHCI_INST (controller)->qh_data = memalign (16, sizeof (qh_t));
193         UHCI_INST (controller)->qh_last = memalign (16, sizeof (qh_t));
194
195         if (! UHCI_INST (controller)->qh_prei ||
196             ! UHCI_INST (controller)->qh_intr ||
197             ! UHCI_INST (controller)->qh_data ||
198             ! UHCI_INST (controller)->qh_last)
199                 fatal("Not enough memory for USB controller queues.\n");
200
201         UHCI_INST (controller)->qh_prei->headlinkptr =
202                 virt_to_phys (UHCI_INST (controller)->qh_intr) | FLISTP_QH;
203         UHCI_INST (controller)->qh_prei->elementlinkptr = 0 | FLISTP_TERMINATE;
204
205         UHCI_INST (controller)->qh_intr->headlinkptr =
206                 virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_QH;
207         UHCI_INST (controller)->qh_intr->elementlinkptr = 0 | FLISTP_TERMINATE;
208
209         UHCI_INST (controller)->qh_data->headlinkptr =
210                 virt_to_phys (UHCI_INST (controller)->qh_last) | FLISTP_QH;
211         UHCI_INST (controller)->qh_data->elementlinkptr = 0 | FLISTP_TERMINATE;
212
213         UHCI_INST (controller)->qh_last->headlinkptr = virt_to_phys (UHCI_INST (controller)->qh_data) | FLISTP_TERMINATE;
214         UHCI_INST (controller)->qh_last->elementlinkptr = virt_to_phys (antiberserk) | FLISTP_TERMINATE;
215
216         for (i = 0; i < 1024; i++) {
217                 UHCI_INST (controller)->framelistptr[i] =
218                         virt_to_phys (UHCI_INST (controller)->qh_prei) | FLISTP_QH;
219         }
220         controller->devices[0]->controller = controller;
221         controller->devices[0]->init = uhci_rh_init;
222         controller->devices[0]->init (controller->devices[0]);
223         uhci_reset (controller);
224         return controller;
225 }
226
227 static void
228 uhci_shutdown (hci_t *controller)
229 {
230         if (controller == 0)
231                 return;
232         detach_controller (controller);
233         UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)->
234                                                   roothub);
235         uhci_reg_write16(controller, USBCMD,
236                          uhci_reg_read16(controller, USBCMD) & 0);      // stop work
237         free (UHCI_INST (controller)->framelistptr);
238         free (UHCI_INST (controller)->qh_prei);
239         free (UHCI_INST (controller)->qh_intr);
240         free (UHCI_INST (controller)->qh_data);
241         free (UHCI_INST (controller)->qh_last);
242         free (UHCI_INST (controller));
243         free (controller);
244 }
245
246 static void
247 uhci_start (hci_t *controller)
248 {
249         uhci_reg_write16(controller, USBCMD,
250                          uhci_reg_read16(controller, USBCMD) | 1);      // start work on schedule
251 }
252
253 static void
254 uhci_stop (hci_t *controller)
255 {
256         uhci_reg_write16(controller, USBCMD,
257                          uhci_reg_read16(controller, USBCMD) & ~1);     // stop work on schedule
258 }
259
260 #define GET_TD(x) ((void*)(((unsigned int)(x))&~0xf))
261
262 static td_t *
263 wait_for_completed_qh (hci_t *controller, qh_t *qh)
264 {
265         int timeout = 1000000;  /* max 30 ms. */
266         void *current = GET_TD (qh->elementlinkptr);
267         while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) {
268                 if (current != GET_TD (qh->elementlinkptr)) {
269                         current = GET_TD (qh->elementlinkptr);
270                         timeout = 1000000;
271                 }
272                 uhci_reg_write16(controller, USBSTS,
273                                  uhci_reg_read16(controller, USBSTS) | 0);      // clear resettable registers
274                 udelay (30);
275         }
276         return (GET_TD (qh->elementlinkptr) ==
277                 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr));
278 }
279
280 static int
281 maxlen (int size)
282 {
283         return (size - 1) & 0x7ff;
284 }
285
286 static int
287 min (int a, int b)
288 {
289         if (a < b)
290                 return a;
291         else
292                 return b;
293 }
294
295 static int
296 uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen,
297               unsigned char *data)
298 {
299         int endp = 0;           /* this is control: always 0 */
300         int mlen = dev->endpoints[0].maxpacketsize;
301         int count = (2 + (dalen + mlen - 1) / mlen);
302         unsigned short req = ((unsigned short *) devreq)[0];
303         int i;
304         td_t *tds = memalign (16, sizeof (td_t) * count);
305         memset (tds, 0, sizeof (td_t) * count);
306         count--;                /* to compensate for 0-indexed array */
307         for (i = 0; i < count; i++) {
308                 tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
309         }
310         tds[count].ptr = 0 | TD_DEPTH_FIRST | TD_TERMINATE;
311
312         tds[0].token = UHCI_SETUP |
313                 dev->address << TD_DEVADDR_SHIFT |
314                 endp << TD_EP_SHIFT |
315                 TD_TOGGLE_DATA0 |
316                 maxlen(drlen) << TD_MAXLEN_SHIFT;
317         tds[0].bufptr = virt_to_phys (devreq);
318         tds[0].ctrlsts = (3 << TD_COUNTER_SHIFT) |
319                 (dev->speed?TD_LOWSPEED:0) |
320                 TD_STATUS_ACTIVE;
321
322         int toggle = 1;
323         for (i = 1; i < count; i++) {
324                 switch (dir) {
325                         case SETUP: tds[i].token = UHCI_SETUP; break;
326                         case IN:    tds[i].token = UHCI_IN;    break;
327                         case OUT:   tds[i].token = UHCI_OUT;   break;
328                 }
329                 tds[i].token |= dev->address << TD_DEVADDR_SHIFT |
330                         endp << TD_EP_SHIFT |
331                         maxlen (min (mlen, dalen)) << TD_MAXLEN_SHIFT |
332                         toggle << TD_TOGGLE_SHIFT;
333                 tds[i].bufptr = virt_to_phys (data);
334                 tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) |
335                         (dev->speed?TD_LOWSPEED:0) |
336                         TD_STATUS_ACTIVE;
337                 toggle ^= 1;
338                 dalen -= mlen;
339                 data += mlen;
340         }
341
342         tds[count].token = (dir == OUT) ? UHCI_IN : UHCI_OUT |
343                 dev->address << TD_DEVADDR_SHIFT |
344                 endp << TD_EP_SHIFT |
345                 maxlen(0) << TD_MAXLEN_SHIFT |
346                 TD_TOGGLE_DATA1;
347         tds[count].bufptr = 0;
348         tds[0].ctrlsts = (0 << TD_COUNTER_SHIFT) | /* as Linux 2.4.10 does */
349                 (dev->speed?TD_LOWSPEED:0) |
350                 TD_STATUS_ACTIVE;
351         UHCI_INST (dev->controller)->qh_data->elementlinkptr =
352                 virt_to_phys (tds) & ~(FLISTP_QH | FLISTP_TERMINATE);
353         td_t *td = wait_for_completed_qh (dev->controller,
354                                           UHCI_INST (dev->controller)->
355                                           qh_data);
356         int result;
357         if (td == 0) {
358                 result = 0;
359         } else {
360                 debug ("control packet, req %x\n", req);
361                 td_dump (td);
362                 result = 1;
363         }
364         free (tds);
365         return result;
366 }
367
368 static td_t *
369 create_schedule (int numpackets)
370 {
371         if (numpackets == 0)
372                 return 0;
373         td_t *tds = memalign (16, sizeof (td_t) * numpackets);
374         memset (tds, 0, sizeof (td_t) * numpackets);
375         int i;
376         for (i = 0; i < numpackets; i++) {
377                 tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST;
378         }
379         tds[numpackets - 1].ptr = 0 | TD_TERMINATE;
380         return tds;
381 }
382
383 static void
384 fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data,
385                int *toggle)
386 {
387         switch (ep->direction) {
388                 case IN: td->token = UHCI_IN; break;
389                 case OUT: td->token = UHCI_OUT; break;
390                 case SETUP: td->token = UHCI_SETUP; break;
391         }
392         td->token |= ep->dev->address << TD_DEVADDR_SHIFT |
393                 (ep->endpoint & 0xf) << TD_EP_SHIFT |
394                 maxlen (length) << TD_MAXLEN_SHIFT |
395                 (*toggle & 1) << TD_TOGGLE_SHIFT;
396         td->bufptr = virt_to_phys (data);
397         td->ctrlsts = ((ep->direction == SETUP?3:0) << TD_COUNTER_SHIFT) |
398                 ep->dev->speed?TD_LOWSPEED:0 |
399                 TD_STATUS_ACTIVE;
400         *toggle ^= 1;
401 }
402
403 static int
404 run_schedule (usbdev_t *dev, td_t *td)
405 {
406         UHCI_INST (dev->controller)->qh_data->elementlinkptr =
407                 virt_to_phys (td) | ~(FLISTP_QH | FLISTP_TERMINATE);
408         td = wait_for_completed_qh (dev->controller,
409                                     UHCI_INST (dev->controller)->qh_data);
410         if (td == 0) {
411                 return 0;
412         } else {
413                 td_dump (td);
414                 return 1;
415         }
416 }
417
418 /* finalize == 1: if data is of packet aligned size, add a zero length packet */
419 static int
420 uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
421 {
422         int maxpsize = ep->maxpacketsize;
423         if (maxpsize == 0)
424                 fatal("MaxPacketSize == 0!!!");
425         int numpackets = (size + maxpsize - 1 + finalize) / maxpsize;
426         if (numpackets == 0)
427                 return 0;
428         td_t *tds = create_schedule (numpackets);
429         int i = 0, toggle = ep->toggle;
430         while ((size > 0) || ((size == 0) && (finalize != 0))) {
431                 fill_schedule (&tds[i], ep, min (size, maxpsize), data,
432                                &toggle);
433                 i++;
434                 data += maxpsize;
435                 size -= maxpsize;
436         }
437         if (run_schedule (ep->dev, tds) == 1) {
438                 debug("Stalled. Trying to clean up.\n");
439                 clear_stall (ep);
440                 free (tds);
441                 return 1;
442         }
443         ep->toggle = toggle;
444         free (tds);
445         return 0;
446 }
447
448 typedef struct {
449         qh_t *qh;
450         td_t *tds;
451         td_t *last_td;
452         u8 *data;
453         int lastread;
454         int total;
455         int reqsize;
456 } intr_q;
457
458 /* create and hook-up an intr queue into device schedule */
459 static void*
460 uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming)
461 {
462         u8 *data = malloc(reqsize*reqcount);
463         td_t *tds = memalign(16, sizeof(td_t) * reqcount);
464         qh_t *qh = memalign(16, sizeof(qh_t));
465
466         if (!data || !tds || !qh)
467                 fatal("Not enough memory to create USB intr queue prerequisites.\n");
468
469         qh->elementlinkptr = virt_to_phys(tds);
470
471         intr_q *q = malloc(sizeof(intr_q));
472         if (!q)
473                 fatal("Not enough memory to create USB intr queue.\n");
474         q->qh = qh;
475         q->tds = tds;
476         q->data = data;
477         q->lastread = 0;
478         q->total = reqcount;
479         q->reqsize = reqsize;
480         q->last_td = &tds[reqcount - 1];
481
482         memset (tds, 0, sizeof (td_t) * reqcount);
483         int i;
484         for (i = 0; i < reqcount; i++) {
485                 tds[i].ptr = virt_to_phys (&tds[i + 1]);
486
487                 switch (ep->direction) {
488                         case IN: tds[i].token = UHCI_IN; break;
489                         case OUT: tds[i].token = UHCI_OUT; break;
490                         case SETUP: tds[i].token = UHCI_SETUP; break;
491                 }
492                 tds[i].token |= ep->dev->address << TD_DEVADDR_SHIFT |
493                         (ep->endpoint & 0xf) << TD_EP_SHIFT |
494                         maxlen (reqsize) << TD_MAXLEN_SHIFT |
495                         (ep->toggle & 1) << TD_TOGGLE_SHIFT;
496                 tds[i].bufptr = virt_to_phys (data);
497                 tds[i].ctrlsts = (0 << TD_COUNTER_SHIFT) |
498                         ep->dev->speed?TD_LOWSPEED:0 |
499                         TD_STATUS_ACTIVE;
500                 ep->toggle ^= 1;
501                 data += reqsize;
502         }
503         tds[reqcount - 1].ptr = 0 | TD_TERMINATE;
504         for (i = reqtiming; i < 1024; i += reqtiming) {
505                 /* FIXME: wrap in another qh, one for each occurance of the qh in the framelist */
506                 qh->headlinkptr = UHCI_INST (ep->dev->controller)->framelistptr[i] & ~FLISTP_TERMINATE;
507                 UHCI_INST (ep->dev->controller)->framelistptr[i] = virt_to_phys(qh) | FLISTP_QH;
508         }
509         return q;
510 }
511
512 /* remove queue from device schedule, dropping all data that came in */
513 static void
514 uhci_destroy_intr_queue (endpoint_t *ep, void *q_)
515 {
516         intr_q *q = (intr_q*)q_;
517         u32 val = virt_to_phys (q->qh);
518         u32 end = virt_to_phys (UHCI_INST (ep->dev->controller)->qh_intr);
519         int i;
520         for (i=0; i<1024; i++) {
521                 u32 oldptr = 0;
522                 u32 ptr = UHCI_INST (ep->dev->controller)->framelistptr[i];
523                 while (ptr != end) {
524                         if (((qh_t*)phys_to_virt(ptr))->elementlinkptr == val) {
525                                 ((qh_t*)phys_to_virt(oldptr))->headlinkptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
526                                 free(phys_to_virt(ptr));
527                                 break;
528                         }
529                         oldptr = ptr;
530                         ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr;
531                 }
532         }
533         free(q->data);
534         free(q->tds);
535         free(q->qh);
536         free(q);
537 }
538
539 /* read one intr-packet from queue, if available. extend the queue for new input.
540    return NULL if nothing new available.
541    Recommended use: while (data=poll_intr_queue(q)) process(data);
542  */
543 static u8*
544 uhci_poll_intr_queue (void *q_)
545 {
546         intr_q *q = (intr_q*)q_;
547         if ((q->tds[q->lastread].ctrlsts & TD_STATUS_ACTIVE) == 0) {
548                 /* FIXME: handle errors */
549                 int current = q->lastread;
550                 int previous;
551                 if (q->lastread == 0) {
552                         previous = q->total - 1;
553                 } else {
554                         previous = q->lastread - 1;
555                 }
556                 q->tds[previous].ctrlsts &= ~TD_STATUS_MASK;
557                 q->tds[previous].ptr = 0 | TD_TERMINATE;
558                 if (q->last_td != &q->tds[previous]) {
559                         q->last_td->ptr = virt_to_phys(&q->tds[previous]) & ~TD_TERMINATE;
560                         q->last_td = &q->tds[previous];
561                 }
562                 q->tds[previous].ctrlsts |= TD_STATUS_ACTIVE;
563                 q->lastread = (q->lastread + 1) % q->total;
564                 return &q->data[current*q->reqsize];
565         }
566         return NULL;
567 }
568
569 void
570 uhci_reg_write32 (hci_t *ctrl, usbreg reg, u32 value)
571 {
572         outl (value, ctrl->reg_base + reg);
573 }
574
575 u32
576 uhci_reg_read32 (hci_t *ctrl, usbreg reg)
577 {
578         return inl (ctrl->reg_base + reg);
579 }
580
581 void
582 uhci_reg_write16 (hci_t *ctrl, usbreg reg, u16 value)
583 {
584         outw (value, ctrl->reg_base + reg);
585 }
586
587 u16
588 uhci_reg_read16 (hci_t *ctrl, usbreg reg)
589 {
590         return inw (ctrl->reg_base + reg);
591 }
592
593 void
594 uhci_reg_write8 (hci_t *ctrl, usbreg reg, u8 value)
595 {
596         outb (value, ctrl->reg_base + reg);
597 }
598
599 u8
600 uhci_reg_read8 (hci_t *ctrl, usbreg reg)
601 {
602         return inb (ctrl->reg_base + reg);
603 }