Some driver fixes for libpayload:
[coreboot.git] / payloads / libpayload / drivers / usb / uhci.c
1 /*
2  * This file is part of the libpayload project.
3  *
4  * Copyright (C) 2008 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 #include <usb/usb.h>
31 #include "uhci.h"
32 #include <arch/virtual.h>
33
34 static void uhci_start (hci_t *controller);
35 static void uhci_stop (hci_t *controller);
36 static void uhci_reset (hci_t *controller);
37 static void uhci_shutdown (hci_t *controller);
38 static int uhci_packet (usbdev_t *dev, int endp, int pid, int toggle,
39                         int length, u8 *data);
40 static int uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize);
41 static int uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq,
42                          int dalen, u8 *data);
43 static void* uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
44 static void uhci_destroy_intr_queue (endpoint_t *ep, void *queue);
45 static u8* uhci_poll_intr_queue (void *queue);
46
47 #if 0
48 /* dump uhci */
49 static void
50 uhci_dump (hci_t *controller)
51 {
52         printf ("dump:\nUSBCMD: %x\n", uhci_reg_read16 (controller, USBCMD));
53         printf ("USBSTS: %x\n", uhci_reg_read16 (controller, USBSTS));
54         printf ("USBINTR: %x\n", uhci_reg_read16 (controller, USBINTR));
55         printf ("FRNUM: %x\n", uhci_reg_read16 (controller, FRNUM));
56         printf ("FLBASEADD: %x\n", uhci_reg_read32 (controller, FLBASEADD));
57         printf ("SOFMOD: %x\n", uhci_reg_read8 (controller, SOFMOD));
58         printf ("PORTSC1: %x\n", uhci_reg_read16 (controller, PORTSC1));
59         printf ("PORTSC2: %x\n", uhci_reg_read16 (controller, PORTSC2));
60 }
61 #endif
62
63 static void
64 td_dump (td_t *td)
65 {
66         char td_value[3];
67         char *td_type;
68         switch (td->pid) {
69                 case SETUP:
70                         td_type="SETUP";
71                         break;
72                 case IN:
73                         td_type="IN";
74                         break;
75                 case OUT:
76                         td_type="OUT";
77                         break;
78                 default:
79                         sprintf(td_value, "%x", td->pid);
80                         td_type=td_value;
81         }
82         printf ("%s packet (at %lx) to %x.%x failed\n", td_type,
83                 virt_to_phys (td), td->dev_addr, td->endp);
84         printf ("td (counter at %x) returns: ", td->counter);
85         printf (" bitstuff err: %x, ", td->status_bitstuff_err);
86         printf (" CRC err: %x, ", td->status_crc_err);
87         printf (" NAK rcvd: %x, ", td->status_nakrcvd);
88         printf (" Babble: %x, ", td->status_babble);
89         printf (" Data Buffer err: %x, ", td->status_databuf_err);
90         printf (" Stalled: %x, ", td->status_stalled);
91         printf (" Active: %x\n", td->status_active);
92         if (td->status_babble)
93                 printf (" Babble because of %s\n",
94                         td->status_bitstuff_err ? "host" : "device");
95         if (td->status_active)
96                 printf (" still active - timeout?\n");
97 }
98
99 static void
100 uhci_reset (hci_t *controller)
101 {
102         /* reset */
103         uhci_reg_write16 (controller, USBCMD, 4);
104         mdelay (50);
105         uhci_reg_write16 (controller, USBCMD, 0);
106         mdelay (10);
107         uhci_reg_write16 (controller, USBCMD, 2);
108         while ((uhci_reg_read16 (controller, USBCMD) & 2) != 0)
109                 mdelay (1);
110
111         uhci_reg_write32 (controller, FLBASEADD,
112                           (u32) virt_to_phys (UHCI_INST (controller)->
113                                               framelistptr));
114         //printf ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
115
116         /* disable irqs */
117         uhci_reg_write16 (controller, USBINTR, 0);
118
119         /* reset framelist index */
120         uhci_reg_write16 (controller, FRNUM, 0);
121
122         uhci_reg_mask16 (controller, USBCMD, ~0, 0xc0); // max packets, configure flag
123
124         uhci_start (controller);
125 }
126
127 hci_t *
128 uhci_init (pcidev_t addr)
129 {
130         int i;
131         hci_t *controller = new_controller ();
132
133         controller->instance = malloc (sizeof (uhci_t));
134         controller->start = uhci_start;
135         controller->stop = uhci_stop;
136         controller->reset = uhci_reset;
137         controller->shutdown = uhci_shutdown;
138         controller->packet = uhci_packet;
139         controller->bulk = uhci_bulk;
140         controller->control = uhci_control;
141         controller->create_intr_queue = uhci_create_intr_queue;
142         controller->destroy_intr_queue = uhci_destroy_intr_queue;
143         controller->poll_intr_queue = uhci_poll_intr_queue;
144         for (i = 1; i < 128; i++) {
145                 controller->devices[i] = 0;
146         }
147         init_device_entry (controller, 0);
148         UHCI_INST (controller)->roothub = controller->devices[0];
149
150         controller->bus_address = addr;
151         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 */
152
153         /* kill legacy support handler */
154         uhci_stop (controller);
155         mdelay (1);
156         uhci_reg_write16 (controller, USBSTS, 0x3f);
157         pci_write_config32 (controller->bus_address, 0xc0, 0x8f00);
158
159         UHCI_INST (controller)->framelistptr = memalign (0x1000, 1024 * sizeof (flistp_t *));   /* 4kb aligned to 4kb */
160         memset (UHCI_INST (controller)->framelistptr, 0,
161                 1024 * sizeof (flistp_t));
162
163         /* According to the *BSD UHCI code, this one is needed on some
164            PIIX chips, because otherwise they misbehave. It must be
165            added to the last chain.
166
167            FIXME: this leaks, if the driver should ever be reinited
168                   for some reason. Not a problem now.
169            */
170         td_t *antiberserk = memalign(16, sizeof(td_t));
171         memset(antiberserk, 0, sizeof(td_t));
172
173         UHCI_INST (controller)->qh_prei = memalign (16, sizeof (qh_t));
174         UHCI_INST (controller)->qh_intr = memalign (16, sizeof (qh_t));
175         UHCI_INST (controller)->qh_data = memalign (16, sizeof (qh_t));
176         UHCI_INST (controller)->qh_last = memalign (16, sizeof (qh_t));
177
178         UHCI_INST (controller)->qh_prei->headlinkptr.ptr =
179                 virt_to_phys (UHCI_INST (controller)->qh_intr);
180         UHCI_INST (controller)->qh_prei->headlinkptr.queue_head = 1;
181         UHCI_INST (controller)->qh_prei->elementlinkptr.ptr = 0;
182         UHCI_INST (controller)->qh_prei->elementlinkptr.terminate = 1;
183
184         UHCI_INST (controller)->qh_intr->headlinkptr.ptr =
185                 virt_to_phys (UHCI_INST (controller)->qh_data);
186         UHCI_INST (controller)->qh_intr->headlinkptr.queue_head = 1;
187         UHCI_INST (controller)->qh_intr->elementlinkptr.ptr = 0;
188         UHCI_INST (controller)->qh_intr->elementlinkptr.terminate = 1;
189
190         UHCI_INST (controller)->qh_data->headlinkptr.ptr =
191                 virt_to_phys (UHCI_INST (controller)->qh_last);
192         UHCI_INST (controller)->qh_data->headlinkptr.queue_head = 1;
193         UHCI_INST (controller)->qh_data->elementlinkptr.ptr = 0;
194         UHCI_INST (controller)->qh_data->elementlinkptr.terminate = 1;
195
196         UHCI_INST (controller)->qh_last->headlinkptr.ptr = virt_to_phys (UHCI_INST (controller)->qh_data);
197         UHCI_INST (controller)->qh_last->headlinkptr.terminate = 1;
198         UHCI_INST (controller)->qh_last->elementlinkptr.ptr = virt_to_phys (antiberserk);
199         UHCI_INST (controller)->qh_last->elementlinkptr.terminate = 1;
200
201         for (i = 0; i < 1024; i++) {
202                 UHCI_INST (controller)->framelistptr[i].ptr =
203                         virt_to_phys (UHCI_INST (controller)->qh_prei);
204                 UHCI_INST (controller)->framelistptr[i].terminate = 0;
205                 UHCI_INST (controller)->framelistptr[i].queue_head = 1;
206         }
207         controller->devices[0]->controller = controller;
208         controller->devices[0]->init = uhci_rh_init;
209         controller->devices[0]->init (controller->devices[0]);
210         uhci_reset (controller);
211         return controller;
212 }
213
214 static void
215 uhci_shutdown (hci_t *controller)
216 {
217         if (controller == 0)
218                 return;
219         detach_controller (controller);
220         UHCI_INST (controller)->roothub->destroy (UHCI_INST (controller)->
221                                                   roothub);
222         uhci_reg_mask16 (controller, USBCMD, 0, 0);     // stop work
223         free (UHCI_INST (controller)->framelistptr);
224         free (UHCI_INST (controller)->qh_prei);
225         free (UHCI_INST (controller)->qh_intr);
226         free (UHCI_INST (controller)->qh_data);
227         free (UHCI_INST (controller)->qh_last);
228         free (UHCI_INST (controller));
229         free (controller);
230 }
231
232 static void
233 uhci_start (hci_t *controller)
234 {
235         uhci_reg_mask16 (controller, USBCMD, ~0, 1);    // start work on schedule
236 }
237
238 static void
239 uhci_stop (hci_t *controller)
240 {
241         uhci_reg_mask16 (controller, USBCMD, ~1, 0);    // stop work on schedule
242 }
243
244 #define GET_TD(x) ((void*)(((unsigned int)(x))&~0xf))
245
246 static td_t *
247 wait_for_completed_qh (hci_t *controller, qh_t *qh)
248 {
249         int timeout = 1000000;  /* max 30 ms. */
250         void *current = GET_TD (qh->elementlinkptr.ptr);
251         while ((qh->elementlinkptr.terminate == 0) && (timeout-- > 0)) {
252                 if (current != GET_TD (qh->elementlinkptr.ptr)) {
253                         current = GET_TD (qh->elementlinkptr.ptr);
254                         timeout = 1000000;
255                 }
256                 uhci_reg_mask16 (controller, USBSTS, ~0, 0);    // clear resettable registers
257                 udelay (30);
258         }
259         return (GET_TD (qh->elementlinkptr.ptr) ==
260                 0) ? 0 : GET_TD (phys_to_virt (qh->elementlinkptr.ptr));
261 }
262
263 static void
264 wait_for_completed_td (hci_t *controller, td_t *td)
265 {
266         int timeout = 10000;
267         while ((td->status_active == 1)
268                && ((uhci_reg_read16 (controller, USBSTS) & 2) == 0)
269                && (timeout-- > 0)) {
270                 uhci_reg_mask16 (controller, USBSTS, ~0, 0);    // clear resettable registers
271                 udelay (10);
272         }
273 }
274
275 static int
276 maxlen (int size)
277 {
278         return (size - 1) & 0x7ff;
279 }
280
281 static int
282 min (int a, int b)
283 {
284         if (a < b)
285                 return a;
286         else
287                 return b;
288 }
289
290 static int
291 uhci_control (usbdev_t *dev, pid_t dir, int drlen, void *devreq, int dalen,
292               unsigned char *data)
293 {
294         int endp = 0;           /* this is control: always 0 */
295         int mlen = dev->endpoints[0].maxpacketsize;
296         int count = (2 + (dalen + mlen - 1) / mlen);
297         unsigned short req = ((unsigned short *) devreq)[0];
298         int i;
299         td_t *tds = memalign (16, sizeof (td_t) * count);
300         memset (tds, 0, sizeof (td_t) * count);
301         count--;                /* to compensate for 0-indexed array */
302         for (i = 0; i < count; i++) {
303                 tds[i].ptr = virt_to_phys (&tds[i + 1]);
304                 tds[i].depth_first = 1;
305                 tds[i].terminate = 0;
306         }
307         tds[count].ptr = 0;
308         tds[count].depth_first = 1;
309         tds[count].terminate = 1;
310
311         tds[0].pid = SETUP;
312         tds[0].dev_addr = dev->address;
313         tds[0].endp = endp;
314         tds[0].maxlen = maxlen (drlen);
315         tds[0].counter = 3;
316         tds[0].data_toggle = 0;
317         tds[0].lowspeed = dev->lowspeed;
318         tds[0].bufptr = virt_to_phys (devreq);
319         tds[0].status_active = 1;
320
321         int toggle = 1;
322         for (i = 1; i < count; i++) {
323                 tds[i].pid = dir;
324                 tds[i].dev_addr = dev->address;
325                 tds[i].endp = endp;
326                 tds[i].maxlen = maxlen (min (mlen, dalen));
327                 tds[i].counter = 3;
328                 tds[i].data_toggle = toggle;
329                 tds[i].lowspeed = dev->lowspeed;
330                 tds[i].bufptr = virt_to_phys (data);
331                 tds[i].status_active = 1;
332                 toggle ^= 1;
333                 dalen -= mlen;
334                 data += mlen;
335         }
336
337         tds[count].pid = (dir == OUT) ? IN : OUT;
338         tds[count].dev_addr = dev->address;
339         tds[count].endp = endp;
340         tds[count].maxlen = maxlen (0);
341         tds[count].counter = 0; /* as per linux 2.4.10 */
342         tds[count].data_toggle = 1;
343         tds[count].lowspeed = dev->lowspeed, tds[count].bufptr = 0;
344         tds[count].status_active = 1;
345         UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
346                 virt_to_phys (tds);
347         UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
348         UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
349         td_t *td = wait_for_completed_qh (dev->controller,
350                                           UHCI_INST (dev->controller)->
351                                           qh_data);
352         int result;
353         if (td == 0) {
354                 result = 0;
355         } else {
356                 printf ("control packet, req %x\n", req);
357                 td_dump (td);
358                 result = 1;
359         }
360         free (tds);
361         return result;
362 }
363
364 static int
365 uhci_packet (usbdev_t *dev, int endp, int pid, int toggle, int length,
366              unsigned char *data)
367 {
368         static td_t *td = 0;
369         if (td == 0)
370                 td = memalign (16, sizeof (td_t));
371
372         memset (td, 0, sizeof (td_t));
373         td->ptr = 0;
374         td->terminate = 1;
375         td->queue_head = 0;
376
377         td->pid = pid;
378         td->dev_addr = dev->address;
379         td->endp = endp & 0xf;
380         td->maxlen = maxlen (length);
381         if (pid == SETUP)
382                 td->counter = 3;
383         else
384                 td->counter = 0;
385         td->data_toggle = toggle & 1;
386         td->lowspeed = dev->lowspeed;
387         td->bufptr = virt_to_phys (data);
388
389         td->status_active = 1;
390
391         UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
392                 virt_to_phys (td);
393         UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
394         UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
395         wait_for_completed_td (dev->controller, td);
396         if ((td->status & 0x7f) == 0) {
397                 //printf("successfully sent a %x packet to %x.%x\n",pid, dev->address,endp);
398                 // success
399                 return 0;
400         } else {
401                 td_dump (td);
402                 return 1;
403         }
404 }
405
406 static td_t *
407 create_schedule (int numpackets)
408 {
409         if (numpackets == 0)
410                 return 0;
411         td_t *tds = memalign (16, sizeof (td_t) * numpackets);
412         memset (tds, 0, sizeof (td_t) * numpackets);
413         int i;
414         for (i = 0; i < numpackets; i++) {
415                 tds[i].ptr = virt_to_phys (&tds[i + 1]);
416                 tds[i].terminate = 0;
417                 tds[i].queue_head = 0;
418                 tds[i].depth_first = 1;
419         }
420         tds[numpackets - 1].ptr = 0;
421         tds[numpackets - 1].terminate = 1;
422         tds[numpackets - 1].queue_head = 0;
423         tds[numpackets - 1].depth_first = 0;
424         return tds;
425 }
426
427 static void
428 fill_schedule (td_t *td, endpoint_t *ep, int length, unsigned char *data,
429                int *toggle)
430 {
431         td->pid = ep->direction;
432         td->dev_addr = ep->dev->address;
433         td->endp = ep->endpoint & 0xf;
434         td->maxlen = maxlen (length);
435         if (ep->direction == SETUP)
436                 td->counter = 3;
437         else
438                 td->counter = 0;
439         td->data_toggle = *toggle & 1;
440         td->lowspeed = ep->dev->lowspeed;
441         td->bufptr = virt_to_phys (data);
442
443         td->status_active = 1;
444         *toggle ^= 1;
445 }
446
447 static int
448 run_schedule (usbdev_t *dev, td_t *td)
449 {
450         UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr =
451                 virt_to_phys (td);
452         UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0;
453         UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0;
454         td = wait_for_completed_qh (dev->controller,
455                                     UHCI_INST (dev->controller)->qh_data);
456         if (td == 0) {
457                 return 0;
458         } else {
459                 td_dump (td);
460                 return 1;
461         }
462 }
463
464 /* finalize == 1: if data is of packet aligned size, add a zero length packet */
465 static int
466 uhci_bulk (endpoint_t *ep, int size, u8 *data, int finalize)
467 {
468         int maxpsize = ep->maxpacketsize;
469         if (maxpsize == 0)
470                 fatal ("MaxPacketSize == 0!!!");
471         int numpackets = (size + maxpsize - 1 + finalize) / maxpsize;
472         if (numpackets == 0)
473                 return 0;
474         td_t *tds = create_schedule (numpackets);
475         int i = 0, toggle = ep->toggle;
476         while ((size > 0) || ((size == 0) && (finalize != 0))) {
477                 fill_schedule (&tds[i], ep, min (size, maxpsize), data,
478                                &toggle);
479                 i++;
480                 data += maxpsize;
481                 size -= maxpsize;
482         }
483         if (run_schedule (ep->dev, tds) == 1) {
484                 clear_stall (ep);
485                 free (tds);
486                 return 1;
487         }
488         ep->toggle = toggle;
489         free (tds);
490         return 0;
491 }
492
493 typedef struct {
494         qh_t *qh;
495         td_t *tds;
496         td_t *last_td;
497         u8 *data;
498         int lastread;
499         int total;
500         int reqsize;
501 } intr_q;
502
503 /* create and hook-up an intr queue into device schedule */
504 static void*
505 uhci_create_intr_queue (endpoint_t *ep, int reqsize, int reqcount, int reqtiming)
506 {
507         u8 *data = malloc(reqsize*reqcount);
508         td_t *tds = memalign(16, sizeof(td_t) * reqcount);
509         qh_t *qh = memalign(16, sizeof(qh_t));
510
511         qh->elementlinkptr.ptr = virt_to_phys(tds);
512         qh->elementlinkptr.queue_head = 0;
513         qh->elementlinkptr.terminate = 0;
514
515         intr_q *q = malloc(sizeof(intr_q));
516         q->qh = qh;
517         q->tds = tds;
518         q->data = data;
519         q->lastread = 0;
520         q->total = reqcount;
521         q->reqsize = reqsize;
522         q->last_td = &tds[reqcount - 1];
523
524         memset (tds, 0, sizeof (td_t) * reqcount);
525         int i;
526         for (i = 0; i < reqcount; i++) {
527                 tds[i].ptr = virt_to_phys (&tds[i + 1]);
528                 tds[i].terminate = 0;
529                 tds[i].queue_head = 0;
530                 tds[i].depth_first = 0;
531
532                 tds[i].pid = ep->direction;
533                 tds[i].dev_addr = ep->dev->address;
534                 tds[i].endp = ep->endpoint & 0xf;
535                 tds[i].maxlen = maxlen (reqsize);
536                 tds[i].counter = 0;
537                 tds[i].data_toggle = ep->toggle & 1;
538                 tds[i].lowspeed = ep->dev->lowspeed;
539                 tds[i].bufptr = virt_to_phys (data);
540                 tds[i].status_active = 1;
541                 ep->toggle ^= 1;
542                 data += reqsize;
543         }
544         tds[reqcount - 1].ptr = 0;
545         tds[reqcount - 1].terminate = 1;
546         tds[reqcount - 1].queue_head = 0;
547         tds[reqcount - 1].depth_first = 0;
548         for (i = reqtiming; i < 1024; i += reqtiming) {
549                 /* FIXME: wrap in another qh, one for each occurance of the qh in the framelist */
550                 qh->headlinkptr.ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
551                 qh->headlinkptr.terminate = 0;
552                 UHCI_INST (ep->dev->controller)->framelistptr[i].ptr = virt_to_phys(qh);
553                 UHCI_INST (ep->dev->controller)->framelistptr[i].terminate = 0;
554                 UHCI_INST (ep->dev->controller)->framelistptr[i].queue_head = 1;
555         }
556         return q;
557 }
558
559 /* remove queue from device schedule, dropping all data that came in */
560 static void
561 uhci_destroy_intr_queue (endpoint_t *ep, void *q_)
562 {
563         intr_q *q = (intr_q*)q_;
564         u32 val = virt_to_phys (q->qh);
565         u32 end = virt_to_phys (UHCI_INST (ep->dev->controller)->qh_intr);
566         int i;
567         for (i=0; i<1024; i++) {
568                 u32 oldptr = 0;
569                 u32 ptr = UHCI_INST (ep->dev->controller)->framelistptr[i].ptr;
570                 while (ptr != end) {
571                         if (((qh_t*)phys_to_virt(ptr))->elementlinkptr.ptr == val) {
572                                 ((qh_t*)phys_to_virt(oldptr))->headlinkptr.ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
573                                 free(phys_to_virt(ptr));
574                                 break;
575                         }
576                         oldptr = ptr;
577                         ptr = ((qh_t*)phys_to_virt(ptr))->headlinkptr.ptr;
578                 }
579         }
580         free(q->data);
581         free(q->tds);
582         free(q->qh);
583         free(q);
584 }
585
586 /* read one intr-packet from queue, if available. extend the queue for new input.
587    return NULL if nothing new available.
588    Recommended use: while (data=poll_intr_queue(q)) process(data);
589  */
590 static u8*
591 uhci_poll_intr_queue (void *q_)
592 {
593         intr_q *q = (intr_q*)q_;
594         if (q->tds[q->lastread].status_active == 0) {
595                 /* FIXME: handle errors */
596                 int current = q->lastread;
597                 int previous;
598                 if (q->lastread == 0) {
599                         previous = q->total - 1;
600                 } else {
601                         previous = q->lastread - 1;
602                 }
603                 q->tds[previous].status = 0;
604                 q->tds[previous].ptr = 0;
605                 q->tds[previous].terminate = 1;
606                 if (q->last_td != &q->tds[previous]) {
607                         q->last_td->ptr = virt_to_phys(&q->tds[previous]);
608                         q->last_td->terminate = 0;
609                         q->last_td = &q->tds[previous];
610                 }
611                 q->tds[previous].status_active = 1;
612                 q->lastread = (q->lastread + 1) % q->total;
613                 return &q->data[current*q->reqsize];
614         }
615         return NULL;
616 }
617
618 void
619 uhci_reg_write32 (hci_t *ctrl, usbreg reg, u32 value)
620 {
621         outl (value, ctrl->reg_base + reg);
622 }
623
624 u32
625 uhci_reg_read32 (hci_t *ctrl, usbreg reg)
626 {
627         return inl (ctrl->reg_base + reg);
628 }
629
630 void
631 uhci_reg_write16 (hci_t *ctrl, usbreg reg, u16 value)
632 {
633         outw (value, ctrl->reg_base + reg);
634 }
635
636 u16
637 uhci_reg_read16 (hci_t *ctrl, usbreg reg)
638 {
639         return inw (ctrl->reg_base + reg);
640 }
641
642 void
643 uhci_reg_write8 (hci_t *ctrl, usbreg reg, u8 value)
644 {
645         outb (value, ctrl->reg_base + reg);
646 }
647
648 u8
649 uhci_reg_read8 (hci_t *ctrl, usbreg reg)
650 {
651         return inb (ctrl->reg_base + reg);
652 }
653
654 void
655 uhci_reg_mask32 (hci_t *ctrl, usbreg reg, u32 andmask, u32 ormask)
656 {
657         uhci_reg_write32 (ctrl, reg,
658                           (uhci_reg_read32 (ctrl, reg) & andmask) | ormask);
659 }
660
661 void
662 uhci_reg_mask16 (hci_t *ctrl, usbreg reg, u16 andmask, u16 ormask)
663 {
664         uhci_reg_write16 (ctrl, reg,
665                           (uhci_reg_read16 (ctrl, reg) & andmask) | ormask);
666 }
667
668 void
669 uhci_reg_mask8 (hci_t *ctrl, usbreg reg, u8 andmask, u8 ormask)
670 {
671         uhci_reg_write8 (ctrl, reg,
672                          (uhci_reg_read8 (ctrl, reg) & andmask) | ormask);
673 }