added Interrupt handling framework

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22145 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2007-09-01 19:54:45 +00:00
parent 3d41648479
commit 4f733fe93b
4 changed files with 54 additions and 6 deletions

View File

@ -24,6 +24,7 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
, fCommandSlotCount(0)
, fPortCount(0)
, fPortMax(0)
, fIRQ(0)
, fInstanceCheck(-1)
{
memset(fPorts, 0, sizeof(fPorts));
@ -100,6 +101,12 @@ AHCIController::Init()
while ((fRegs->pi & (1 << fPortMax)) == 0)
fPortMax--;
fIRQ = gPCI->read_pci_config(fPCIDevice, PCI_interrupt_line, 1);
if (fIRQ == 0 || fIRQ == 0xff) {
TRACE("no IRQ assigned\n");
goto err;
}
TRACE("cap: Interface Speed Support: generation %lu\n", (fRegs->cap >> CAP_ISS_SHIFT) & CAP_ISS_MASK);
TRACE("cap: Number of Command Slots: %d (raw %#lx)\n", fCommandSlotCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
TRACE("cap: Number of Ports: %d (raw %#lx)\n", fPortCount, (fRegs->cap >> CAP_NCS_SHIFT) & CAP_NCS_MASK);
@ -118,7 +125,13 @@ AHCIController::Init()
TRACE("Ports Implemented: %08lx\n", fRegs->pi);
TRACE("Highest port Number: %d\n", fPortMax);
TRACE("AHCI Version %lu.%lu\n", fRegs->vs >> 16, fRegs->vs & 0xff);
TRACE("Interrupt %u\n", fIRQ);
// setup interrupt handler
if (install_io_interrupt_handler(fIRQ, Interrupt, this, 0) < B_OK) {
TRACE("can't install interrupt handler\n");
goto err;
}
for (int i = 0; i <= fPortMax; i++) {
if (fRegs->pi & (1 << i)) {
@ -137,12 +150,6 @@ AHCIController::Init()
}
}
// disable interrupts
fRegs->ghc &= ~GHC_IE;
// clear pending interrupts
fRegs->is = 0xffffffff;
return B_OK;
err:
@ -168,6 +175,10 @@ AHCIController::Uninit()
// clear pending interrupts
fRegs->is = 0xffffffff;
// well...
remove_io_interrupt_handler(fIRQ, Interrupt, this);
delete_area(fRegsArea);
// --- Instance check workaround begin
@ -208,6 +219,31 @@ AHCIController::ResetController()
}
int32
AHCIController::Interrupt(void *data)
{
AHCIController *self = (AHCIController *)data;
uint32 int_stat = self->fRegs->is & self->fRegs->pi;
if (int_stat == 0)
return B_UNHANDLED_INTERRUPT;
for (int i = 0; i < self->fPortMax; i++) {
if (int_stat & (1 << i)) {
if (self->fPorts[i]) {
self->fPorts[i]->Interrupt();
} else {
FLOW("interrupt on non-existent port %d\n", i);
}
}
}
// clear interrupts
self->fRegs->is = int_stat;
return B_INVOKE_SCHEDULER;
}
void
AHCIController::ExecuteRequest(scsi_ccb *request)
{

View File

@ -31,6 +31,8 @@ private:
status_t ResetController();
void RegsFlush();
static int32 Interrupt(void *data);
private:
device_node_handle fNode;
pci_device_info* fPCIDevice;
@ -43,6 +45,7 @@ private:
int fCommandSlotCount;
int fPortCount;
int fPortMax;
uint8 fIRQ;
AHCIPort * fPorts[32];

View File

@ -36,3 +36,10 @@ AHCIPort::Uninit()
{
TRACE("AHCIPort::Uninit port %d\n", fIndex);
}
void
AHCIPort::Interrupt()
{
TRACE("AHCIPort::Interrupt port %d\n", fIndex);
}

View File

@ -17,6 +17,8 @@ public:
status_t Init();
void Uninit();
void Interrupt();
private:
int fIndex;
};