!!! To use with the ATA stack, change #define ATA_STACK from 0 to 1 !!!

Adapted to new ata stack. Works now. Hopefully useable with ide stack, too.

Modified to fix the DMA problem introduced with the last change. 
Since the interrupt is already cleared in the interrupt handler,
we can no longer test the interrupt bit in finish_dma().



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30475 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2009-04-27 22:13:05 +00:00
parent ca2a912bc9
commit 34d49541b0
1 changed files with 75 additions and 2 deletions

View File

@ -31,6 +31,8 @@
#define TRACE dprintf
// set this to 1 for the ata stack, or 0 for the ide stack
#define ATA_STACK 0
static ide_for_controller_interface *ide;
static device_manager_info *pnp;
@ -188,6 +190,35 @@ ide_adapter_read_pio(ide_adapter_channel_info *channel, uint16 *data,
static int32
ide_adapter_inthand(void *arg)
{
#if ATA_STACK
ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg;
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 statusATA, statusBM;
// this could be a spurious interrupt, so always read status
// register unconditionally to acknowledge those
statusATA = pci->read_io_8(device, channel->command_block_base + 7);
if (!channel->dmaing)
return B_UNHANDLED_INTERRUPT;
// read bus master DMA status to test if the interrupt was
// really generated by our controller
statusBM = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
if (statusBM & IDE_BM_STATUS_INTERRUPT) {
// clear pending PCI bus master DMA interrupt
pci->write_io_8(device, channel->bus_master_base + IDE_BM_STATUS_REG,
(statusBM & 0xf8) | IDE_BM_STATUS_INTERRUPT);
// signal interrupt to ATA stack
return ide->irq_handler(channel->ide_channel, statusATA);
} else {
return B_UNHANDLED_INTERRUPT;
}
#else
ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg;
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
@ -215,6 +246,7 @@ ide_adapter_inthand(void *arg)
status = pci->read_io_8(device, channel->command_block_base + 7);
return ide->irq_handler(channel->ide_channel, status);
#endif
}
@ -274,6 +306,7 @@ ide_adapter_start_dma(ide_adapter_channel_info *channel)
+ IDE_BM_COMMAND_REG);
command |= IDE_BM_COMMAND_START_STOP;
channel->dmaing = true;
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
@ -286,6 +319,36 @@ ide_adapter_start_dma(ide_adapter_channel_info *channel)
static status_t
ide_adapter_finish_dma(ide_adapter_channel_info *channel)
{
#if ATA_STACK
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 command;
uint8 status;
// read BM status first
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
// stop DMA engine, this also clears IDE_BM_STATUS_ACTIVE
// in the BM status register
command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command & ~IDE_BM_COMMAND_START_STOP);
channel->dmaing = false;
// reset error flag
pci->write_io_8(device, channel->bus_master_base + IDE_BM_STATUS_REG,
status | IDE_BM_STATUS_ERROR);
if ((status & IDE_BM_STATUS_ACTIVE) != 0)
return B_DEV_DATA_OVERRUN;
if ((status & IDE_BM_STATUS_ERROR) != 0)
return B_ERROR;
return B_OK;
#else
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 command;
@ -310,7 +373,9 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
if ((status & IDE_BM_STATUS_ERROR) != 0)
return B_ERROR;
/*
// this doesn't work anymore, because the
// interrupt handler always clears this bit now
if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer aborted" );
@ -320,13 +385,14 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
SHOW_ERROR0( 2, "DMA transfer: buffer underrun" );
return B_DEV_DATA_UNDERRUN;
}
*/
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer: buffer too large" );
return B_DEV_DATA_OVERRUN;
}
return B_OK;
#endif
}
@ -417,8 +483,15 @@ ide_adapter_init_channel(device_node *node,
}
TRACE("PCI-IDE: init channel done\n");
#if ATA_STACK
// disable interrupts
ide_adapter_write_device_control(channel, ide_devctrl_bit3 | ide_devctrl_nien);
#else
// enable interrupts so the channel is ready to run
ide_adapter_write_device_control(channel, ide_devctrl_bit3);
#endif
*cookie = channel;