--- /dev/null
+/*
+ * 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)
+{
+
+}
#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
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