modified interrupt handling to fit ata_adapter

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30493 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen
2009-04-29 21:16:18 +00:00
parent 388243cc43
commit 730e6467fe
2 changed files with 27 additions and 54 deletions
@@ -91,20 +91,7 @@ inthand(void *arg)
if ((pci->read_io_8(device, channel->bus_master_base + 3) & 0x20) == 0) if ((pci->read_io_8(device, channel->bus_master_base + 3) & 0x20) == 0)
return B_UNHANDLED_INTERRUPT; return B_UNHANDLED_INTERRUPT;
if (channel->dmaing) { return ide_adapter->inthand(arg);
// in DMA mode, there is a safe test
// in PIO mode, this doesn't work
*(uint8 *)&bm_status = pci->read_io_8( device,
channel->bus_master_base + ide_bm_status_reg );
if (!bm_status.interrupt)
return B_UNHANDLED_INTERRUPT;
}
// acknowledge IRQ
status = pci->read_io_8(device, channel->command_block_base + 7);
return ide->irq_handler(channel->ide_channel, status);
} }
@@ -761,40 +761,27 @@ dma_finish(void *channelCookie)
FLOW("dma_finish enter\n"); FLOW("dma_finish enter\n");
command = *channel->bm_command_reg & ~IDE_BM_COMMAND_START_STOP;
channel->dma_active = false;
*channel->bm_command_reg = command;
status = *channel->bm_status_reg; status = *channel->bm_status_reg;
*channel->bm_status_reg = status | IDE_BM_STATUS_INTERRUPT command = *channel->bm_command_reg;
| IDE_BM_STATUS_ERROR; *channel->bm_command_reg = command & ~IDE_BM_COMMAND_START_STOP;
channel->dma_active = false;
*channel->bm_status_reg = status | IDE_BM_STATUS_ERROR;
*channel->dev_ctrl; // read altstatus to flush *channel->dev_ctrl; // read altstatus to flush
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
TRACE("dma_finish: buffer too large\n");
return B_DEV_DATA_OVERRUN;
}
if ((status & IDE_BM_STATUS_ERROR) != 0) { if ((status & IDE_BM_STATUS_ERROR) != 0) {
FLOW("dma_finish: failed\n"); FLOW("dma_finish: failed\n");
return B_ERROR; return B_ERROR;
} }
if ((status & IDE_BM_STATUS_INTERRUPT) == 0) { FLOW("dma_finish leave\n");
if ((status & IDE_BM_STATUS_ACTIVE) != 0) { return B_OK;
TRACE("dma_finish: transfer aborted\n");
return B_ERROR;
} else {
TRACE("dma_finish: buffer underrun\n");
return B_DEV_DATA_UNDERRUN;
}
} else {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
TRACE("dma_finish: buffer too large\n");
return B_DEV_DATA_OVERRUN;
} else {
FLOW("dma_finish leave\n");
return B_OK;
}
}
} }
@@ -802,12 +789,13 @@ static int32
handle_interrupt(void *arg) handle_interrupt(void *arg)
{ {
controller_data *controller = arg; controller_data *controller = arg;
uint8 status; uint8 statusATA, statusBM;
int32 result, ret; int32 result;
int i; int i;
// FLOW("handle_interrupt\n"); // FLOW("handle_interrupt\n");
result = B_UNHANDLED_INTERRUPT; result = B_UNHANDLED_INTERRUPT;
for (i = 0; i < controller->channel_count; i++) { for (i = 0; i < controller->channel_count; i++) {
@@ -815,21 +803,19 @@ handle_interrupt(void *arg)
if (!channel || channel->lost) if (!channel || channel->lost)
continue; continue;
if (channel->dma_active) { // this could be a spurious interrupt, so always read status
if ((*channel->bm_status_reg & IDE_BM_STATUS_INTERRUPT) == 0) // register unconditionally to acknowledge those
continue; statusATA = *(channel->command_block + 7);
} else {
// for PIO, read the "Task File Configuration + Status" Interrupt
// status
if (!(*channel->stat & (1 << 11)))
continue;
}
// acknowledge IRQ if (!channel->dma_active)
status = *(channel->command_block + 7); continue;
ret = ide->irq_handler(channel->ide_channel, status);
if (ret == B_INVOKE_SCHEDULER || result == B_UNHANDLED_INTERRUPT) statusBM = *channel->bm_status_reg;
result = ret; if (statusBM & IDE_BM_STATUS_INTERRUPT) {
*channel->bm_status_reg = (statusBM & 0xf8) | IDE_BM_STATUS_INTERRUPT;
ide->irq_handler(channel->ide_channel, statusATA);
result = B_INVOKE_SCHEDULER;
}
} }
return result; return result;