Modules/EHCI - Planning out, might need USB HC API changes
authorJohn Hodge <[email protected]>
Mon, 16 Jul 2012 05:33:38 +0000 (13:33 +0800)
committerJohn Hodge <[email protected]>
Mon, 16 Jul 2012 05:33:38 +0000 (13:33 +0800)
KernelLand/Modules/USB/EHCI/Makefile [new file with mode: 0644]
KernelLand/Modules/USB/EHCI/ehci.c [new file with mode: 0644]
KernelLand/Modules/USB/EHCI/ehci.h

diff --git a/KernelLand/Modules/USB/EHCI/Makefile b/KernelLand/Modules/USB/EHCI/Makefile
new file mode 100644 (file)
index 0000000..069d030
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Acess2 EHCI Driver
+#
+
+OBJ = ehci.o
+CPPFLAGS = -I../Core/include
+NAME = EHCI
+
+-include ../Makefile.tpl
diff --git a/KernelLand/Modules/USB/EHCI/ehci.c b/KernelLand/Modules/USB/EHCI/ehci.c
new file mode 100644 (file)
index 0000000..87d84b6
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Acess2 EHCI Driver
+ * - By John Hodge (thePowersGang)
+ * 
+ * ehci.c
+ * - Driver Core
+ */
+#define DEBUG  1
+#define VERSION        VER2(0,1)
+#include <acess.h>
+#include <modules.h>
+#include <usb_host.h>
+#include "ehci.h"
+#include <drv_pci.h>
+
+// === CONSTANTS ===
+#define EHCI_MAX_CONTROLLERS   4
+
+// === PROTOTYPES ===
+ int   EHCI_Initialise(char **Arguments);
+ int   EHCI_Cleanup(void);
+ int   EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum);
+void   EHCI_InterruptHandler(int IRQ, void *Ptr);
+// -- API ---
+void   *EHCI_InitInterrupt(void *Ptr, int Endpoint, int bInput, int Period, tUSBHostCb Cb, void *CbData, void *Buf, size_t Length);
+void   *EHCI_InitIsoch  (void *Ptr, int Endpoint);
+void   *EHCI_InitControl(void *Ptr, int Endpoint);
+void   *EHCI_InitBulk   (void *Ptr, int Endpoint);
+void   *EHCI_RemEndpoint(void *Ptr, void *Handle);
+void   *EHCI_SETUP(void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, void *Data, size_t Length);
+void   *EHCI_IN   (void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, void *Data, size_t Length);
+void   *EHCI_OUT  (void *Ptr, void *Dest, tUSBHostCb Cb, void *CbData, void *Data, size_t Length);
+
+// === GLOBALS ===
+MODULE_DEFINE(0, VERSION, USB_EHCI, EHCI_Initialise, NULL, "USB_Core", NULL);
+tEHCI_Controller       gaEHCI_Controllers[EHCI_MAX_CONTROLLERS];
+
+// === CODE ===
+int EHCI_Initialise(char **Arguments)
+{
+       for( int id = -1; (id = PCI_GetDeviceByClass(0x0C0320, 0xFFFFFF, id)) >= 0;  )
+       {
+               Uint32  addr = PCI_GetBAR(id, 0);
+               if( addr == 0 ) {
+                       // Oops, PCI BIOS emulation time
+               }
+               Uint8   irq = PCI_GetIRQ(id);
+               if( irq == 0 ) {
+                       // TODO: The same
+               }
+
+               if( EHCI_InitController(addr, irq) ) {
+                       // TODO: Detect other forms of failure than "out of slots"
+                       break ;
+               }
+       }
+       return 0;
+}
+
+int EHCI_Cleanup(void)
+{
+       return 0;
+}
+
+// --- Driver Init ---
+int EHCI_InitController(tPAddr BaseAddress, Uint8 InterruptNum)
+{
+       tEHCI_Controller        *cont = NULL;
+
+       for( int i = 0; i < EHCI_MAX_CONTROLLERS; i ++ )
+       {
+               if( gaEHCI_Controllers[i].PhysBase == 0 ) {
+                       cont = &gaEHCI_Controllers[i];
+                       cont->PhysBase = BaseAddress;
+                       break;
+               }
+       }
+
+       if(!cont) {
+               return 1;
+       }
+
+       // -- Build up structure --
+       cont->CapRegs = (void*)MM_MapHWPages(BaseAddress, 1);
+       // TODO: Error check
+       cont->OpRegs = (void*)( (Uint32*)cont->CapRegs + cont->CapRegs->CapLength / 4 );
+       // - Allocate periodic queue
+       cont->PeriodicQueue = (void*)MM_AllocDMA(1, 32, NULL);
+       // TODO: Error check
+
+       // -- Bind IRQ --
+       IRQ_AddHandler(InterruptNum, EHCI_InterruptHandler, cont);
+
+       // -- Initialisation procedure (from ehci-r10) --
+       // - Reset controller
+       cont->OpRegs->USBCmd = USBCMD_HCReset;
+       // - Set CTRLDSSEGMENT (TODO: 64-bit support)
+       // - Set USBINTR
+       cont->OpRegs->USBIntr = USBINTR_IOC|USBINTR_PortChange|USBINTR_FrameRollover;
+       // - Set PERIODICLIST BASE
+       cont->OpRegs->PeridocListBase = MM_GetPhysAddr( (tVAddr) cont->PeriodicQueue );
+       // - Enable controller
+       cont->OpRegs->USBCmd = (0x40 << 16) | USBCMD_PeriodicEnable | USBCMD_Run;
+       // - Route all ports
+       cont->OpRegs->ConfigFlag = 1;
+       
+       return 0;
+}
+
+void EHCI_InterruptHandler(int IRQ, void *Ptr)
+{
+
+}
index 431b039..120c2f4 100644 (file)
@@ -8,6 +8,14 @@
 #ifndef _EHCI_H_
 #define _EHCI_H_
 
+typedef struct sEHCI_CapRegs   tEHCI_CapRegs;
+typedef struct sEHCI_OpRegs    tEHCI_OpRegs;
+typedef struct sEHCI_iTD       tEHCI_iTD;
+typedef struct sEHCI_siTD      tEHCI_siTD;
+typedef struct sEHCI_qTD       tEHCI_qTD;
+typedef struct sEHCI_QH        tEHCI_QH;
+typedef struct sEHCI_Controller        tEHCI_Controller;
+
 struct sEHCI_CapRegs
 {
        Uint8   CapLength;      // Byte offset of Operational registers
@@ -152,5 +160,71 @@ struct sEHCI_OpRegs
        Uint32  PortSC[15];
 };
 
+#define USBCMD_Run     0x0001
+#define USBCMD_HCReset 0x0002
+#define USBCMD_PeriodicEnable  0x0010
+#define USBCMD_AsyncEnable     0x0020
+
+#define USBINTR_IOC    0x0001
+#define USBINTR_Error  0x0002
+#define USBINTR_PortChange     0x0004
+#define USBINTR_FrameRollover  0x0008
+#define USBINTR_HostSystemError        0x0010
+#define USBINTR_AsyncAdvance   0x0020
+
+struct sEHCI_iTD
+{
+       Uint32  Link;
+       struct {
+               Uint16  Offset;
+               Uint16  LengthSts;
+       } Transactions[8];
+       // -- 0 --
+       // 0:6  - Device
+       // 7    - Reserved
+       // 8:11 - Endpoint
+       // -- 1 --
+       // 0:10 - Max packet size
+       // 11   - IN/OUT
+       Uint32  BufferPointers[8];      // Page aligned, low 12 bits are overloaded
+};
+
+struct sEHCI_siTD
+{
+       Uint32  Link;
+       Uint32  Dest;
+       Uint32  uFrame;
+       Uint32  StatusLength;
+       Uint32  Page0;
+       Uint32  Page1;
+       Uint32  BackLink;
+};
+
+struct sEHCI_qTD
+{
+       Uint32  Link;
+       Uint32  Link2;  // Used when there's a short packet
+       Uint32  Token;
+       Uint32  Pages[5];       //First has offset in low 12 bits
+};
+
+struct sEHCI_QH
+{
+       Uint32  HLink;  // Horizontal link
+       Uint32  Endpoint;
+       Uint32  EndpointExt;
+       Uint32  CurrentTD;
+       tEHCI_qTD       Overlay;
+};
+
+struct sEHCI_Controller
+{
+       tPAddr  PhysBase;
+       tEHCI_CapRegs   *CapRegs;
+       tEHCI_OpRegs    *OpRegs;
+
+       Uint32  *PeriodicQueue;
+};
+
 #endif
 

UCC git Repository :: git.ucc.asn.au