* 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) {
|
if (status & OHCI_SCHEDULING_OVERRUN) {
|
||||||
// TODO
|
// TODO
|
||||||
|
TRACE(("usb_ohci: scheduling overrun occured\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & OHCI_WRITEBACK_DONE_HEAD) {
|
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;
|
finishTransfers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & OHCI_RESUME_DETECTED) {
|
if (status & OHCI_RESUME_DETECTED) {
|
||||||
// TODO
|
// TODO
|
||||||
|
TRACE(("usb_ohci: resume detected\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status & OHCI_UNRECOVERABLE_ERROR) {
|
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) {
|
if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
|
||||||
// TODO
|
// TODO
|
||||||
|
TRACE(("usb_ohci: root hub status change\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
release_spinlock(&lock);
|
release_spinlock(&lock);
|
||||||
@@ -420,13 +428,51 @@ OHCI::_FinishTransfer()
|
|||||||
while (!fStopFinishThread) {
|
while (!fStopFinishThread) {
|
||||||
if (acquire_sem(fFinishTransfersSem) < B_OK)
|
if (acquire_sem(fFinishTransfersSem) < B_OK)
|
||||||
continue;
|
continue;
|
||||||
// We have to acknowledge here after we get the TD list
|
|
||||||
// fHcca->done_head = 0;
|
// eat up sems that have been released by multiple interrupts
|
||||||
// Write back WDH bit in the interrupt status register
|
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
|
status_t
|
||||||
OHCI::Start()
|
OHCI::Start()
|
||||||
{
|
{
|
||||||
@@ -461,6 +507,7 @@ OHCI::Start()
|
|||||||
status_t
|
status_t
|
||||||
OHCI::SubmitTransfer(Transfer *transfer)
|
OHCI::SubmitTransfer(Transfer *transfer)
|
||||||
{
|
{
|
||||||
|
// short circuit the root hub
|
||||||
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
if (transfer->TransferPipe()->DeviceAddress() == fRootHubAddress)
|
||||||
return fRootHub->ProcessTransfer(this, transfer);
|
return fRootHub->ProcessTransfer(this, transfer);
|
||||||
|
|
||||||
@@ -522,10 +569,11 @@ OHCI::_SubmitControlRequest(Transfer *transfer)
|
|||||||
vector.iov_len = sizeof(usb_request_data);
|
vector.iov_len = sizeof(usb_request_data);
|
||||||
_WriteDescriptorChain(setupDescriptor, &vector, 1);
|
_WriteDescriptorChain(setupDescriptor, &vector, 1);
|
||||||
|
|
||||||
|
status_t result;
|
||||||
if (transfer->VectorCount() > 0) {
|
if (transfer->VectorCount() > 0) {
|
||||||
ohci_general_td *dataDescriptor = NULL;
|
ohci_general_td *dataDescriptor = NULL;
|
||||||
ohci_general_td *lastDescriptor = NULL;
|
ohci_general_td *lastDescriptor = NULL;
|
||||||
status_t result = _CreateDescriptorChain(&dataDescriptor,
|
result = _CreateDescriptorChain(&dataDescriptor,
|
||||||
&lastDescriptor,
|
&lastDescriptor,
|
||||||
directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
|
directionIn ? OHCI_TD_DIRECTION_PID_OUT : OHCI_TD_DIRECTION_PID_IN,
|
||||||
transfer->VectorLength());
|
transfer->VectorLength());
|
||||||
@@ -556,10 +604,27 @@ OHCI::_SubmitControlRequest(Transfer *transfer)
|
|||||||
// 3. Tell the controller to process the control list
|
// 3. Tell the controller to process the control list
|
||||||
_WriteReg(OHCI_COMMAND_STATUS, OHCI_CONTROL_LIST_FILLED);
|
_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;
|
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
|
status_t
|
||||||
OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
|
OHCI::_SubmitIsochronousTransfer(Transfer *transfer)
|
||||||
{
|
{
|
||||||
@@ -583,6 +648,13 @@ OHCI::_CreateDescriptorChain(ohci_general_td **_firstDescriptor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
OHCI::_FreeDescriptorChain(ohci_general_td *top)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
|
OHCI::_WriteDescriptorChain(ohci_general_td *topDescriptor, iovec *vector,
|
||||||
size_t vectorCount)
|
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
|
status_t
|
||||||
OHCI::_InsertEndpointForPipe(Pipe *pipe)
|
OHCI::_InsertEndpointForPipe(Pipe *pipe)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class OHCIRootHub;
|
|||||||
|
|
||||||
typedef struct transfer_data_s {
|
typedef struct transfer_data_s {
|
||||||
Transfer *transfer;
|
Transfer *transfer;
|
||||||
|
ohci_general_td *top;
|
||||||
bool incoming;
|
bool incoming;
|
||||||
bool canceled;
|
bool canceled;
|
||||||
transfer_data_s *link;
|
transfer_data_s *link;
|
||||||
@@ -80,6 +81,12 @@ private:
|
|||||||
static int32 _InterruptHandler(void *data);
|
static int32 _InterruptHandler(void *data);
|
||||||
int32 _Interrupt();
|
int32 _Interrupt();
|
||||||
|
|
||||||
|
// Transfer functions
|
||||||
|
status_t _AddPendingTransfer(Transfer *transfer,
|
||||||
|
ohci_general_td *first,
|
||||||
|
ohci_general_td *last,
|
||||||
|
bool directionIn);
|
||||||
|
|
||||||
static int32 _FinishThread(void *data);
|
static int32 _FinishThread(void *data);
|
||||||
void _FinishTransfer();
|
void _FinishTransfer();
|
||||||
|
|
||||||
@@ -121,6 +128,10 @@ static int32 _FinishThread(void *data);
|
|||||||
iovec *vector,
|
iovec *vector,
|
||||||
size_t vectorCount);
|
size_t vectorCount);
|
||||||
|
|
||||||
|
// OHCI needs this function
|
||||||
|
addr_t _LogicalAddress(addr_t physical);
|
||||||
|
bool _IsIsochronous(addr_t logical);
|
||||||
|
|
||||||
// Register functions
|
// Register functions
|
||||||
inline void _WriteReg(uint32 reg, uint32 value);
|
inline void _WriteReg(uint32 reg, uint32 value);
|
||||||
inline uint32 _ReadReg(uint32 reg);
|
inline uint32 _ReadReg(uint32 reg);
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ typedef struct ohci_isochronous_td
|
|||||||
{
|
{
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint32 buffer_page_byte_0; // Physical page number of byte 0
|
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
|
uint32 last_byte_address; // Physical buffer end
|
||||||
uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
|
uint16 offset[OHCI_ITD_NOFFSET]; // Buffer offsets
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user