2 * Universal Host Controller Interface driver
5 * Better (any) root hub handling
11 #include "threads/pte.h"
12 #include "threads/malloc.h"
13 #include "threads/palloc.h"
14 #include "threads/synch.h"
15 #include "threads/interrupt.h"
16 #include "threads/thread.h"
17 #include "devices/pci.h"
18 #include "devices/usb.h"
19 #include "devices/timer.h"
21 #define UHCI_MAX_PORTS 8
23 #define FRAME_LIST_ENTRIES 1024
24 #define TD_ENTRIES (4096/32) /* number of entries allocated */
25 #define QH_ENTRIES (4096/16)
27 /* uhci pci registers */
28 #define UHCI_REG_USBCMD 0x00 /* Command */
29 #define UHCI_REG_USBSTS 0x02 /* Status */
30 #define UHCI_REG_USBINTR 0x04 /* interrupt enable */
31 #define UHCI_REG_FRNUM 0x06 /* frame number */
32 #define UHCI_REG_FLBASEADD 0x08 /* frame list base address */
33 #define UHCI_REG_SOFMOD 0x0c /* start of frame modify */
34 #define UHCI_REG_PORTSC1 0x10 /* port 1 status/control */
35 #define UHCI_REG_PORTSC2 0x12 /* port 2 status/control */
36 #define UHCI_REGSZ 0x20 /* register iospace size */
38 /* in PCI config space for some reason */
39 #define UHCI_REG_LEGSUP 0xC0
42 /* command register */
43 #define USB_CMD_MAX_PACKET (1 << 7)
44 #define USB_CMD_CONFIGURE (1 << 6)
45 #define USB_CMD_FGR (1 << 4) /* force global resume */
46 #define USB_CMD_EGSM (1 << 3) /* global suspend mode */
47 #define USB_CMD_GRESET (1 << 2) /* global reset */
48 #define USB_CMD_HCRESET (1 << 1) /* host controller reset */
49 #define USB_CMD_RS (1 << 0) /* run/stop */
52 #define USB_STATUS_HALTED (1 << 5)
53 #define USB_STATUS_PROCESSERR (1 << 4)
54 #define USB_STATUS_HOSTERR (1 << 3)
55 #define USB_STATUS_RESUME (1 << 2)
56 #define USB_STATUS_INTERR (1 << 1)
57 #define USB_STATUS_USBINT (1 << 0)
59 /* interrupt enable register */
60 #define USB_INTR_SHORT (1 << 3) /* enable short packets */
61 #define USB_INTR_IOC (1 << 2) /* interrupt on complete */
62 #define USB_INTR_RESUME (1 << 1) /* resume interrupt enable */
63 #define USB_INTR_TIMEOUT (1 << 0) /* timeout int enable */
65 /* port control register */
66 #define USB_PORT_SUSPEND (1 << 12)
67 #define USB_PORT_RESET (1 << 9)
68 #define USB_PORT_LOWSPEED (1 << 8)
69 #define USB_PORT_RESUMED (1 << 6) /* resume detected */
70 #define USB_PORT_CHANGE (1 << 3) /* enable change */
71 #define USB_PORT_ENABLE (1 << 2) /* enable the port */
72 #define USB_PORT_CONNECTCHG (1 << 1) /* connect status changed */
73 #define USB_PORT_CONNECTSTATUS (1 << 0) /* device is connected */
75 #define ptr_to_flp(x) (((uintptr_t)x) >> 4)
76 #define flp_to_ptr(x) (uintptr_t)(((uintptr_t)x) << 4)
78 #define UHCI_LP_POINTER 0xfffffff0 /* Pointer field. */
79 #define UHCI_LP_TERMINATE 0x00000001 /* 1=pointer not valid */
80 #define UHCI_LP_QUEUE_HEAD 0x00000002 /* 1=points to queue head,
81 0=points to tx descriptor. */
82 #define UHCI_LP_DEPTH 0x00000004 /* Tx descriptor only:
83 1=execute depth first,
84 0=execute breadth first. */
88 uint32_t pid:8; /* packet id */
89 uint32_t dev_addr:7; /* device address */
91 uint32_t data_toggle:1;
93 uint32_t maxlen:11; /* maximum pkt length */
98 uint32_t actual_len:11;
101 /* status information */
107 uint32_t buffer_error:1;
112 uint32_t ioc:1; /* issue int on complete */
113 uint32_t ios:1; /* isochronous select */
114 uint32_t ls:1; /* low speed device */
115 uint32_t error_limit:2; /* errors before interrupt */
116 uint32_t spd:1; /* short packet detect */
120 #define TD_FL_ASYNC 1
121 #define TD_FL_USED 0x80000000
126 struct td_control control;
127 struct td_token token;
131 struct list_elem td_elem; /* Element in queue_head's td_list. */
137 uint32_t next_qh; /* Queue head link pointer. */
138 uint32_t first_td; /* Queue element link pointer. */
140 struct list_elem qh_elem; /* Element in uhci_info's qh_list. */
141 struct list td_list; /* List of tx_descriptor structures. */
142 struct semaphore completion; /* Upped by interrupt on completion. */
149 struct pci_io *io; /* pci io space */
151 uint32_t *frame_list; /* Page-aligned list of 1024 frame pointers. */
152 struct list qh_list; /* List of queue_head structuress. */
153 struct queue_head *term_qh;
156 uint8_t attached_ports;
161 struct tx_descriptor *td;
162 struct uhci_dev_info *ud;
163 struct semaphore sem;
164 struct list_elem peers;
169 struct uhci_info *ui; /* owner */
170 bool low_speed; /* whether device is low speed */
171 int dev_addr; /* device address */
172 int errors; /* aggregate errors */
173 struct list_elem peers; /* next dev on host */
179 struct uhci_dev_info *ud;
181 int maxpkt; /* max packet size */
182 int toggle; /* data toggle bit for bulk transfers */
185 #define uhci_lock(x) lock_acquire(&(x)->lock)
186 #define uhci_unlock(x) lock_release(&(x)->lock)
187 #define dev_lock(x) lock_acquire(&(x)->lock)
188 #define dev_unlock(x) lock_release(&(x)->lock)
191 static int token_to_pid (int token);
193 static int uhci_dev_control (host_eop_info, struct usb_setup_pkt *,
194 void *data, size_t *size);
195 static int uhci_dev_bulk (host_eop_info, bool out, void *data, size_t *size);
196 static int uhci_detect_change (host_info);
199 static struct queue_head *allocate_queue_head (void);
200 static struct tx_descriptor *allocate_transfer_descriptor (struct queue_head *);
203 static void uhci_process_completed (struct uhci_info *ui);
207 static struct uhci_info *uhci_create_info (struct pci_io *io);
208 static void uhci_destroy_info (struct uhci_info *ui);
209 static host_eop_info uhci_create_eop (host_dev_info hd, int eop, int maxpkt);
210 static void uhci_remove_eop (host_eop_info hei);
211 static host_dev_info uhci_create_chan (host_info hi, int dev_addr, int ver);
212 static void uhci_destroy_chan (host_dev_info);
213 static void uhci_modify_chan (host_dev_info, int dev_addr, int ver);
215 static int check_and_flip_change (struct uhci_info *ui, int reg);
216 #define uhci_is_stopped(x) (pci_reg_read16((x)->io, UHCI_REG_USBSTS) \
218 #define uhci_port_enabled(x, y) (pci_reg_read16((x)->io, (y)) & USB_PORT_ENABLE)
219 static void uhci_setup_td (struct tx_descriptor *td, int dev_addr, int token,
220 int eop, void *pkt, int sz, int toggle, bool ls);
221 static int uhci_enable_port (struct uhci_info *ui, int port);
222 static void uhci_irq (void *uhci_data);
223 static void uhci_detect_ports (struct uhci_info *ui);
225 static void dump_regs (struct uhci_info *ui);
227 void uhci_init (void);
230 static struct usb_host uhci_host = {
232 .dev_control = uhci_dev_control,
233 .dev_bulk = uhci_dev_bulk,
234 .detect_change = uhci_detect_change,
235 .create_dev_channel = uhci_create_chan,
236 .remove_dev_channel = uhci_destroy_chan,
237 .modify_dev_channel = uhci_modify_chan,
238 .create_eop = uhci_create_eop,
239 .remove_eop = uhci_remove_eop
245 uint32_t q = vtop (p);
246 ASSERT ((q & UHCI_LP_POINTER) == q);
257 while ((pd = pci_get_dev_by_class (PCI_MAJOR_SERIALBUS, PCI_MINOR_USB,
258 PCI_USB_IFACE_UHCI, dev_num)) != NULL)
261 struct uhci_info *ui;
268 while ((io = pci_io_enum (pd, io)) != NULL)
270 if (pci_io_size (io) == UHCI_REGSZ)
274 /* not found, next PCI */
278 ui = uhci_create_info (io);
283 uhci_detect_ports (ui);
285 pci_write_config16 (ui->dev, UHCI_REG_LEGSUP, 0x8f00);
286 pci_reg_write16 (ui->io, UHCI_REG_USBCMD, USB_CMD_HCRESET);
287 asm volatile ("mfence":::"memory");
289 if (pci_reg_read16 (ui->io, UHCI_REG_USBCMD) & USB_CMD_HCRESET)
290 printf ("reset failed!\n");
291 pci_reg_write16 (ui->io, UHCI_REG_USBINTR, 0);
292 pci_reg_write16 (ui->io, UHCI_REG_USBCMD, 0);
294 pci_reg_write16 (ui->io, UHCI_REG_PORTSC1, 0);
295 pci_reg_write16 (ui->io, UHCI_REG_PORTSC2, 0);
297 pci_reg_write8 (ui->io, UHCI_REG_SOFMOD, 64);
298 pci_reg_write32 (ui->io, UHCI_REG_FLBASEADD, make_lp (ui->frame_list));
299 pci_reg_write16 (ui->io, UHCI_REG_FRNUM, 0);
300 asm volatile ("mfence":::"memory");
302 /* deactivate SMM junk, only enable IRQ */
303 pci_write_config16 (ui->dev, UHCI_REG_LEGSUP, 0x2000);
305 asm volatile ("mfence":::"memory");
307 pci_reg_write16 (ui->io, UHCI_REG_USBCMD,
308 USB_CMD_RS | USB_CMD_CONFIGURE | USB_CMD_MAX_PACKET);
309 pci_reg_write16 (ui->io, UHCI_REG_USBINTR,
310 USB_INTR_SHORT | USB_INTR_IOC |
311 USB_INTR_TIMEOUT | USB_INTR_RESUME);
313 asm volatile ("mfence":::"memory");
315 printf ("UHCI: Enabling %d root ports\n", ui->num_ports);
316 ui->attached_ports = 0;
317 for (i = 0; i < ui->num_ports; i++)
318 ui->attached_ports += uhci_enable_port (ui, i);
320 pci_register_irq (pd, uhci_irq, ui);
322 usb_register_host (&uhci_host, ui);
326 #define UHCI_PORT_TIMEOUT 1000
328 uhci_enable_port (struct uhci_info *ui, int idx)
331 int time, stable_since;
335 port = UHCI_REG_PORTSC1 + idx * 2;
339 for (time = 0; ; time += 25)
342 new_status = pci_reg_read16 (ui->io, port);
343 if (status != (new_status & USB_PORT_CONNECTSTATUS)
344 || new_status & USB_PORT_CONNECTCHG)
346 if (new_status & USB_PORT_CONNECTCHG)
347 pci_reg_write16 (ui->io, port, (new_status & ~0xe80a) | USB_PORT_CONNECTCHG);
349 status = new_status & USB_PORT_CONNECTSTATUS;
351 else if (time - stable_since >= 100)
353 else if (time >= 1500)
357 //printf ("time=%d stable_since=%d\n", time, stable_since);
359 if (!(status & USB_PORT_CONNECTSTATUS))
362 for (count = 0; count < 3; count++)
364 status = pci_reg_read16 (ui->io, port) & ~0xe80a;
365 //printf ("read %x, write %x, ", status, status | USB_PORT_RESET);
366 pci_reg_write16 (ui->io, port, status | USB_PORT_RESET);
369 status = pci_reg_read16 (ui->io, port) & ~0xe80a;
370 //printf ("read %x, write %x, ", status, status & ~USB_PORT_RESET);
371 pci_reg_write16 (ui->io, port, status & ~USB_PORT_RESET);
374 status = pci_reg_read16 (ui->io, port) & ~0xe80a;
375 //printf ("read %x, write %x, ", status, status & ~(USB_PORT_CONNECTCHG | USB_PORT_CHANGE));
376 pci_reg_write16 (ui->io, port, status & ~(USB_PORT_CONNECTCHG | USB_PORT_CHANGE));
378 status = pci_reg_read16 (ui->io, port) & ~0xe80a;
379 //printf ("read %x, write %x, ", status, status | USB_PORT_ENABLE);
380 pci_reg_write16 (ui->io, port, status | USB_PORT_ENABLE);
382 status = pci_reg_read16 (ui->io, port);
383 //printf ("read %x\n", status);
384 if (status & USB_PORT_ENABLE)
388 if (!(status & USB_PORT_CONNECTSTATUS))
390 //printf ("port %d not connected\n", idx);
391 pci_reg_write16 (ui->io, port, 0);
401 dump_regs (struct uhci_info *ui)
403 int regs[] = { 0, 2, 4, 6, 8, 0xc, 0x10, 0x12 };
404 int sz[] = { 2, 2, 2, 2, 4, 2, 2, 2 };
406 { "cmd", "sts", "intr", "frnum", "base", "sofmod", "portsc1", "portsc2" };
408 printf ("UHCI registers: ");
409 for (i = 0; i < 8; i++)
413 printf ("%s: %x", name[i], (sz[i] == 2) ?
414 pci_reg_read16 (ui->io, regs[i]) :
415 pci_reg_read32 (ui->io, regs[i]));
417 printf (", legsup=%x\n", pci_read_config16 (ui->dev, UHCI_REG_LEGSUP));
422 uhci_destroy_info (struct uhci_info *ui)
424 palloc_free_page (ui->frame_list);
428 static struct uhci_info *
429 uhci_create_info (struct pci_io *io)
431 struct uhci_info *ui;
432 struct queue_head *qh1, *qh2;
433 struct tx_descriptor *td;
436 ui = malloc (sizeof (struct uhci_info));
439 lock_init (&ui->lock);
441 /* Create initial queue head and put on qh list. */
442 list_init (&ui->qh_list);
444 qh1 = allocate_queue_head ();
445 list_push_back (&ui->qh_list, &qh1->qh_elem);
447 ui->term_qh = qh2 = allocate_queue_head ();
448 qh1->next_qh = make_lp (qh2) | UHCI_LP_QUEUE_HEAD;
450 td = allocate_transfer_descriptor (qh2);
451 td->token.maxlen = 0x7ff;
452 td->token.dev_addr = 0x7f;
453 td->token.pid = USB_TOKEN_IN;
455 /* Create an empty schedule */
456 ui->frame_list = palloc_get_page (PAL_ASSERT | PAL_NOCACHE);
457 for (i = 0; i < FRAME_LIST_ENTRIES; i++)
458 ui->frame_list[i] = make_lp (qh1) | UHCI_LP_QUEUE_HEAD;
459 //printf ("frame_list=%p: %08x\n", ui->frame_list, ui->frame_list[0]);
461 // thread_create ("uhci watchdog", PRI_MIN,
462 // (thread_func *) uhci_stall_watchdog, ui);
468 print_td_list (struct queue_head *qh)
472 for (e = list_begin (&qh->td_list); e != list_end (&qh->td_list);
475 struct tx_descriptor *td = list_entry (e, struct tx_descriptor, td_elem);
476 printf (" %08x: next_td=%08x control=%08x %d,%d,%d,%d,%x buf_ptr=%08x\n",
477 vtop (td), td->next_td, *(uint32_t *) &td->control,
478 (td->token.maxlen + 1) & 0x7ff, td->token.data_toggle,
479 td->token.end_point, td->token.dev_addr, td->token.pid,
481 hex_dump (0, ptov (td->buf_ptr), (td->token.maxlen + 1) & 0x7ff, true);
486 print_qh_list (struct uhci_info *ui)
490 for (e = list_begin (&ui->qh_list); e != list_end (&ui->qh_list);
493 struct queue_head *qh = list_entry (e, struct queue_head, qh_elem);
494 printf ("%08x: next_qh=%08x first_td=%08x\n",
495 vtop (qh), qh->next_qh, qh->first_td);
500 static struct tx_descriptor *
501 execute_qh (struct uhci_info *ui, struct queue_head *qh)
503 struct queue_head *prev_qh;
504 struct tx_descriptor *last_td;
505 enum intr_level old_level;
507 /* Mark the final tx descriptor to interrupt us when it's
509 last_td = list_entry (list_back (&qh->td_list), struct tx_descriptor, td_elem);
510 last_td->control.ioc = 1;
512 qh->next_qh = make_lp (ui->term_qh) | UHCI_LP_QUEUE_HEAD;
514 /* Add the queue head to the list of queue heads.
515 qh_list is accessed from uhci_irq so we need to disable
517 old_level = intr_disable ();
518 list_push_back (&ui->qh_list, &qh->qh_elem);
519 prev_qh = list_entry (list_prev (&qh->qh_elem), struct queue_head, qh_elem);
520 prev_qh->next_qh = make_lp (qh) | UHCI_LP_QUEUE_HEAD;
523 intr_set_level (old_level);
525 /* Wait until the queue has been processed. */
526 //printf ("down...");
527 sema_down (&qh->completion);
531 /* Return the descriptor that failed, or a null pointer on
533 return (qh->first_td & UHCI_LP_TERMINATE
535 : ptov (qh->first_td & UHCI_LP_POINTER));
539 uhci_dev_control (host_eop_info hei, struct usb_setup_pkt *setup,
540 void *data, size_t *size)
542 struct uhci_eop_info *ue;
543 struct uhci_dev_info *ud;
544 struct queue_head *qh;
545 struct tx_descriptor *td;
553 /* don't bother if ports are down */
554 if (ud->ui->attached_ports == 0)
555 return USB_HOST_ERR_NODEV;
557 qh = allocate_queue_head ();
559 return USB_HOST_ERR_NOMEM;
561 /* Setup stage: SETUP packet. */
562 td = allocate_transfer_descriptor (qh);
564 return USB_HOST_ERR_NOMEM;
566 uhci_setup_td (td, ud->dev_addr, USB_TOKEN_SETUP, ue->eop,
567 setup, sizeof *setup, ue->toggle, ud->low_speed);
569 /* Data stage: IN/OUT packets. */
573 while (size_alloced < *size)
575 int packet = *size - size_alloced;
576 if (packet > ue->maxpkt)
579 td = allocate_transfer_descriptor (qh);
581 return USB_HOST_ERR_NOMEM;
583 ue->toggle = !ue->toggle;
584 uhci_setup_td (td, ud->dev_addr,
585 setup->direction ? USB_TOKEN_IN : USB_TOKEN_OUT,
586 ue->eop, data + size_alloced, packet,
587 ue->toggle, ud->low_speed);
589 td->offset = size_alloced;
591 size_alloced += packet;
595 /* Status stage: OUT/IN packet. */
596 td = allocate_transfer_descriptor (qh);
598 return USB_HOST_ERR_NOMEM;
600 status_token = setup->direction ? USB_TOKEN_OUT : USB_TOKEN_IN;
601 uhci_setup_td (td, ud->dev_addr, status_token, ue->eop,
602 NULL, 0, ue->toggle, ud->low_speed);
605 td = execute_qh (ud->ui, qh);
607 ue->toggle = td->token.data_toggle;
608 //printf ("execution done, td=%p\n", td);
611 && list_front (&qh->td_list) != &td->td_elem
612 && list_back (&qh->td_list) != &td->td_elem
613 && !td->control.active
614 && !td->control.stalled
615 && !td->control.buffer_error
616 && !td->control.babble
618 && !td->control.timeout
619 && !td->control.bitstuff
620 && (((td->control.actual_len + 1) & 0x7ff)
621 < ((td->token.maxlen + 1) & 0x7ff)))
623 /* Short packet detected in stream, which indicates that
624 the input data is shorter than the maximum that we
627 Re-queue the Status stage. */
629 *size = td->offset + ((td->control.actual_len + 1) & 0x7ff);
631 //delayed_free_qh (qh);
633 qh = allocate_queue_head ();
635 return USB_HOST_ERR_NOMEM;
637 td = allocate_transfer_descriptor (qh);
639 return USB_HOST_ERR_NOMEM;
641 uhci_setup_td (td, ud->dev_addr, status_token, ue->eop,
642 NULL, 0, ue->toggle, ud->low_speed);
644 //printf ("short packet, requeuing status\n");
645 td = execute_qh (ud->ui, qh);
647 ue->toggle = td->token.data_toggle;
652 if (td->control.bitstuff)
653 err = USB_HOST_ERR_BITSTUFF;
654 else if (td->control.timeout)
655 err = USB_HOST_ERR_TIMEOUT;
656 else if (td->control.nak)
657 err = USB_HOST_ERR_NAK;
658 else if (td->control.babble)
659 err = USB_HOST_ERR_BABBLE;
660 else if (td->control.buffer_error)
661 err = USB_HOST_ERR_BUFFER;
662 else if (td->control.stalled)
663 err = USB_HOST_ERR_STALL;
665 PANIC ("unknown USB error");
668 err = USB_HOST_ERR_NONE;
670 //delayed_free_qh (qh);
672 //printf ("err=%d\n", err);
673 if (err == 0 && data != NULL)
674 hex_dump (0, data, *size, true);
679 uhci_dev_bulk (host_eop_info hei, bool out, void *data, size_t *size)
681 struct uhci_eop_info *ue;
682 struct uhci_dev_info *ud;
683 struct queue_head *qh;
684 struct tx_descriptor *td;
691 /* don't bother if ports are down */
692 if (ud->ui->attached_ports == 0)
693 return USB_HOST_ERR_NODEV;
696 memset (data, 0xcc, *size);
698 qh = allocate_queue_head ();
700 return USB_HOST_ERR_NOMEM;
702 /* Data stage: IN/OUT packets. */
704 while (size_alloced < *size)
706 int packet = *size - size_alloced;
707 if (packet > ue->maxpkt)
710 td = allocate_transfer_descriptor (qh);
712 return USB_HOST_ERR_NOMEM;
714 uhci_setup_td (td, ud->dev_addr,
715 out ? USB_TOKEN_OUT : USB_TOKEN_IN,
716 ue->eop, data + size_alloced, packet,
717 ue->toggle, ud->low_speed);
718 ue->toggle = !ue->toggle;
720 td->offset = size_alloced;
722 size_alloced += packet;
726 td = execute_qh (ud->ui, qh);
729 ue->toggle = !td->token.data_toggle;
731 *size = td->offset + ((td->control.actual_len + 1) & 0x7ff);
733 if (td->control.bitstuff)
734 err = USB_HOST_ERR_BITSTUFF;
735 else if (td->control.timeout)
736 err = USB_HOST_ERR_TIMEOUT;
737 else if (td->control.nak)
738 err = USB_HOST_ERR_NAK;
739 else if (td->control.babble)
740 err = USB_HOST_ERR_BABBLE;
741 else if (td->control.buffer_error)
742 err = USB_HOST_ERR_BUFFER;
743 else if (td->control.stalled)
744 err = USB_HOST_ERR_STALL;
747 /* Just a short packet. */
748 printf ("short packet\n");
749 err = USB_HOST_ERR_NONE;
752 PANIC ("unknown USB error");
755 err = USB_HOST_ERR_NONE;
757 //delayed_free_qh (qh);
760 PANIC ("err=%d\n", err);
761 if (err == 0 && data != NULL && !out)
762 hex_dump (0, data, *size, true);
767 token_to_pid (int token)
771 case USB_TOKEN_SETUP:
772 return USB_PID_SETUP;
778 PANIC ("Unknown USB token\n");
783 uhci_setup_td (struct tx_descriptor *td, int dev_addr, int token,
784 int eop, void *pkt, int sz, int toggle, bool ls UNUSED)
786 td->buf_ptr = (sz == 0) ? 0 : vtop (pkt);
788 td->token.pid = token_to_pid (token);
789 td->token.dev_addr = dev_addr;
790 td->token.end_point = eop;
791 td->token.data_toggle = toggle;
792 td->token.maxlen = sz - 1;
793 // td->control.ls = ls;
795 td->control.actual_len = 0;
796 td->control.active = 1;
797 td->next_td = UHCI_LP_TERMINATE;
799 /* kill packet if too many errors */
800 td->control.error_limit = 3;
804 uhci_irq (void *uhci_data)
806 struct uhci_info *ui;
809 //printf ("uhci_irq\n");
811 status = pci_reg_read16 (ui->io, UHCI_REG_USBSTS);
812 if (status & USB_STATUS_PROCESSERR)
816 PANIC ("UHCI: Malformed schedule");
818 else if (status & USB_STATUS_HOSTERR)
822 PANIC ("UHCI: Host system error");
824 else if (status & (USB_STATUS_INTERR | USB_STATUS_USBINT))
827 //pci_reg_write16 (ui->io, UHCI_REG_USBINTR, 0);
828 pci_reg_write16 (ui->io, UHCI_REG_USBSTS,
829 status & (USB_STATUS_INTERR | USB_STATUS_USBINT));
830 if (status & USB_STATUS_INTERR)
832 printf ("USB_STATUS_INTERR\n");
836 //if (status & USB_STATUS_USBINT)
837 //printf ("USB_STATUS_USBINT\n");
839 uhci_process_completed (ui);
842 printf ("nothing?\n");
845 /* Queue processing finished.
846 Remove from lists, wake up waiter. */
848 finish_qh (struct queue_head *qh)
850 struct list_elem *p = list_prev (&qh->qh_elem);
851 struct queue_head *prev_qh = list_entry (p, struct queue_head, qh_elem);
853 //printf ("finish_qh\n");
854 prev_qh->next_qh = qh->next_qh;
855 list_remove (&qh->qh_elem);
856 sema_up (&qh->completion);
860 uhci_process_completed (struct uhci_info *ui)
864 if (list_empty (&ui->qh_list))
867 /* Note that we skip the first element in the list, which is an
868 empty queue head pointed to by every frame list pointer. */
869 for (e = list_next (list_begin (&ui->qh_list));
870 e != list_end (&ui->qh_list); )
872 struct queue_head *qh = list_entry (e, struct queue_head, qh_elem);
873 uint32_t first_td = qh->first_td;
877 //printf ("first_td=%08x\n", first_td);
878 if ((first_td & UHCI_LP_POINTER) == 0)
882 struct tx_descriptor *td = ptov (first_td & UHCI_LP_POINTER);
883 if (!td->control.active)
894 uhci_detect_change (host_info hi)
896 struct uhci_info *ui;
903 for (i = 0; i < ui->num_ports; i++)
905 change = check_and_flip_change (ui, i);
915 check_and_flip_change (struct uhci_info *ui, int port)
920 reg = UHCI_REG_PORTSC1 + port * 2;
921 val = pci_reg_read16 (ui->io, reg);
922 if (val & USB_PORT_CHANGE)
924 pci_reg_write16 (ui->io, reg, val & ~(USB_PORT_CHANGE));
931 static struct queue_head *
932 allocate_queue_head (void)
934 size_t qh_size = sizeof *allocate_queue_head ();
935 struct queue_head *qh = calloc (1, qh_size > 16 ? qh_size : 16);
938 qh->next_qh = UHCI_LP_TERMINATE;
939 qh->first_td = UHCI_LP_TERMINATE;
940 list_init (&qh->td_list);
941 sema_init (&qh->completion, 0);
946 static struct tx_descriptor *
947 allocate_transfer_descriptor (struct queue_head *qh)
949 struct tx_descriptor *td = calloc (1, sizeof *td);
952 /* FIXME: free the whole queue head. */
956 if (list_empty (&qh->td_list))
957 qh->first_td = make_lp (td);
960 struct list_elem *p = list_back (&qh->td_list);
961 struct tx_descriptor *prev_td = list_entry (p, struct tx_descriptor,
963 prev_td->next_td = make_lp (td);
965 list_push_back (&qh->td_list, &td->td_elem);
966 td->next_td = UHCI_LP_TERMINATE;
971 uhci_create_chan (host_info hi, int dev_addr, int ver)
973 struct uhci_info *ui;
974 struct uhci_dev_info *ud;
976 ASSERT (dev_addr <= 127 && dev_addr >= 0);
980 ud = malloc (sizeof (struct uhci_dev_info));
981 ud->dev_addr = dev_addr;
982 ud->low_speed = (ver == USB_VERSION_1_0) ? true : false;
986 lock_init (&ud->lock);
992 uhci_destroy_chan (host_dev_info hd UNUSED)
995 /* FIXME: wake up all waiting queue heads. */
996 /* FIXME: arrange for qhs to be freed. */
1000 uhci_modify_chan (host_dev_info hd, int dev_addr, int ver)
1002 struct uhci_dev_info *ud;
1005 ud->dev_addr = dev_addr;
1006 ud->low_speed = (ver == USB_VERSION_1_0) ? true : false;
1010 uhci_detect_ports (struct uhci_info *ui)
1014 for (i = 0; i < UHCI_MAX_PORTS; i++)
1017 status = pci_reg_read16 (ui->io, UHCI_REG_PORTSC1 + i * 2);
1018 if (!(status & 0x0080) || status == 0xffff)
1024 static host_eop_info
1025 uhci_create_eop (host_dev_info hd, int eop, int maxpkt)
1027 struct uhci_dev_info *ud;
1028 struct uhci_eop_info *e;
1032 e = malloc (sizeof (struct uhci_eop_info));
1042 uhci_remove_eop (host_eop_info hei)