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