From: John Hodge Date: Tue, 29 Nov 2011 15:19:43 +0000 (+0800) Subject: Modules/USB - Debugging polling and async X-Git-Tag: rel0.14~54 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=0e361ff8d9472885f770a370c0d477c229041572;p=tpg%2Facess2.git Modules/USB - Debugging polling and async --- diff --git a/Modules/USB/Core/main.c b/Modules/USB/Core/main.c index d92c7729..36a1363b 100644 --- a/Modules/USB/Core/main.c +++ b/Modules/USB/Core/main.c @@ -10,6 +10,10 @@ #include #include "usb.h" +// === IMPORTS === +extern void USB_PollThread(void *unused); +extern void USB_AsyncThread(void *Unused); + // === PROTOTYPES === int USB_Install(char **Arguments); void USB_Cleanup(void); @@ -38,6 +42,10 @@ tUSBHost *gUSB_Hosts = NULL; int USB_Install(char **Arguments) { Log_Warning("USB", "Not Complete - Devel Only"); + + Proc_SpawnWorker(USB_PollThread, NULL); + Proc_SpawnWorker(USB_AsyncThread, NULL); + return MODULE_ERR_OK; } diff --git a/Modules/USB/Core/usb_io.c b/Modules/USB/Core/usb_io.c index 993bf0cc..50320c65 100644 --- a/Modules/USB/Core/usb_io.c +++ b/Modules/USB/Core/usb_io.c @@ -10,7 +10,7 @@ #include #include "usb.h" #include "usb_lowlevel.h" -#include +#include typedef struct sAsyncOp tAsyncOp; @@ -25,9 +25,11 @@ struct sAsyncOp // === PROTOTYPES === void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data); void USB_Request(tUSBInterface *Iface, int Endpoint, int Type, int Req, int Value, int Index, int Len, void *Data); +void USB_AsyncCallback(void *Ptr, void *Buf, int Length); +void USB_AsyncThread(void *unused); // === GLOBALS === -tSemaphore glUSB_AsyncQueue; +tWorkqueue gUSB_AsyncQueue; // === CODE === void USB_ReadDescriptor(tUSBInterface *Iface, int Type, int Index, int Length, void *Data) @@ -65,15 +67,52 @@ void USB_RecvData(tUSBInterface *Dev, int Endpoint, int Length, void *Data) void USB_RecvDataA(tUSBInterface *Dev, int Endpoint, int Length, void *DataBuf, tUSB_DataCallback Callback) { - Log_Warning("USB", "TODO: Implement USB_RecvDataA"); + tAsyncOp *op; + tUSBHost *host; + + ENTER("pDev iEndpoint iLength pDataBuf", Dev, Endpoint, Length, DataBuf); + + op = malloc(sizeof(*op)); + op->Next = NULL; + op->Endpt = &Dev->Endpoints[Endpoint-1]; + op->Length = Length; + op->Data = DataBuf; + + // TODO: Handle transfers that are larger than one packet + + host = Dev->Dev->Host; + LOG("IN from %p %i:%i", host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum); + host->HostDef->SendIN( + host->Ptr, Dev->Dev->Address, op->Endpt->EndpointNum, + 0, USB_AsyncCallback, op, + DataBuf, Length + ); + + LEAVE('-'); + +// Log_Warning("USB", "TODO: Implement USB_RecvDataA"); +} + +void USB_AsyncCallback(void *Ptr, void *Buf, int Length) +{ + tAsyncOp *op = Ptr; + op->Length = Length; + LOG("adding %p to work queue", op); + Workqueue_AddWork(&gUSB_AsyncQueue, op); } void USB_AsyncThread(void *Unused) { for(;;) { - Semaphore_Wait(&glUSB_AsyncQueue, 1); - + tAsyncOp *op = Workqueue_GetWork(&gUSB_AsyncQueue); + tUSBInterface *iface = op->Endpt->Interface; + + LOG("op = %p", op); + + iface->Driver->Endpoints[op->Endpt->EndpointIdx].DataAvail( + iface, op->Endpt->EndpointIdx, + op->Length, op->Data); } } diff --git a/Modules/USB/Core/usb_poll.c b/Modules/USB/Core/usb_poll.c index 92e02922..8fd1b0ce 100644 --- a/Modules/USB/Core/usb_poll.c +++ b/Modules/USB/Core/usb_poll.c @@ -26,7 +26,7 @@ void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint) tUSBEndpoint *endpt; // Some sanity checks - if(Endpoint <= 0 || Endpoint >= Iface->nEndpoints) return ; + if(Endpoint <= 0 || Endpoint > Iface->nEndpoints) return ; endpt = &Iface->Endpoints[Endpoint-1]; if(endpt->PollingPeriod > POLL_MAX || endpt->PollingPeriod <= 0) return ; @@ -39,8 +39,14 @@ void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint) endpt->PollingAtoms = (endpt->PollingPeriod + POLL_ATOM-1) / POLL_ATOM; if(endpt->PollingAtoms > POLL_SLOTS) endpt->PollingAtoms = POLL_SLOTS; // Add to poll queue - endpt->Next = gUSB_PollQueues[endpt->PollingAtoms]; - gUSB_PollQueues[endpt->PollingAtoms] = endpt; + // TODO: Locking + { + int idx = giUSB_PollPosition + 1; + if(idx >= POLL_SLOTS) idx -= POLL_SLOTS; + LOG("idx = %i", idx); + endpt->Next = gUSB_PollQueues[idx]; + gUSB_PollQueues[idx] = endpt; + } } /** @@ -48,6 +54,7 @@ void USB_StartPollingEndpoint(tUSBInterface *Iface, int Endpoint) */ int USB_PollThread(void *unused) { + Threads_SetName("USB Polling Thread"); for(;;) { tUSBEndpoint *ep, *prev; @@ -56,9 +63,11 @@ int USB_PollThread(void *unused) prev = (void*)( (tVAddr)&gUSB_PollQueues[giUSB_PollPosition] - offsetof(tUSBEndpoint, Next) ); // Process queue +// LOG("giUSB_PollPosition = %i", giUSB_PollPosition); for( ep = gUSB_PollQueues[giUSB_PollPosition]; ep; prev = ep, ep = ep->Next ) { int period_in_atoms = ep->PollingAtoms; + LOG("%i: ep = %p", giUSB_PollPosition, ep); // Check for invalid entries if(period_in_atoms < 0 || period_in_atoms > POLL_ATOM) @@ -81,7 +90,7 @@ int USB_PollThread(void *unused) // TODO: Async checking? // - Send the read request on all of them then wait for the first to complete USB_RecvDataA( - ep->Interface, ep->EndpointIdx, + ep->Interface, ep->EndpointIdx+1, ep->MaxPacketSize, ep->InputData, ep->Interface->Driver->Endpoints[ep->EndpointIdx].DataAvail ); diff --git a/Modules/USB/UHCI/uhci.c b/Modules/USB/UHCI/uhci.c index 8df6c287..3c2abd9e 100644 --- a/Modules/USB/UHCI/uhci.c +++ b/Modules/USB/UHCI/uhci.c @@ -4,7 +4,7 @@ * * Universal Host Controller Interface */ -#define DEBUG 0 +#define DEBUG 1 #define VERSION VER2(0,5) #include #include @@ -148,6 +148,8 @@ void UHCI_int_AppendTD(tUHCI_Controller *Cont, tUHCI_TD *TD) // TODO: How to handle FRNUM incrementing while we are in this function? +// LOG("USBINTR = 0x%x", inw(Cont->IOBase + USBINTR)); + // Empty list if( Cont->FrameList[next_frame] & 1 ) { @@ -219,6 +221,7 @@ void *UHCI_int_SendTransaction( // Interrupt on completion if( Cb ) { td->Control |= (1 << 24); + LOG("IOC Cb=%p CbData=%p", Cb, CbData); td->_info.Callback = Cb; // NOTE: if ERRPTR then the TD is kept allocated until checked td->_info.CallbackPtr = CbData; } @@ -343,22 +346,23 @@ void UHCI_CheckPortUpdate(void *Ptr) void UHCI_InterruptHandler(int IRQ, void *Ptr) { tUHCI_Controller *Host = Ptr; + int frame = ((int)inw(Host->IOBase + FRNUM) & 0x3FF) - 1; Uint16 status = inw(Host->IOBase + USBSTS); - Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x", status); + if(frame < 0) frame += 1024; + Log_Debug("UHCI", "UHIC Interrupt, status = 0x%x, frame = %i", status, frame); // Interrupt-on-completion if( status & 1 ) { tPAddr link; - int frame = inw(Host->IOBase + FRNUM) - 1; - if(frame < 0) frame += 1024; - + link = Host->FrameList[frame]; Host->FrameList[frame] = 1; while( !(link & 1) ) { tUHCI_TD *td = UHCI_int_GetTDFromPhys(link); int byte_count = (td->Control&0x7FF)+1; + LOG("link = 0x%x, td = %p, byte_count = %i", link, td, byte_count); // Handle non-page aligned destination // TODO: This will break if the destination is not in global memory if(td->_info.bCopyData) @@ -370,6 +374,7 @@ void UHCI_InterruptHandler(int IRQ, void *Ptr) // Callback if(td->_info.Callback && td->_info.Callback != INVLPTR) { + LOG("Calling cb %p", td->_info.Callback); td->_info.Callback(td->_info.CallbackPtr, td->_info.DataPtr, byte_count); td->_info.Callback = NULL; } @@ -381,5 +386,6 @@ void UHCI_InterruptHandler(int IRQ, void *Ptr) // Host->LastCleanedFrame = frame; } + LOG("status = 0x%02x", status); outw(Host->IOBase + USBSTS, status); }