!!! 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:
parent
ca2a912bc9
commit
34d49541b0
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue