From 20bbb1bf28b5ccd3fcda07e27f0dd24c62fbe71d Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Sun, 18 May 2008 09:23:29 +0000 Subject: [PATCH] * Make the operational register memory a uint8 * instead of a uint32 * so the driver has at least a chance of working (it previously always used wrong offsets for register access). * Remove the hash approach for now (I'm going to explore a few other ways of doing that first). * Reorder some stuff and check for errors in some more places. * More cleanup (mostly whitespace again). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25538 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/busses/usb/ohci.cpp | 115 +++++------------- src/add-ons/kernel/busses/usb/ohci.h | 76 ++---------- src/add-ons/kernel/busses/usb/ohci_hardware.h | 22 ++-- 3 files changed, 52 insertions(+), 161 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp index 2b2bc778ce..2de28decc9 100644 --- a/src/add-ons/kernel/busses/usb/ohci.cpp +++ b/src/add-ons/kernel/busses/usb/ohci.cpp @@ -77,8 +77,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) fFinishTransfersSem(-1), fFinishThread(-1), fStopFinishThread(false), - fHashGenericTable(NULL), - fHashIsochronousTable(NULL), fRootHub(NULL), fRootHubAddress(0), fPortCount(0) @@ -138,35 +136,17 @@ OHCI::OHCI(pci_info *info, Stack *stack) memset(fHcca, 0, sizeof(ohci_hcca)); - // Allocate hash tables - fHashGenericTable = (ohci_general_td **) - malloc(sizeof(ohci_general_td *) * OHCI_HASH_SIZE); - if (fHashGenericTable == NULL) { - TRACE_ERROR(("usb_ohci: unable to allocate hash generic table\n")); - return; - } - - fHashIsochronousTable = (ohci_isochronous_td **) - malloc(sizeof(ohci_isochronous_td *) * OHCI_HASH_SIZE); - if (fHashIsochronousTable == NULL) { - free(fHashGenericTable); - TRACE_ERROR(("usb_ohci: unable to allocate hash isochronous table\n")); - return; - } - // Set Up Host controller // Dummy endpoints fDummyControl = _AllocateEndpoint(); if (!fDummyControl) return; - fDummyControl->flags |= OHCI_ENDPOINT_SKIP; fDummyBulk = _AllocateEndpoint(); if (!fDummyBulk) { _FreeEndpoint(fDummyControl); return; } - fDummyBulk->flags |= OHCI_ENDPOINT_SKIP; fDummyIsochronous = _AllocateEndpoint(); if (!fDummyIsochronous) { @@ -174,7 +154,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) _FreeEndpoint(fDummyBulk); return; } - fDummyIsochronous->flags |= OHCI_ENDPOINT_SKIP; // Static endpoints that get linked in the HCCA fInterruptEndpoints = new(std::nothrow) @@ -202,7 +181,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) } // Make them point all to the dummy isochronous endpoint - fInterruptEndpoints[i]->flags |= OHCI_ENDPOINT_SKIP; fInterruptEndpoints[i]->next_physical_endpoint = fDummyIsochronous->physical_address; } @@ -341,9 +319,6 @@ OHCI::~OHCI() if (fRegisterArea >= B_OK) delete_area(fRegisterArea); - free(fHashGenericTable); - free(fHashIsochronousTable); - _FreeEndpoint(fDummyControl); _FreeEndpoint(fDummyBulk); _FreeEndpoint(fDummyIsochronous); @@ -365,9 +340,11 @@ OHCI::Start() { TRACE(("usb_ohci: starting OHCI Host Controller\n")); - if ((_ReadReg(OHCI_CONTROL) & OHCI_HC_FUNCTIONAL_STATE_MASK) + uint32 control = _ReadReg(OHCI_CONTROL); + if ((control & OHCI_HC_FUNCTIONAL_STATE_MASK) != OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL) { - TRACE_ERROR(("usb_ohci: Controller not started!\n")); + TRACE_ERROR(("usb_ohci: Controller not started (0x%08lx)!\n", + control)); return B_ERROR; } else TRACE(("usb_ohci: Controller is operational!\n")); @@ -578,7 +555,7 @@ OHCI::AddTo(Stack *stack) status_t OHCI::GetPortStatus(uint8 index, usb_port_status *status) { - TRACE(("usb_ohci::%s(%ud, )\n", __FUNCTION__, index)); + TRACE(("usb_ohci: get port status %ud\n", index)); if (index >= fPortCount) return B_BAD_INDEX; @@ -857,7 +834,7 @@ OHCI::_FinishTransfers() ohci_isochronous_td *isoCurrent = NULL; ohci_isochronous_td *isoTop = NULL; while (doneList != 0) { - current = _FindDescriptorInHash(doneList); + current = NULL; //_FindDescriptorInHash(doneList); if (current != NULL) { doneList = current->next_physical_descriptor; current->next_done_descriptor = (void *)top; @@ -865,7 +842,7 @@ OHCI::_FinishTransfers() continue; } - isoCurrent = _FindIsoDescriptorInHash(doneList); + isoCurrent = NULL; //_FindIsoDescriptorInHash(doneList); if (isoCurrent != NULL) { doneList = isoCurrent->next_physical_descriptor; isoCurrent->next_done_descriptor = (void *)isoTop; @@ -1135,11 +1112,14 @@ OHCI::_AllocateEndpoint() return NULL; } + endpoint->flags = OHCI_ENDPOINT_SKIP; endpoint->physical_address = (addr_t)physicalAddress; endpoint->head_logical_descriptor = NULL; endpoint->head_physical_descriptor = 0; endpoint->tail_logical_descriptor = NULL; endpoint->tail_physical_descriptor = 0; + endpoint->next_logical_endpoint = NULL; + endpoint->next_physical_endpoint = 0; return endpoint; } @@ -1214,27 +1194,32 @@ OHCI::_InsertEndpointForPipe(Pipe *pipe) endpoint->flags = flags; // Add the endpoint to the appropriate list - ohci_endpoint_descriptor *head = NULL; uint32 type = pipe->Type(); + ohci_endpoint_descriptor *head = NULL; if (type & USB_OBJECT_CONTROL_PIPE) head = fDummyControl; else if (type & USB_OBJECT_BULK_PIPE) head = fDummyBulk; else if (type & USB_OBJECT_INTERRUPT_PIPE) head = _FindInterruptEndpoint(pipe->Interval()); - else if (type & USB_OBJECT_ISO_PIPE) { - // Set the isochronous bit format - endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; + else if (type & USB_OBJECT_ISO_PIPE) head = fDummyIsochronous; - } else { + else TRACE_ERROR(("usb_ohci: unknown pipe type\n")); + + if (head == NULL) { + TRACE_ERROR(("usb_ohci: no list found for endpoint\n")); _FreeEndpoint(endpoint); - return B_BAD_VALUE; + return B_ERROR; } // Create (necessary) dummy descriptor if (pipe->Type() & USB_OBJECT_ISO_PIPE) { + // Set the isochronous bit format + endpoint->flags |= OHCI_ENDPOINT_ISOCHRONOUS_FORMAT; // TODO + _FreeEndpoint(endpoint); + return B_ERROR; } else { ohci_general_td *dummy = _CreateGeneralDescriptor(0); dummy->next_logical_descriptor = NULL; @@ -1245,15 +1230,23 @@ OHCI::_InsertEndpointForPipe(Pipe *pipe) endpoint->tail_physical_descriptor = dummy->physical_address; } - // TODO: Change lock lo LockEndpoint() - Lock(); + if (!Lock()) { + if (endpoint->head_logical_descriptor) { + _FreeGeneralDescriptor( + (ohci_general_td *)endpoint->head_logical_descriptor); + } + + _FreeEndpoint(endpoint); + return B_ERROR; + } + pipe->SetControllerCookie((void *)endpoint); endpoint->next_logical_endpoint = head->next_logical_endpoint; endpoint->next_physical_endpoint = head->next_physical_endpoint; head->next_logical_endpoint = (void *)endpoint; head->next_physical_endpoint = (uint32)endpoint->physical_address; - Unlock(); + Unlock(); return B_OK; } @@ -1422,50 +1415,6 @@ OHCI::_FreeIsochronousDescriptor(ohci_isochronous_td *descriptor) } -void -OHCI::_AddDescriptorToHash(ohci_general_td *descriptor) -{ - // TODO -} - - -void -OHCI::_RemoveDescriptorFromHash(ohci_general_td *descriptor) -{ - // TODO -} - - -ohci_general_td* -OHCI::_FindDescriptorInHash(uint32 physicalAddress) -{ - // TODO - return NULL; -} - - -void -OHCI::_AddIsoDescriptorToHash(ohci_isochronous_td *descriptor) -{ - // TODO -} - - -void -OHCI::_RemoveIsoDescriptorFromHash(ohci_isochronous_td *descriptor) -{ - // TODO -} - - -ohci_isochronous_td* -OHCI::_FindIsoDescriptorInHash(uint32 physicalAddress) -{ - // TODO - return NULL; -} - - inline void OHCI::_WriteReg(uint32 reg, uint32 value) { diff --git a/src/add-ons/kernel/busses/usb/ohci.h b/src/add-ons/kernel/busses/usb/ohci.h index fd9c265375..b3c9790e3b 100644 --- a/src/add-ons/kernel/busses/usb/ohci.h +++ b/src/add-ons/kernel/busses/usb/ohci.h @@ -3,8 +3,9 @@ * Distributed under the terms of the MIT License. * * Authors: - * Jan-Rixt Van Hoye - * Salvatore Benedetto + * Jan-Rixt Van Hoye + * Salvatore Benedetto + * Michael Lotz */ #ifndef OHCI_H @@ -28,49 +29,14 @@ typedef struct transfer_data_s { transfer_data_s *link; } transfer_data; -// -------------------------------------- -// OHCI:: Software isonchronous -// transfer descriptor -// -------------------------------------- -typedef struct hcd_soft_itransfer -{ - ohci_isochronous_td itd; - struct hcd_soft_itransfer *nextitd; // mirrors nexttd in ITD - struct hcd_soft_itransfer *dnext; // next in done list - addr_t physaddr; // physical address to the host controller isonchronous transfer - //LIST_ENTRY(hcd_soft_itransfer) hnext; - uint16 flags; // flags -#ifdef DIAGNOSTIC - char isdone; // is the transfer done? -#endif -}hcd_soft_itransfer; -#define OHCI_SITD_SIZE ((sizeof (struct hcd_soft_itransfer) + OHCI_ITD_ALIGN - 1) / OHCI_ITD_ALIGN * OHCI_ITD_ALIGN) -#define OHCI_SITD_CHUNK 64 - -#define OHCI_NUMBER_OF_ENDPOINTS (2 * OHCI_NUMBER_OF_INTERRUPTS - 1) - -// Note: the controller returns only the physical -// address of the first processed descriptor of -// an heterogeneous list (isochronous + generic). Unfortunately -// we don't have a way to know whether the descriptor is -// generic or isochronous, either way to translate the address back to -// kernel address. The physical address is used as the hash value. -// (Kindly borrowed from *BSD) - -#define OHCI_HASH_SIZE 128 -#define HASH(x) (((x) >> 4) % OHCI_HASH_SIZE) - - -class OHCI : public BusManager -{ +class OHCI : public BusManager { public: - OHCI(pci_info *info, Stack *stack); ~OHCI(); status_t Start(); -virtual status_t SubmitTransfer(Transfer *transfer); +virtual status_t SubmitTransfer(Transfer *transfer); virtual status_t CancelQueuedTransfers(Pipe *pipe, bool force); @@ -80,8 +46,8 @@ virtual status_t NotifyPipeChange(Pipe *pipe, static status_t AddTo(Stack *stack); // Port operations - uint8 PortCount() { return fPortCount; }; - status_t GetPortStatus(uint8 index, + uint8 PortCount() { return fPortCount; }; + status_t GetPortStatus(uint8 index, usb_port_status *status); status_t SetPortFeature(uint8 index, uint16 feature); status_t ClearPortFeature(uint8 index, uint16 feature); @@ -152,31 +118,15 @@ static int32 _FinishThread(void *data); void _FreeIsochronousDescriptor( ohci_isochronous_td *descriptor); - // Hash tables related methods - void _AddDescriptorToHash( - ohci_general_td *descriptor); - void _RemoveDescriptorFromHash( - ohci_general_td *descriptor); - ohci_general_td *_FindDescriptorInHash( - uint32 physicalAddress); - - void _AddIsoDescriptorToHash( - ohci_isochronous_td *descriptor); - void _RemoveIsoDescriptorFromHash( - ohci_isochronous_td *descriptor); - ohci_isochronous_td *_FindIsoDescriptorInHash( - uint32 physicalAddress); - - // Register functions inline void _WriteReg(uint32 reg, uint32 value); inline uint32 _ReadReg(uint32 reg); static pci_module_info *sPCIModule; - pci_info *fPCIInfo; + pci_info *fPCIInfo; Stack *fStack; - uint32 *fOperationalRegisters; + uint8 *fOperationalRegisters; area_id fRegisterArea; // Host Controller Communication Area related stuff @@ -196,12 +146,8 @@ static pci_module_info *sPCIModule; thread_id fFinishThread; bool fStopFinishThread; - // Hash table - ohci_general_td **fHashGenericTable; - ohci_isochronous_td **fHashIsochronousTable; - // Root Hub - OHCIRootHub *fRootHub; + OHCIRootHub *fRootHub; uint8 fRootHubAddress; // Port management @@ -214,7 +160,7 @@ public: OHCIRootHub(Object *rootObject, int8 deviceAddress); -static status_t ProcessTransfer(OHCI *ohci, +static status_t ProcessTransfer(OHCI *ohci, Transfer *transfer); }; diff --git a/src/add-ons/kernel/busses/usb/ohci_hardware.h b/src/add-ons/kernel/busses/usb/ohci_hardware.h index 936a58c8b3..b7b2154f56 100644 --- a/src/add-ons/kernel/busses/usb/ohci_hardware.h +++ b/src/add-ons/kernel/busses/usb/ohci_hardware.h @@ -5,6 +5,7 @@ * Authors: * Jan-Rixt Van Hoye * Salvatore Benedetto + * Michael Lotz */ #ifndef OHCI_HARDWARE_H @@ -271,15 +272,14 @@ #define OHCI_NUMBER_OF_INTERRUPTS 32 -typedef struct ohci_hcca -{ +typedef struct { uint32 interrupt_table[OHCI_NUMBER_OF_INTERRUPTS]; uint32 current_frame_number; uint32 done_head; // The following is 120 instead of 116 because the spec // only specifies 252 bytes uint8 reserved_for_hc[120]; -}; +} ohci_hcca; #define OHCI_DONE_INTERRUPTS 1 #define OHCI_HCCA_SIZE 256 @@ -292,20 +292,18 @@ typedef struct ohci_hcca // Endpoint descriptor structure (section 4.2) // -------------------------------- -typedef struct ohci_endpoint_descriptor -{ +typedef struct { // Hardware part uint32 flags; // Flags field uint32 tail_physical_descriptor; // Queue tail physical pointer uint32 head_physical_descriptor; // Queue head physical pointer uint32 next_physical_endpoint; // Physical pointer to the next endpoint // Software part - // TODO: What about type, state and interval (only interrupts) ? addr_t physical_address; // Physical pointer to this address void *tail_logical_descriptor; // Queue tail logical pointer void *head_logical_descriptor; // Queue head logical pointer void *next_logical_endpoint; // Logical pointer to the next endpoint -}; +} ohci_endpoint_descriptor; #define OHCI_ENDPOINT_ADDRESS_MASK 0x0000007f #define OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s) ((s) & 0x7f) @@ -333,8 +331,7 @@ typedef struct ohci_endpoint_descriptor // General transfer descriptor structure (section 4.3.1) // -------------------------------- -typedef struct ohci_general_td -{ +typedef struct { // Hardware part 16 bytes uint32 flags; // Flags field uint32 buffer_physical; // Physical buffer pointer @@ -348,7 +345,7 @@ typedef struct ohci_general_td size_t buffer_size; // Size of the buffer void *transfer; // Pointer to the transfer_data bool is_last; // Last descriptor of the transfer -}; +} ohci_general_td; #define OHCI_BUFFER_ROUNDING 0x00040000 #define OHCI_TD_DIRECTION_PID_MASK 0x00180000 @@ -374,8 +371,7 @@ typedef struct ohci_general_td // -------------------------------- #define OHCI_ITD_NOFFSET 8 -typedef struct ohci_isochronous_td -{ +typedef struct { // Hardware part 32 byte uint32 flags; uint32 buffer_page_byte_0; // Physical page number of byte 0 @@ -386,7 +382,7 @@ typedef struct ohci_isochronous_td addr_t physical_address; // Physical address of this descriptor void *next_logical_descriptor; // Logical pointer next descriptor void *next_done_descriptor; // Used for collision in the hash table -}; +} ohci_isochronous_td; #define OHCI_ITD_GET_STARTING_FRAME(x) ((x) & 0x0000ffff) #define OHCI_ITD_SET_STARTING_FRAME(x) ((x) & 0xffff)