diff --git a/headers/os/drivers/bus/ATA.h b/headers/os/drivers/bus/ATA.h index e6cd8aaf81..bb30d11b5c 100644 --- a/headers/os/drivers/bus/ATA.h +++ b/headers/os/drivers/bus/ATA.h @@ -17,7 +17,7 @@ // maximum number of devices connected to controller (uint8, optional, default:2) #define ATA_CONTROLLER_MAX_DEVICES_ITEM "ide/max_devices" // set to not-0 if DMA is supported (uint8, optional, default:0) -#define ATA_CONTROLLER_CAN_DMA_ITEM "ide/can_dma" +#define ATA_CONTROLLER_CAN_DMA_ITEM "ide/can_DMA" // name of controller (string, required) #define ATA_CONTROLLER_CONTROLLER_NAME_ITEM "ide/controller_name" diff --git a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp index d5ad4c2fc0..72edd74def 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp @@ -18,17 +18,21 @@ ATAChannel::ATAChannel(device_node *node) fSCSIBus(NULL), fDeviceCount(0), fDevices(NULL), - fUseDMA(false), + fUseDMA(true), fRequest(NULL) { mutex_init(&fLock, "ata channel"); + gDeviceManager->get_attr_uint32(node, ATA_CHANNEL_ID_ITEM, &fChannelID, + true); + snprintf(fDebugContext, sizeof(fDebugContext), " %lu", fChannelID); + if (fUseDMA) { void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS); if (settings != NULL) { if (get_driver_boolean_parameter(settings, B_SAFEMODE_DISABLE_IDE_DMA, false, false)) { - TRACE("disabling dma because of safemode setting\n"); + TRACE_ALWAYS("disabling DMA because of safemode setting\n"); fUseDMA = false; } @@ -39,7 +43,13 @@ ATAChannel::ATAChannel(device_node *node) if (fUseDMA) { uint8 canDMA; if (gDeviceManager->get_attr_uint8(node, ATA_CONTROLLER_CAN_DMA_ITEM, - &canDMA, true) != B_OK || canDMA == 0) { + &canDMA, true) != B_OK) { + TRACE_ERROR("unknown if controller supports DMA, not using it\n"); + fUseDMA = false; + } + + if (canDMA == 0) { + TRACE_ALWAYS("controller doesn't support DMA, disabling\n"); fUseDMA = false; } } @@ -66,11 +76,6 @@ ATAChannel::ATAChannel(device_node *node) for (uint8 i = 0; i < fDeviceCount; i++) fDevices[i] = NULL; - - gDeviceManager->get_attr_uint32(node, ATA_CHANNEL_ID_ITEM, &fChannelID, - true); - snprintf(fDebugContext, sizeof(fDebugContext), " %lu", fChannelID); - device_node *parent = gDeviceManager->get_parent_node(node); fStatus = gDeviceManager->get_driver(parent, (driver_module_info **)&fController, &fCookie); @@ -149,15 +154,15 @@ ATAChannel::ScanBus() continue; } - TRACE_ALWAYS("identified ATA%s device %u\n", device->IsATAPI() - ? "PI" : "", i); - if (device->Configure() != B_OK) { TRACE_ERROR("failed to configure device\n"); delete device; continue; } + TRACE_ALWAYS("identified ATA%s device %u\n", device->IsATAPI() + ? "PI" : "", i); + fDevices[i] = device; } diff --git a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp index fdc9eb0ff2..3c802c4c68 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp @@ -16,6 +16,7 @@ ATADevice::ATADevice(ATAChannel *channel, uint8 index) fUseLBA(false), fUse48Bits(false), fUseDMA(channel->UseDMA()), + fDMAMode(0), fTotalSectors(0), fRegisterMask(0) { @@ -361,7 +362,43 @@ ATADevice::ConfigureDMA() if (!fUseDMA) return B_OK; - fUseDMA = false; + if (!fInfoBlock.DMA_supported) { + TRACE_ALWAYS("DMA not supported by device\n"); + fUseDMA = false; + return B_OK; + } + + #define CHECK_DMA_MODE(element, mode) \ + if (fInfoBlock.element) { \ + fDMAMode = mode; \ + modeCount++; \ + } + + uint32 modeCount = 0; + + CHECK_DMA_MODE(MDMA0_selected, 0x00); + CHECK_DMA_MODE(MDMA1_selected, 0x01); + CHECK_DMA_MODE(MDMA2_selected, 0x02); + + if (fInfoBlock._88_valid) { + CHECK_DMA_MODE(UDMA0_selected, 0x10); + CHECK_DMA_MODE(UDMA1_selected, 0x11); + CHECK_DMA_MODE(UDMA2_selected, 0x12); + CHECK_DMA_MODE(UDMA3_selected, 0x13); + CHECK_DMA_MODE(UDMA4_selected, 0x14); + CHECK_DMA_MODE(UDMA5_selected, 0x15); + CHECK_DMA_MODE(UDMA6_selected, 0x16); + } + + #undef CHECK_DMA_MODE + + if (modeCount != 1) { + TRACE_ERROR("more than on DMA mode selected, not using DMA\n"); + fUseDMA = false; + return B_OK; + } + + TRACE_ALWAYS("using DMA mode 0x%02x\n", fDMAMode); return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h index ac3f1adecd..4a99efe629 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h +++ b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h @@ -188,6 +188,7 @@ private: bool fUseLBA; bool fUse48Bits; bool fUseDMA; + uint8 fDMAMode; uint64 fTotalSectors; ata_device_infoblock fInfoBlock; ata_task_file fTaskFile;