Add stubs for USB OHCI support.
authorKevin O'Connor <kevin@koconnor.net>
Mon, 12 Oct 2009 14:09:15 +0000 (10:09 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Mon, 12 Oct 2009 14:09:15 +0000 (10:09 -0400)
Enable USB wrapper functions to call either ohci or ehci helpers.
Implement pci_config_maskw in place of pci_set_bus_master.
Introduce 'struct usb_pipe' in place of 'void *' for pipes.

Makefile
src/config.h
src/pci.c
src/pci.h
src/usb-hid.c
src/usb-ohci.c [new file with mode: 0644]
src/usb-ohci.h [new file with mode: 0644]
src/usb-uhci.c
src/usb-uhci.h
src/usb.c
src/usb.h

index 97dd7957411b91851b240a2eda58b7dfc1991aa7..b1af624c65acce0246da451077b695e7d8b426ea 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@ OUT=out/
 SRCBOTH=output.c util.c block.c floppy.c ata.c misc.c mouse.c kbd.c pci.c \
         serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
         pnpbios.c pirtable.c vgahooks.c pmm.c ramdisk.c \
-        usb.c usb-uhci.c usb-hid.c paravirt.c
+        usb.c usb-uhci.c usb-ohci.c usb-hid.c paravirt.c
 SRC16=$(SRCBOTH) system.c disk.c apm.c pcibios.c font.c
 SRC32=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
       acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
index fa0dd1d820e024b683a263fc08e354292d1b89cf..ae83ae396c010ea31d8051d99009006f53afdc45 100644 (file)
@@ -30,6 +30,8 @@
 #define CONFIG_USB 1
 // Support USB UHCI controllers
 #define CONFIG_USB_UHCI 1
+// Support USB OHCI controllers
+#define CONFIG_USB_OHCI 0
 // Support USB keyboards
 #define CONFIG_USB_KEYBOARD 1
 // Support for IDE disk code
index e6b74d5347ba4e4f3e692cddf169667e82ffb770..143acf634910c32a7a9616c5aec23253965c4c03 100644 (file)
--- a/src/pci.c
+++ b/src/pci.c
@@ -48,6 +48,15 @@ u8 pci_config_readb(u16 bdf, u32 addr)
     return inb(PORT_PCI_DATA + (addr & 3));
 }
 
+void
+pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
+{
+    u16 val = pci_config_readw(bdf, addr);
+    val = (val & ~off) | on;
+    pci_config_writew(bdf, addr, val);
+}
+
+// Helper function for foreachpci() macro - return next device
 int
 pci_next(int bdf, int *pmax)
 {
@@ -156,10 +165,8 @@ pci_find_device(u16 vendid, u16 devid)
     int bdf, max;
     foreachpci(bdf, max) {
         u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
-        if (v != id)
-            continue;
-        // Found it.
-        return bdf;
+        if (v == id)
+            return bdf;
     }
     return -1;
 }
@@ -171,18 +178,8 @@ pci_find_class(u16 classid)
     int bdf, max;
     foreachpci(bdf, max) {
         u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
-        if (v != classid)
-            continue;
-        // Found it.
-        return bdf;
+        if (v == classid)
+            return bdf;
     }
     return -1;
 }
-
-void
-pci_set_bus_master(u16 bdf)
-{
-    u16 val = pci_config_readw(bdf, PCI_COMMAND);
-    val |= PCI_COMMAND_MASTER;
-    pci_config_writew(bdf, PCI_COMMAND, val);
-}
index 166b775e85e3cc7d2227fce78351dc54ef66ebed..a0b6b9c3e3c356ec5afefedda167550b73a31971 100644 (file)
--- a/src/pci.h
+++ b/src/pci.h
@@ -25,11 +25,11 @@ void pci_config_writeb(u16 bdf, u32 addr, u8 val);
 u32 pci_config_readl(u16 bdf, u32 addr);
 u16 pci_config_readw(u16 bdf, u32 addr);
 u8 pci_config_readb(u16 bdf, u32 addr);
+void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
 
 int pci_find_vga();
 int pci_find_device(u16 vendid, u16 devid);
 int pci_find_class(u16 classid);
-void pci_set_bus_master(u16 bdf);
 
 int pci_next(int bdf, int *pmax);
 #define foreachpci(BDF, MAX)                    \
index 7e5b3098fef7b38378450c4351d8010b3143ad02..6deb2b09e87b641cc38401766534cf3dee019f4f 100644 (file)
@@ -10,7 +10,7 @@
 #include "usb.h" // usb_ctrlrequest
 #include "biosvar.h" // GET_GLOBAL
 
-void *keyboard_pipe VAR16VISIBLE;
+struct usb_pipe *keyboard_pipe VAR16VISIBLE;
 
 
 /****************************************************************
@@ -78,7 +78,7 @@ usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface, int imax)
     if (ret)
         return -1;
 
-    void *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
+    struct usb_pipe *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
     if (!pipe)
         return -1;
     keyboard_pipe = pipe;
diff --git a/src/usb-ohci.c b/src/usb-ohci.c
new file mode 100644 (file)
index 0000000..638b8a4
--- /dev/null
@@ -0,0 +1,109 @@
+// Code for handling OHCI USB controllers.
+//
+// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
+//
+// This file may be distributed under the terms of the GNU LGPLv3 license.
+
+#include "util.h" // dprintf
+#include "pci.h" // pci_bdf_to_bus
+#include "config.h" // CONFIG_*
+#include "ioport.h" // outw
+#include "usb-ohci.h" // USBLEGSUP
+#include "pci_regs.h" // PCI_BASE_ADDRESS_4
+#include "usb.h" // struct usb_s
+#include "farptr.h" // GET_FLATPTR
+#include "biosvar.h" // GET_GLOBAL
+
+static void
+reset_ohci(struct usb_s *cntl)
+{
+}
+
+static void
+configure_ohci(struct usb_s *cntl)
+{
+    // XXX - check for SMM control?
+
+    writel(&cntl->ohci.regs->intrdisable, OHCI_INTR_MIE);
+
+    struct ohci_hcca *hcca = memalign_low(256, sizeof(*hcca));
+    if (!hcca) {
+        dprintf(1, "No ram for ohci init\n");
+        return;
+    }
+
+    
+}
+
+static void
+start_ohci(struct usb_s *cntl)
+{
+}
+
+// Find any devices connected to the root hub.
+static int
+check_ohci_ports(struct usb_s *cntl)
+{
+    return 0;
+}
+
+int
+ohci_init(struct usb_s *cntl)
+{
+    if (! CONFIG_USB_OHCI)
+        return 0;
+
+    cntl->type = USB_TYPE_OHCI;
+    u32 baseaddr = pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_0);
+    cntl->ohci.regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
+
+    dprintf(3, "OHCI init on dev %02x:%02x.%x (regs=%p)\n"
+            , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf)
+            , pci_bdf_to_fn(cntl->bdf), cntl->ohci.regs);
+
+    // Enable bus mastering and memory access.
+    pci_config_maskw(cntl->bdf, PCI_COMMAND
+                     , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
+
+    reset_ohci(cntl);
+    configure_ohci(cntl);
+    start_ohci(cntl);
+
+    int count = check_ohci_ports(cntl);
+    if (! count) {
+        // XXX - no devices; free data structures.
+        return 0;
+    }
+
+    return 0;
+}
+
+int
+ohci_control(u32 endp, int dir, const void *cmd, int cmdsize
+             , void *data, int datasize)
+{
+    if (! CONFIG_USB_OHCI)
+        return 0;
+
+    dprintf(5, "ohci_control %x\n", endp);
+    return 0;
+}
+
+struct usb_pipe *
+ohci_alloc_intr_pipe(u32 endp, int period)
+{
+    if (! CONFIG_USB_OHCI)
+        return NULL;
+
+    dprintf(7, "ohci_alloc_intr_pipe %x %d\n", endp, period);
+    return NULL;
+}
+
+int
+ohci_poll_intr(void *pipe, void *data)
+{
+    ASSERT16();
+    if (! CONFIG_USB_OHCI)
+        return -1;
+    return -1;
+}
diff --git a/src/usb-ohci.h b/src/usb-ohci.h
new file mode 100644 (file)
index 0000000..9d13f8c
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef __USB_OHCI_H
+#define __USB_OHCI_H
+
+// usb-ohci.c
+struct usb_s;
+int ohci_init(struct usb_s *cntl);
+int ohci_control(u32 endp, int dir, const void *cmd, int cmdsize
+                 , void *data, int datasize);
+struct usb_pipe *ohci_alloc_intr_pipe(u32 endp, int period);
+int ohci_poll_intr(void *pipe, void *data);
+
+
+/****************************************************************
+ * ohci structs and flags
+ ****************************************************************/
+
+struct ohci_ed {
+    u32 hwINFO;
+    u32 hwTailP;
+    u32 hwHeadP;
+    u32 hwNextED;
+} PACKED;
+
+#define ED_ISO          (1 << 15)
+#define ED_SKIP         (1 << 14)
+#define ED_LOWSPEED     (1 << 13)
+#define ED_OUT          (0x01 << 11)
+#define ED_IN           (0x02 << 11)
+
+#define ED_C            (0x02)
+#define ED_H            (0x01)
+
+struct ohci_td {
+    u32 hwINFO;
+    u32 hwCBP;
+    u32 hwNextTD;
+    u32 hwBE;
+} PACKED;
+
+#define TD_CC       0xf0000000
+#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
+#define TD_DI       0x00E00000
+#define TD_DI_SET(X) (((X) & 0x07)<< 21)
+
+#define TD_DONE     0x00020000
+#define TD_ISO      0x00010000
+
+#define TD_EC       0x0C000000
+#define TD_T        0x03000000
+#define TD_T_DATA0  0x02000000
+#define TD_T_DATA1  0x03000000
+#define TD_T_TOGGLE 0x00000000
+#define TD_DP       0x00180000
+#define TD_DP_SETUP 0x00000000
+#define TD_DP_IN    0x00100000
+#define TD_DP_OUT   0x00080000
+
+#define TD_R        0x00040000
+
+struct ohci_hcca {
+    u32  int_table[32];
+    u32  frame_no;
+    u32  done_head;
+    u8   reserved[120];
+} PACKED;
+
+struct ohci_regs {
+    u32  revision;
+    u32  control;
+    u32  cmdstatus;
+    u32  intrstatus;
+    u32  intrenable;
+    u32  intrdisable;
+
+    u32  hcca;
+    u32  ed_periodcurrent;
+    u32  ed_controlhead;
+    u32  ed_controlcurrent;
+    u32  ed_bulkhead;
+    u32  ed_bulkcurrent;
+    u32  donehead;
+
+    u32  fminterval;
+    u32  fmremaining;
+    u32  fmnumber;
+    u32  periodicstart;
+    u32  lsthresh;
+
+    u32  roothub_a;
+    u32  roothub_b;
+    u32  roothub_status;
+    u32  roothub_portstatus[15];
+} PACKED;
+
+#define OHCI_INTR_MIE   (1 << 31)
+
+#endif // usb-ohci.h
index 814e3eca56b812f14de86821f41476420feb1e3b..4d3df4521edef2bdfab83e51de22c7360503f0ab 100644 (file)
@@ -23,12 +23,12 @@ reset_uhci(struct usb_s *cntl)
     pci_config_writew(cntl->bdf, USBLEGSUP, USBLEGSUP_RWC);
 
     // Reset the HC
-    outw(USBCMD_HCRESET, cntl->iobase + USBCMD);
+    outw(USBCMD_HCRESET, cntl->uhci.iobase + USBCMD);
     udelay(5);
 
     // Disable interrupts and commands (just to be safe).
-    outw(0, cntl->iobase + USBINTR);
-    outw(0, cntl->iobase + USBCMD);
+    outw(0, cntl->uhci.iobase + USBINTR);
+    outw(0, cntl->uhci.iobase + USBCMD);
 }
 
 static void
@@ -40,7 +40,7 @@ configure_uhci(struct usb_s *cntl)
     struct uhci_qh *data_qh = malloc_low(sizeof(*data_qh));
     struct uhci_qh *term_qh = malloc_high(sizeof(*term_qh));
     if (!term_td || !fl || !data_qh || !term_qh) {
-        dprintf(1, "No ram for uhci init");
+        dprintf(1, "No ram for uhci init\n");
         return;
     }
 
@@ -57,7 +57,7 @@ configure_uhci(struct usb_s *cntl)
     memset(data_qh, 0, sizeof(*data_qh));
     data_qh->element = UHCI_PTR_TERM;
     data_qh->link = (u32)term_qh | UHCI_PTR_QH;
-    cntl->qh = data_qh;
+    cntl->uhci.qh = data_qh;
 
     // Set schedule to point to primary queue head
     int i;
@@ -66,28 +66,28 @@ configure_uhci(struct usb_s *cntl)
     }
 
     // Set the frame length to the default: 1 ms exactly
-    outb(USBSOF_DEFAULT, cntl->iobase + USBSOF);
+    outb(USBSOF_DEFAULT, cntl->uhci.iobase + USBSOF);
 
     // Store the frame list base address
-    outl((u32)fl->links, cntl->iobase + USBFLBASEADD);
+    outl((u32)fl->links, cntl->uhci.iobase + USBFLBASEADD);
 
     // Set the current frame number
-    outw(0, cntl->iobase + USBFRNUM);
+    outw(0, cntl->uhci.iobase + USBFRNUM);
 }
 
 static void
 start_uhci(struct usb_s *cntl)
 {
     // Mark as configured and running with a 64-byte max packet.
-    outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->iobase + USBCMD);
+    outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->uhci.iobase + USBCMD);
 }
 
 // Find any devices connected to the root hub.
 static int
 check_ports(struct usb_s *cntl)
 {
-    u16 port1 = inw(cntl->iobase + USBPORTSC1);
-    u16 port2 = inw(cntl->iobase + USBPORTSC2);
+    u16 port1 = inw(cntl->uhci.iobase + USBPORTSC1);
+    u16 port2 = inw(cntl->uhci.iobase + USBPORTSC2);
 
     if (!((port1 & USBPORTSC_CCS) || (port2 & USBPORTSC_CCS)))
         // No devices
@@ -95,30 +95,30 @@ check_ports(struct usb_s *cntl)
 
     // reset ports
     if (port1 & USBPORTSC_CCS)
-        outw(USBPORTSC_PR, cntl->iobase + USBPORTSC1);
+        outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC1);
     if (port2 & USBPORTSC_CCS)
-        outw(USBPORTSC_PR, cntl->iobase + USBPORTSC2);
+        outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC2);
     mdelay(10);
-    outw(0, cntl->iobase + USBPORTSC1);
-    outw(0, cntl->iobase + USBPORTSC2);
+    outw(0, cntl->uhci.iobase + USBPORTSC1);
+    outw(0, cntl->uhci.iobase + USBPORTSC2);
     mdelay(10);
 
     // Configure ports
     int totalcount = 0;
-    port1 = inw(cntl->iobase + USBPORTSC1);
+    port1 = inw(cntl->uhci.iobase + USBPORTSC1);
     if (port1 & USBPORTSC_CCS) {
-        outw(USBPORTSC_PE, cntl->iobase + USBPORTSC1);
+        outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC1);
         int count = configure_usb_device(cntl, !!(port1 & USBPORTSC_LSDA));
         if (! count)
-            outw(0, cntl->iobase + USBPORTSC1);
+            outw(0, cntl->uhci.iobase + USBPORTSC1);
         totalcount += count;
     }
-    port2 = inw(cntl->iobase + USBPORTSC2);
+    port2 = inw(cntl->uhci.iobase + USBPORTSC2);
     if (port2 & USBPORTSC_CCS) {
-        outw(USBPORTSC_PE, cntl->iobase + USBPORTSC2);
+        outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC2);
         int count = configure_usb_device(cntl, !!(port2 & USBPORTSC_LSDA));
         if (! count)
-            outw(0, cntl->iobase + USBPORTSC2);
+            outw(0, cntl->uhci.iobase + USBPORTSC2);
         totalcount += count;
     }
     return totalcount;
@@ -130,14 +130,15 @@ uhci_init(struct usb_s *cntl)
     if (! CONFIG_USB_UHCI)
         return 0;
 
-    cntl->iobase = (pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_4)
-                    & PCI_BASE_ADDRESS_IO_MASK);
+    cntl->type = USB_TYPE_UHCI;
+    cntl->uhci.iobase = (pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_4)
+                         & PCI_BASE_ADDRESS_IO_MASK);
 
     dprintf(3, "UHCI init on dev %02x:%02x.%x (io=%x)\n"
             , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf)
-            , pci_bdf_to_fn(cntl->bdf), cntl->iobase);
+            , pci_bdf_to_fn(cntl->bdf), cntl->uhci.iobase);
 
-    pci_set_bus_master(cntl->bdf);
+    pci_config_maskw(cntl->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
 
     reset_uhci(cntl);
     configure_uhci(cntl);
@@ -213,7 +214,7 @@ uhci_control(u32 endp, int dir, const void *cmd, int cmdsize
     tds[i].buffer = 0;
 
     // Transfer data
-    struct uhci_qh *data_qh = cntl->qh;
+    struct uhci_qh *data_qh = cntl->uhci.qh;
     data_qh->element = (u32)&tds[0];
     int ret = wait_qh(data_qh);
     if (ret)
@@ -223,7 +224,7 @@ uhci_control(u32 endp, int dir, const void *cmd, int cmdsize
     return 0;
 }
 
-void *
+struct usb_pipe *
 uhci_alloc_intr_pipe(u32 endp, int period)
 {
     if (! CONFIG_USB_UHCI)
@@ -259,23 +260,24 @@ uhci_alloc_intr_pipe(u32 endp, int period)
     }
 
     qh->next_td = &tds[0];
+    qh->pipe.endp = endp;
 
     // XXX - need schedule - just add to primary list for now.
-    struct uhci_qh *data_qh = cntl->qh;
+    struct uhci_qh *data_qh = cntl->uhci.qh;
     qh->link = data_qh->link;
     data_qh->link = (u32)qh | UHCI_PTR_QH;
 
-    return qh;
+    return &qh->pipe;
 }
 
 int
-uhci_poll_intr(void *pipe, void *data)
+uhci_poll_intr(struct usb_pipe *pipe, void *data)
 {
     ASSERT16();
     if (! CONFIG_USB_UHCI)
         return -1;
 
-    struct uhci_qh *qh = pipe;
+    struct uhci_qh *qh = container_of(pipe, struct uhci_qh, pipe);
     struct uhci_td *td = GET_FLATPTR(qh->next_td);
     u32 status = GET_FLATPTR(td->status);
     u32 token = GET_FLATPTR(td->token);
index 6ad7e1582989a4e8c0eb7ca53a4fee0bbab88b77..b284fcc98738b480d413e602c50329dcd821d901 100644 (file)
@@ -1,13 +1,15 @@
 #ifndef __USB_UHCI_H
 #define __USB_UHCI_H
 
+#include "usb.h" // struct usb_pipe
+
 // usb-uhci.c
 struct usb_s;
 int uhci_init(struct usb_s *cntl);
 int uhci_control(u32 endp, int dir, const void *cmd, int cmdsize
                  , void *data, int datasize);
-void *uhci_alloc_intr_pipe(u32 endp, int period);
-int uhci_poll_intr(void *pipe, void *data);
+struct usb_pipe *uhci_alloc_intr_pipe(u32 endp, int period);
+int uhci_poll_intr(struct usb_pipe *pipe, void *data);
 
 
 /****************************************************************
@@ -119,7 +121,7 @@ struct uhci_qh {
 
     // Software fields
     struct uhci_td *next_td;
-    u32 reserved;
+    struct usb_pipe pipe;
 } PACKED;
 
 #define UHCI_PTR_BITS           0x000F
index 8e14b8eca5cf21377662a726139dc5ff3ccb6bc9..edaef11486445c3c61f838d6b07f083b67db60c6 100644 (file)
--- a/src/usb.c
+++ b/src/usb.c
@@ -10,6 +10,7 @@
 #include "pci_regs.h" // PCI_CLASS_REVISION
 #include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
 #include "usb-uhci.h" // uhci_init
+#include "usb-ohci.h" // ohci_init
 #include "usb-hid.h" // usb_keyboard_setup
 #include "usb.h" // struct usb_s
 
@@ -19,19 +20,40 @@ static int
 send_control(u32 endp, int dir, const void *cmd, int cmdsize
              , void *data, int datasize)
 {
-    return uhci_control(endp, dir, cmd, cmdsize, data, datasize);
+    struct usb_s *cntl = endp2cntl(endp);
+    switch (cntl->type) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_control(endp, dir, cmd, cmdsize, data, datasize);
+    case USB_TYPE_OHCI:
+        return ohci_control(endp, dir, cmd, cmdsize, data, datasize);
+    }
 }
 
-void *
+struct usb_pipe *
 alloc_intr_pipe(u32 endp, int period)
 {
-    return uhci_alloc_intr_pipe(endp, period);
+    struct usb_s *cntl = endp2cntl(endp);
+    switch (cntl->type) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_alloc_intr_pipe(endp, period);
+    case USB_TYPE_OHCI:
+        return ohci_alloc_intr_pipe(endp, period);
+    }
 }
 
 int
-usb_poll_intr(void *pipe, void *data)
+usb_poll_intr(struct usb_pipe *pipe, void *data)
 {
-    return uhci_poll_intr(pipe, data);
+    struct usb_s *cntl = endp2cntl(pipe->endp);
+    switch (cntl->type) {
+    default:
+    case USB_TYPE_UHCI:
+        return uhci_poll_intr(pipe, data);
+    case USB_TYPE_OHCI:
+        return ohci_poll_intr(pipe, data);
+    }
 }
 
 int
@@ -195,6 +217,8 @@ usb_setup()
         int devcount = 0;
         if (code == PCI_CLASS_SERIAL_USB_UHCI)
             devcount = uhci_init(cntl);
+        else if (code == PCI_CLASS_SERIAL_USB_OHCI)
+            devcount = ohci_init(cntl);
 
         if (devcount > 0) {
             // Success
index e8d74553403a4f5731a6b78732e29a52dc67706a..36fde59fe7e0489185efca730ef2a7e77351b23d 100644 (file)
--- a/src/usb.h
+++ b/src/usb.h
@@ -4,14 +4,30 @@
 
 // Local information for a usb controller.
 struct usb_s {
-    u16 bdf;
-    u16 iobase;
+    u8 type;
     u8 maxaddr;
-    void *qh;
+    u16 bdf;
+
+    union {
+        struct {
+            u16 iobase;
+            void *qh;
+        } uhci;
+        struct {
+            struct ohci_regs *regs;
+        } ohci;
+    };
 };
 
+#define USB_TYPE_UHCI 1
+#define USB_TYPE_OHCI 2
+
 extern struct usb_s USBControllers[];
 
+struct usb_pipe {
+    u32 endp;
+};
+
 #define USB_MAXADDR 127
 
 // usb.c
@@ -20,8 +36,8 @@ int configure_usb_device(struct usb_s *cntl, int lowspeed);
 struct usb_ctrlrequest;
 int send_default_control(u32 endp, const struct usb_ctrlrequest *req
                          , void *data);
-void *alloc_intr_pipe(u32 endp, int period);
-int usb_poll_intr(void *pipe, void *data);
+struct usb_pipe *alloc_intr_pipe(u32 endp, int period);
+int usb_poll_intr(struct usb_pipe *pipe, void *data);
 
 
 /****************************************************************