* 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:
Salvatore Benedetto
2008-01-06 14:34:22 +00:00
parent 4accd841c7
commit d98bdb30bc
3 changed files with 104 additions and 7 deletions
+92 -6
View File
@@ -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)
{
+11
View File
@@ -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
};