From: John Hodge Date: Mon, 16 Jul 2012 05:33:38 +0000 (+0800) Subject: Modules/EHCI - Planning out, might need USB HC API changes X-Git-Tag: rel0.15~706^2~70^2~5 X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=bd1e8e83753ed047a4a6b561e3049b2414e8205f Modules/EHCI - Planning out, might need USB HC API changes --- diff --git a/KernelLand/Modules/USB/EHCI/Makefile b/KernelLand/Modules/USB/EHCI/Makefile new file mode 100644 index 00000000..069d0302 --- /dev/null +++ b/KernelLand/Modules/USB/EHCI/Makefile @@ -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 index 00000000..87d84b69 --- /dev/null +++ b/KernelLand/Modules/USB/EHCI/ehci.c @@ -0,0 +1,113 @@ +/* + * Acess2 EHCI Driver + * - By John Hodge (thePowersGang) + * + * ehci.c + * - Driver Core + */ +#define DEBUG 1 +#define VERSION VER2(0,1) +#include +#include +#include +#include "ehci.h" +#include + +// === 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) +{ + +} diff --git a/KernelLand/Modules/USB/EHCI/ehci.h b/KernelLand/Modules/USB/EHCI/ehci.h index 431b0391..120c2f43 100644 --- a/KernelLand/Modules/USB/EHCI/ehci.h +++ b/KernelLand/Modules/USB/EHCI/ehci.h @@ -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