diff --git a/src/add-ons/kernel/generic/ata_adapter/ata_adapter.c b/src/add-ons/kernel/generic/ata_adapter/ata_adapter.c index bd310aa988..b780fdf3f0 100644 --- a/src/add-ons/kernel/generic/ata_adapter/ata_adapter.c +++ b/src/add-ons/kernel/generic/ata_adapter/ata_adapter.c @@ -184,22 +184,28 @@ ata_adapter_inthand(void *arg) 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) + if (!channel->dmaing) { + // this could be a spurious interrupt, so read status + // register unconditionally to acknowledge those + pci->read_io_8(device, channel->command_block_base + 7); return B_UNHANDLED_INTERRUPT; + } - // read bus master DMA status to test if the interrupt was - // really generated by our controller + // need to read bus master status first, because some controllers + // will clear the interrupt status bit once ATA status is read statusBM = pci->read_io_8(device, channel->bus_master_base + ATA_BM_STATUS_REG); + // test if the interrupt was really generated by our controller if (statusBM & ATA_BM_STATUS_INTERRUPT) { - // clear pending PCI bus master DMA interrupt + // read ATA status register to acknowledge interrupt + statusATA = pci->read_io_8(device, channel->command_block_base + 7); + + // clear pending PCI bus master DMA interrupt, for those + // controllers who don't clear it themselves pci->write_io_8(device, channel->bus_master_base + ATA_BM_STATUS_REG, (statusBM & 0xf8) | ATA_BM_STATUS_INTERRUPT); + // signal interrupt to ATA stack return sATA->interrupt_handler(channel->ataChannel, statusATA); } else { @@ -484,6 +490,7 @@ ata_adapter_detect_channel(pci_device_module_info *pci, pci_device *pci_device, uint8 api; uint16 pcicmdOld; uint16 pcicmdNew; + uint16 pciVendor; SHOW_FLOW0( 3, "" ); @@ -539,9 +546,9 @@ ata_adapter_detect_channel(pci_device_module_info *pci, pci_device *pci_device, } if (pcicmdOld != pcicmdNew) { pci->write_pci_config(pci_device, PCI_command, 2, pcicmdNew); + TRACE("PCI-ATA: pcicmd changed from 0x%04x to 0x%04x\n", + pcicmdOld, pcicmdNew); } - TRACE("PCI-ATA: pcicmd old 0x%04x, new 0x%04x\n", - pcicmdOld, pcicmdNew); if (supports_compatibility_mode) { @@ -555,8 +562,16 @@ ata_adapter_detect_channel(pci_device_module_info *pci, pci_device *pci_device, // better were to use a controller lock, but this had to be done in the IDE // bus manager, and I don't see any reason to add extra code for old // simplex controllers - TRACE("PCI-ATA: Simplex controller - disabling DMA of secondary channel\n"); - controller_can_dma = false; + + // Intel controllers use this bit for something else and are not simplex. + pciVendor = pci->read_pci_config(pci_device, PCI_vendor_id, 2); + + if (pciVendor != 0x8086) { + TRACE("PCI-ATA: Simplex controller - disabling DMA of secondary channel\n"); + controller_can_dma = false; + } else { + TRACE("PCI-ATA: Simplex bit ignored - Intel controller\n"); + } } }