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:
@@ -24,6 +24,7 @@ AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
|||||||
, fCommandSlotCount(0)
|
, fCommandSlotCount(0)
|
||||||
, fPortCount(0)
|
, fPortCount(0)
|
||||||
, fPortMax(0)
|
, fPortMax(0)
|
||||||
|
, fIRQ(0)
|
||||||
, fInstanceCheck(-1)
|
, fInstanceCheck(-1)
|
||||||
{
|
{
|
||||||
memset(fPorts, 0, sizeof(fPorts));
|
memset(fPorts, 0, sizeof(fPorts));
|
||||||
@@ -100,6 +101,12 @@ AHCIController::Init()
|
|||||||
while ((fRegs->pi & (1 << fPortMax)) == 0)
|
while ((fRegs->pi & (1 << fPortMax)) == 0)
|
||||||
fPortMax--;
|
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: 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 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);
|
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("Ports Implemented: %08lx\n", fRegs->pi);
|
||||||
TRACE("Highest port Number: %d\n", fPortMax);
|
TRACE("Highest port Number: %d\n", fPortMax);
|
||||||
TRACE("AHCI Version %lu.%lu\n", fRegs->vs >> 16, fRegs->vs & 0xff);
|
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++) {
|
for (int i = 0; i <= fPortMax; i++) {
|
||||||
if (fRegs->pi & (1 << 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;
|
return B_OK;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@@ -168,6 +175,10 @@ AHCIController::Uninit()
|
|||||||
// clear pending interrupts
|
// clear pending interrupts
|
||||||
fRegs->is = 0xffffffff;
|
fRegs->is = 0xffffffff;
|
||||||
|
|
||||||
|
// well...
|
||||||
|
remove_io_interrupt_handler(fIRQ, Interrupt, this);
|
||||||
|
|
||||||
|
|
||||||
delete_area(fRegsArea);
|
delete_area(fRegsArea);
|
||||||
|
|
||||||
// --- Instance check workaround begin
|
// --- 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
|
void
|
||||||
AHCIController::ExecuteRequest(scsi_ccb *request)
|
AHCIController::ExecuteRequest(scsi_ccb *request)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ private:
|
|||||||
status_t ResetController();
|
status_t ResetController();
|
||||||
void RegsFlush();
|
void RegsFlush();
|
||||||
|
|
||||||
|
static int32 Interrupt(void *data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
device_node_handle fNode;
|
device_node_handle fNode;
|
||||||
pci_device_info* fPCIDevice;
|
pci_device_info* fPCIDevice;
|
||||||
@@ -43,6 +45,7 @@ private:
|
|||||||
int fCommandSlotCount;
|
int fCommandSlotCount;
|
||||||
int fPortCount;
|
int fPortCount;
|
||||||
int fPortMax;
|
int fPortMax;
|
||||||
|
uint8 fIRQ;
|
||||||
AHCIPort * fPorts[32];
|
AHCIPort * fPorts[32];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,3 +36,10 @@ AHCIPort::Uninit()
|
|||||||
{
|
{
|
||||||
TRACE("AHCIPort::Uninit port %d\n", fIndex);
|
TRACE("AHCIPort::Uninit port %d\n", fIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
AHCIPort::Interrupt()
|
||||||
|
{
|
||||||
|
TRACE("AHCIPort::Interrupt port %d\n", fIndex);
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ public:
|
|||||||
status_t Init();
|
status_t Init();
|
||||||
void Uninit();
|
void Uninit();
|
||||||
|
|
||||||
|
void Interrupt();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int fIndex;
|
int fIndex;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user