X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FUSB%2FCore%2Fuhci.c;h=f50324fa8a0ac0958b3d7d93cf394f8b348820da;hb=6844966136c3cc3c7e93a2b69977780e84ff65db;hp=948f6e643216265253cf6528a7e40416c194ce3e;hpb=4ac38b7ae3d361dc2456b866bdd1effb0dfa6ca0;p=tpg%2Facess2.git diff --git a/Modules/USB/Core/uhci.c b/Modules/USB/Core/uhci.c index 948f6e64..f50324fa 100644 --- a/Modules/USB/Core/uhci.c +++ b/Modules/USB/Core/uhci.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "usb.h" #include "uhci.h" @@ -16,20 +17,30 @@ // === PROTOTYPES === int UHCI_Initialise(); void UHCI_Cleanup(); - int UHCI_IOCtl(tVFS_Node *node, int id, void *data); +tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont); +void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD); +void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length); +void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length); +void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length); +void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length); int UHCI_Int_InitHost(tUHCI_Controller *Host); +void UHCI_InterruptHandler(int IRQ, void *Ptr); // === GLOBALS === -//Uint gaFrameList[1024]; tUHCI_TD gaUHCI_TDPool[NUM_TDs]; tUHCI_Controller gUHCI_Controllers[MAX_CONTROLLERS]; +tUSBHost gUHCI_HostDef = { + .SendIN = UHCI_DataIN, + .SendOUT = UHCI_DataOUT, + .SendSETUP = UHCI_SendSetup, + }; // === CODE === /** * \fn int UHCI_Initialise() * \brief Called to initialise the UHCI Driver */ -int UHCI_Initialise() +int UHCI_Initialise(const char **Arguments) { int i=0, id=-1; int ret; @@ -39,16 +50,23 @@ int UHCI_Initialise() // Enumerate PCI Bus, getting a maximum of `MAX_CONTROLLERS` devices while( (id = PCI_GetDeviceByClass(0x0C03, 0xFFFF, id)) >= 0 && i < MAX_CONTROLLERS ) { + tUHCI_Controller *cinfo = &gUHCI_Controllers[i]; // NOTE: Check "protocol" from PCI? - gUHCI_Controllers[i].PciId = id; + cinfo->PciId = id; // Assign a port range (BAR4, Reserve 32 ports) - gUHCI_Controllers[i].IOBase = PCI_GetBAR(id, 4); - gUHCI_Controllers[i].IRQNum = PCI_GetIRQ(id); + cinfo->IOBase = PCI_GetBAR(id, 4); + if( !(cinfo->IOBase & 1) ) { + Log_Warning("UHCI", "MMIO is not supported"); + continue ; + } + cinfo->IRQNum = PCI_GetIRQ(id); - Log("[USB ] Controller PCI #%i: IO Base = 0x%x, IRQ %i", - id, gUHCI_Controllers[i].IOBase, gUHCI_Controllers[i].IRQNum); + Log_Debug("UHCI", "Controller PCI #%i: IO Base = 0x%x, IRQ %i", + id, cinfo->IOBase, cinfo->IRQNum); + IRQ_AddHandler(cinfo->IRQNum, UHCI_InterruptHandler, cinfo); + // Initialise Host ret = UHCI_Int_InitHost(&gUHCI_Controllers[i]); // Detect an error @@ -57,13 +75,15 @@ int UHCI_Initialise() return ret; } + USB_RegisterHost(&gUHCI_HostDef, cinfo); + i ++; } if(i == MAX_CONTROLLERS) { Log_Warning("UHCI", "Over "EXPAND_STR(MAX_CONTROLLERS)" UHCI controllers detected, ignoring rest"); } - LEAVE('i', i); - return i; + LEAVE('i', MODULE_ERR_OK); + return MODULE_ERR_OK; } /** @@ -74,13 +94,78 @@ void UHCI_Cleanup() { } +tUHCI_TD *UHCI_int_AllocateTD(tUHCI_Controller *Cont) +{ + int i; + for(i = 0; i < NUM_TDs; i ++) + { + if(gaUHCI_TDPool[i].Link == 0) { + gaUHCI_TDPool[i].Link = 1; + return &gaUHCI_TDPool[i]; + } + } + return NULL; +} + +void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) +{ + Log_Warning("UHCI", "TODO: Implement AppendTD"); +} + /** - * \brief Sends a packet to a device endpoint + * \brief Send a transaction to the USB bus + * \param Cont Controller pointer + * \param Addr Function Address * 16 + Endpoint + * \param bTgl Data toggle value */ -int UHCI_SendPacket(int ControllerId, int Length) +void *UHCI_int_SendTransaction(tUHCI_Controller *Cont, int Addr, Uint8 Type, int bTgl, int bIOC, void *Data, size_t Length) { - //tUHCI_TD *td = UHCI_AllocateTD(); - return 0; + tUHCI_TD *td; + + if( Length > 0x400 ) return NULL; // Controller allows up to 0x500, but USB doesn't + + td = UHCI_int_AllocateTD(Cont); + + td->Link = 1; + td->Control = (Length - 1) & 0x7FF; + td->Token = ((Length - 1) & 0x7FF) << 21; + td->Token |= (bTgl & 1) << 19; + td->Token |= (Addr & 0xF) << 15; + td->Token |= ((Addr/16) & 0xFF) << 8; + td->Token |= Type; + + // TODO: Ensure 32-bit paddr + if( ((tVAddr)Data & PAGE_SIZE) + Length > PAGE_SIZE ) { + Log_Warning("UHCI", "TODO: Support non single page transfers"); +// td->BufferPointer = + return NULL; + } + else { + td->BufferPointer = MM_GetPhysAddr( (tVAddr)Data ); + } + + if( bIOC ) { +// td->Control + } + + UHCI_int_AppendTD(Cont, td); + + return td; +} + +void *UHCI_DataIN(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length) +{ + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x69, DataTgl, bIOC, Data, Length); +} + +void *UHCI_DataOUT(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length) +{ + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0xE1, DataTgl, bIOC, Data, Length); +} + +void *UHCI_SendSetup(void *Ptr, int Fcn, int Endpt, int DataTgl, int bIOC, void *Data, size_t Length) +{ + return UHCI_int_SendTransaction(Ptr, Fcn*16+Endpt, 0x2D, DataTgl, bIOC, Data, Length); } // === INTERNAL FUNCTIONS === @@ -92,13 +177,16 @@ int UHCI_SendPacket(int ControllerId, int Length) int UHCI_Int_InitHost(tUHCI_Controller *Host) { ENTER("pHost", Host); - + outw( Host->IOBase + USBCMD, 4 ); // GRESET + Time_Delay(10); // TODO: Wait for at least 10ms outw( Host->IOBase + USBCMD, 0 ); // GRESET // Allocate Frame List - Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList); // 1 Page, 32-bit + // - 1 Page, 32-bit address + // - 1 page = 1024 4 byte entries + Host->FrameList = (void *) MM_AllocDMA(1, 32, &Host->PhysFrameList); if( !Host->FrameList ) { Log_Warning("UHCI", "Unable to allocate frame list, aborting"); LEAVE('i', -1); @@ -112,15 +200,51 @@ int UHCI_Int_InitHost(tUHCI_Controller *Host) // Set frame length to 1 ms outb( Host->IOBase + SOFMOD, 64 ); - // Set Frame List Address + // Set Frame List outd( Host->IOBase + FLBASEADD, Host->PhysFrameList ); - - // Set Frame Number outw( Host->IOBase + FRNUM, 0 ); // Enable Interrupts - //PCI_WriteWord( Host->PciId, 0xC0, 0x2000 ); - + outw( Host->IOBase + USBINTR, 0x000F ); + PCI_ConfigWrite( Host->PciId, 0xC0, 2, 0x2000 ); + + outw( Host->IOBase + USBCMD, 0x0001 ); + LEAVE('i', 0); return 0; } + +void UHCI_CheckPortUpdate(tUHCI_Controller *Host) +{ + // Enable ports + for( int i = 0; i < 2; i ++ ) + { + int port = Host->IOBase + PORTSC1 + i*2; + // Check for port change + if( !(inw(port) & 0x0002) ) continue; + outw(port, 0x0002); + + // Check if the port is connected + if( !(inw(port) & 1) ) + { + // TODO: Tell the USB code it's gone? + continue; + } + else + { + LOG("Port %i has something", i); + // Reset port (set bit 9) + outw( port, 0x0100 ); + Time_Delay(50); // 50ms delay + outw( port, inw(port) & ~0x0100 ); + // Enable port + Time_Delay(50); // 50ms delay + outw( port, inw(port) & 0x0004 ); + } + } +} + +void UHCI_InterruptHandler(int IRQ, void *Ptr) +{ + Log_Debug("UHCI", "UHIC Interrupt"); +}