* 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
This commit is contained in:
parent
2b9cc6d877
commit
20bbb1bf28
@ -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)
|
||||
{
|
||||
|
@ -3,8 +3,9 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jan-Rixt Van Hoye
|
||||
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
|
||||
* Jan-Rixt Van Hoye
|
||||
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#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);
|
||||
};
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
* Authors:
|
||||
* Jan-Rixt Van Hoye
|
||||
* Salvatore Benedetto <salvatore.benedetto@gmail.com>
|
||||
* Michael Lotz <mmlr@mlotz.ch>
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
Loading…
Reference in New Issue
Block a user