* Partially implemented interrupt handler routine

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23175 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Salvatore Benedetto
2007-12-27 22:26:29 +00:00
parent 4016bc0e47
commit e78f31ebbe
+63 -2
View File
@@ -346,10 +346,62 @@ OHCI::_Interrupt()
static spinlock lock = 0; static spinlock lock = 0;
acquire_spinlock(&lock); acquire_spinlock(&lock);
int32 result = B_UNHANDLED_INTERRUPT; uint32 status = 0;
uint32 acknowledge = 0;
bool finishTransfers = false;
int32 result = B_HANDLED_INTERRUPT;
// The LSb of done_head is used to inform the HCD that an interrupt
// condition exists for both the done list and for another event recorded in
// the HcInterruptStatus register. If done_head is 0, then the interrupt
// was caused by other than the HccaDoneHead update and the
// HcInterruptStatus register needs to be accessed to determine that exact
// interrupt cause. If HccDoneHead is nonzero, then a done list update
// interrupt is indicated and if the LSb of the Dword is nonzero, then an
// additional interrupt event is indicated and HcInterruptStatus shuold be
// checked to determine its cause.
uint32 doneHead = fHcca->done_head;
if (doneHead != 0) {
status = OHCI_WRITEBACK_DONE_HEAD;
if (doneHead & OHCI_DONE_INTERRUPTS)
status |= _ReadReg(OHCI_INTERRUPT_STATUS)
& _ReadReg(OHCI_INTERRUPT_ENABLE);
} else {
status = _ReadReg(OHCI_INTERRUPT_STATUS) & _ReadReg(OHCI_INTERRUPT_ENABLE)
& ~OHCI_WRITEBACK_DONE_HEAD;
if (status == 0) {
// Nothing to be done (PCI shared interrupt)
release_spinlock(&lock);
return B_UNHANDLED_INTERRUPT;
}
}
if (status & OHCI_SCHEDULING_OVERRUN) {
// TODO
}
if (status & OHCI_WRITEBACK_DONE_HEAD) {
// TODO
finishTransfers = true;
}
if (status & OHCI_RESUME_DETECTED) {
// TODO
}
if (status & OHCI_UNRECOVERABLE_ERROR) {
// TODO
}
if (status & OHCI_ROOT_HUB_STATUS_CHANGE) {
// TODO
}
release_spinlock(&lock); release_spinlock(&lock);
if (finishTransfers)
release_sem_etc(fFinishTransfersSem, 1, B_DO_NOT_RESCHEDULE);
return result; return result;
} }
@@ -368,6 +420,9 @@ 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;
// Write back WDH bit in the interrupt status register
} }
} }
@@ -491,9 +546,14 @@ OHCI::_SubmitControlRequest(Transfer *transfer)
_LinkDescriptors(setupDescriptor, statusDescriptor); _LinkDescriptors(setupDescriptor, statusDescriptor);
} }
// TODO
// 1. Insert the chain descriptors to the endpoint // 1. Insert the chain descriptors to the endpoint
ohci_endpoint_descriptor *endpoint
= (ohci_endpoint_descriptor *)transfer->TransferPipe()->ControllerCookie();
endpoint->tail_physical_descriptor = statusDescriptor->physical_address;
endpoint->head_physical_descriptor = setupDescriptor->physical_address;
// 2. Clear the Skip bit in the enpoint // 2. Clear the Skip bit in the enpoint
endpoint->flags &= ~OHCI_ENDPOINT_SKIP;
// 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);
return B_OK; return B_OK;
@@ -934,6 +994,7 @@ OHCI::_InsertEndpointForPipe(Pipe *pipe)
} }
Lock(); Lock();
pipe->SetControllerCookie((void *)endpoint);
endpoint->next_logical_endpoint = head->next_logical_endpoint; endpoint->next_logical_endpoint = head->next_logical_endpoint;
endpoint->next_physical_endpoint = head->next_physical_endpoint; endpoint->next_physical_endpoint = head->next_physical_endpoint;
head->next_logical_endpoint = (void *)endpoint; head->next_logical_endpoint = (void *)endpoint;