* Started working on the finisher thread
* Added some TRACE calls in the _InterruptHandler git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23266 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -378,23 +378,31 @@ OHCI::_Interrupt()
|
||||
|
||||
if (status & OHCI_SCHEDULING_OVERRUN) {
|
||||
// TODO
|
||||
TRACE(("usb_ohci: scheduling overrun occured\n"));
|
||||
}
|
||||
|
||||
if (status & OHCI_WRITEBACK_DONE_HEAD) {
|
||||
// TODO
|
||||
TRACE(("usb_ohci: transfer descriptor processed\n"));
|
||||
// Ack it in the finisher thread, not here.
|
||||
result = B_INVOKE_SCHEDULER;
|
||||
finishTransfers = true;
|
||||
}
|
||||
|
||||
if (status & OHCI_RESUME_DETECTED) {
|
||||
// TODO
|
||||
TRACE(("usb_ohci: resume detected\n"));
|
||||
}
|
||||
|
||||
if (status & OHCI_UNRECOVERABLE_ERROR) {
|
||||
// TODO
|
||||
TRACE(("usb_ohci: unrecoverable error. Controller halted\n"));
|
||||
_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
|
||||
// TODO: what else?
|
||||
// Perhaps, clean up all the memory.
|
||||
}
|
||||
|
||||
if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
|
||||
// TODO
|
||||
TRACE(("usb_ohci: root hub status change\n"));
|
||||
}
|
||||
|
||||
release_spinlock(&lock);
|
||||
@@ -420,13 +428,51 @@ OHCI::_FinishTransfer()
|
||||
while (!fStopFinishThread) {
|
||||
if (acquire_sem(fFinishTransfersSem) < B_OK)
|
||||
continue;
|
||||
// We have to acknowledge here after we get the TD list
|
||||
// fHcca->done_head = 0;
|
||||
// Write back WDH bit in the interrupt status register
|
||||
|
||||
// eat up sems that have been released by multiple interrupts
|
||||
int32 semCount = 0;
|
||||
get_sem_count(fFinishTransfersSem, &semCount);
|
||||
if (semCount > 0)
|
||||
acquire_sem_etc(fFinishTransfersSem, semCount, B_RELATIVE_TIMEOUT, 0);
|
||||
|
||||
// Pull out the done list and reverse its order
|
||||
// for both general and isochronous descriptors
|
||||
addr_t done_list = fHcca->done_head & ~OHCI_DONE_INTERRUPTS;
|
||||
addr_t logical = _LogicalAddress(done_list);
|
||||
if (_IsIsochronous(logical)) {
|
||||
ohci_general_td *descriptor = (ohci_general_td *)logical;
|
||||
} else {
|
||||
ohci_isochronous_td *descriptor = (ohci_isochronous_td *)logical;
|
||||
}
|
||||
|
||||
// Acknowledge the interrupt
|
||||
fHcca->done_head = 0;
|
||||
_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_WRITEBACK_DONE_HEAD);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addr_t
|
||||
OHCI::_LogicalAddress(addr_t physical)
|
||||
{
|
||||
// How do I implement it ?
|
||||
// 1 - Hash function like others (*BSD, Linux)
|
||||
// 2 - Adding a method to our slab allocator (
|
||||
// offset from the base are the same for phys and logic)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
OHCI::_IsIsochronous(addr_t logical)
|
||||
{
|
||||
// I have NO IDEA how to implement this.
|
||||
// BSD uses two hash table.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::Start()
|
||||
{
|
||||
@@ -461,6 +507,7 @@ OHCI::Start()
|
||||
status_t
|
||||
OHCI::SubmitTransfer(Transfer *transfer)
|
||||
{
|
||||
// short circuit the root hub
|
||||
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
||||
return fRootHub->ProcessTransfer(this, transfer);
|
||||
|
||||
@@ -522,10 +569,11 @@ OHCI::_SubmitControlRequest(Transfer *transfer)
|
||||
vector.iov_len = sizeof(usb_request_data);
|
||||
_WriteDescriptorChain(setupDescriptor, &vector, 1);
|
||||
|
||||
status_t result;
|
||||
if (transfer->VectorCount() > 0) {
|
||||
ohci_general_td *dataDescriptor = NULL;
|
||||
ohci_general_td *lastDescriptor = NULL;
|
||||
status_t result = _CreateDescriptorChain(&dataDescriptor,
|
||||
result = _CreateDescriptorChain(&dataDescriptor,
|
||||
&lastDescriptor,
|
||||
directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
|
||||
transfer->VectorLength());
|
||||
@@ -556,10 +604,27 @@ OHCI::_SubmitControlRequest(Transfer *transfer)
|
||||
// 3. Tell the controller to process the control list
|
||||
_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
|
||||
|
||||
result = _AddPendingTransfer(transfer, setupDescriptor, statusDescriptor,
|
||||
directionIn);
|
||||
if (result < B_OK) {
|
||||
TRACE_ERROR(("usb_ohci: failed to add pending transfer\n"));
|
||||
_FreeDescriptorChain(setupDescriptor);
|
||||
return result;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::_AddPendingTransfer(Transfer *transfer, ohci_general_td *first,
|
||||
ohci_general_td *last, bool direction)
|
||||
{
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
|
||||
{
|
||||
@@ -583,6 +648,13 @@ OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
OHCI::_FreeDescriptorChain(ohci_general_td *top)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
|
||||
size_t vectorCount)
|
||||
@@ -914,6 +986,20 @@ OHCI::_FreeGeneralDescriptor(ohci_general_td *descriptor)
|
||||
}
|
||||
|
||||
|
||||
ohci_isochronous_td*
|
||||
_CreateIsochronousDescriptor()
|
||||
{
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void _FreeIsochronousDescriptor(ohci_isochronous_td *descriptor)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
OHCI::_InsertEndpointForPipe(Pipe *pipe)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ class OHCIRootHub;
|
||||
|
||||
typedef struct transfer_data_s {
|
||||
Transfer *transfer;
|
||||
ohci_general_td *top;
|
||||
bool incoming;
|
||||
bool canceled;
|
||||
transfer_data_s *link;
|
||||
@@ -80,6 +81,12 @@ private:
|
||||
static int32 _InterruptHandler(void *data);
|
||||
int32 _Interrupt();
|
||||
|
||||
// Transfer functions
|
||||
status_t _AddPendingTransfer(Transfer *transfer,
|
||||
ohci_general_td *first,
|
||||
ohci_general_td *last,
|
||||
bool directionIn);
|
||||
|
||||
static int32 _FinishThread(void *data);
|
||||
void _FinishTransfer();
|
||||
|
||||
@@ -121,6 +128,10 @@ static int32 _FinishThread(void *data);
|
||||
iovec *vector,
|
||||
size_t vectorCount);
|
||||
|
||||
// OHCI needs this function
|
||||
addr_t _LogicalAddress(addr_t physical);
|
||||
bool _IsIsochronous(addr_t logical);
|
||||
|
||||
// Register functions
|
||||
inline void _WriteReg(uint32 reg, uint32 value);
|
||||
inline uint32 _ReadReg(uint32 reg);
|
||||
|
||||
@@ -375,7 +375,7 @@ typedef struct ohci_isochronous_td
|
||||
{
|
||||
uint32 flags;
|
||||
uint32 buffer_page_byte_0; // Physical page number of byte 0
|
||||
uint32 next_descriptor; // Next isochronous transfer descriptor
|
||||
uint32 next_physical_descriptor; // Next isochronous transfer descriptor
|
||||
uint32 last_byte_address; // Physical buffer end
|
||||
uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user