From 70eb0da7e03dd17505154258d4b726a30744ff2c Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Tue, 1 Jan 2008 20:31:14 +0000 Subject: [PATCH] Mask io-space bit in promise_tx2 driver, the driver was broken after recent ide-adapter changes. Replaced IDE_ADAPTER_IS_PRIMARY by IDE_ADAPTER_CHANNEL_INDEX to support more than 2 bus master channels, and made ide_adapter aware of 3rd and 4th channel when calculating bus master dma address. Fixed bus master DMA support in legacy_sata driver for tertiary and quaternary channel, channel 3 and 4 were using the DMA engine of primary and secondary channels (that might have destroyed your data). Use PCI_address_io_mask instead of ~PCI_address_space (no functional change). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23207 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../build/os/drivers/bus/ide/ide_adapter.h | 8 ++-- headers/private/drivers/ide_adapter.h | 9 ++--- .../busses/ide/legacy_sata/legacy_sata.c | 37 ++++++----------- .../busses/ide/promise_tx2/promise_tx2.c | 14 +++++-- .../kernel/generic/ide_adapter/ide_adapter.c | 40 +++++++++---------- 5 files changed, 50 insertions(+), 58 deletions(-) diff --git a/headers/build/os/drivers/bus/ide/ide_adapter.h b/headers/build/os/drivers/bus/ide/ide_adapter.h index e840d62f2d..45e60f5d56 100644 --- a/headers/build/os/drivers/bus/ide/ide_adapter.h +++ b/headers/build/os/drivers/bus/ide/ide_adapter.h @@ -93,8 +93,8 @@ enum { // interrupt number (uint8) // can also be defined in controller node if both channels use same IRQ! #define IDE_ADAPTER_INTNUM "ide_adapter/irq" -// non-zero if primary channel, else secondary channel (uint8) -#define IDE_ADAPTER_IS_PRIMARY "ide_adapter/is_primary" +// 0 if primary channel, 1 if secondary channel, 2 if tertiary, ... (uint8) +#define IDE_ADAPTER_CHANNEL_INDEX "ide_adapter/channel_index" // controller node items @@ -177,14 +177,14 @@ typedef struct { status_t (*publish_channel)(device_node_handle controller_node, const char *channel_module_name, uint16 command_block_base, uint16 control_block_base, uint8 intnum, bool can_dma, - bool is_primary, const char *name, + uint8 channel_index, const char *name, io_resource_handle *resources, device_node_handle *node); // verify channel configuration and publish node on success status_t (*detect_channel)(pci_device_module_info *pci, pci_device pci_device, device_node_handle controller_node, const char *channel_module_name, bool controller_can_dma, uint16 command_block_base, uint16 control_block_base, uint16 bus_master_base, - uint8 intnum, bool is_primary, const char *name, + uint8 intnum, uint8 channel_index, const char *name, device_node_handle *node, bool supports_compatibility_mode); // functions that must be called by init/uninit etc. of controller driver diff --git a/headers/private/drivers/ide_adapter.h b/headers/private/drivers/ide_adapter.h index 12c1a0d25f..9beb632691 100644 --- a/headers/private/drivers/ide_adapter.h +++ b/headers/private/drivers/ide_adapter.h @@ -80,9 +80,8 @@ enum { // interrupt number (uint8) // can also be defined in controller node if both channels use same IRQ! #define IDE_ADAPTER_INTNUM "ide_adapter/irq" -// non-zero if primary channel, else secondary channel (uint8) -#define IDE_ADAPTER_IS_PRIMARY "ide_adapter/is_primary" - +// 0 if primary channel, 1 if secondary channel, 2 if tertiary, ... (uint8) +#define IDE_ADAPTER_CHANNEL_INDEX "ide_adapter/channel_index" // controller node items // io address of bus master registers (uint16) @@ -164,14 +163,14 @@ typedef struct { status_t (*publish_channel)(device_node_handle controller_node, const char *channel_module_name, uint16 command_block_base, uint16 control_block_base, uint8 intnum, bool can_dma, - bool is_primary, const char *name, + uint8 channel_index, const char *name, io_resource_handle *resources, device_node_handle *node); // verify channel configuration and publish node on success status_t (*detect_channel)(pci_device_module_info *pci, pci_device pci_device, device_node_handle controller_node, const char *channel_module_name, bool controller_can_dma, uint16 command_block_base, uint16 control_block_base, uint16 bus_master_base, - uint8 intnum, bool is_primary, const char *name, + uint8 intnum, uint8 channel_index, const char *name, device_node_handle *node, bool supports_compatibility_mode); // functions that must be called by init/uninit etc. of controller driver diff --git a/src/add-ons/kernel/busses/ide/legacy_sata/legacy_sata.c b/src/add-ons/kernel/busses/ide/legacy_sata/legacy_sata.c index 5d6b89fafc..c7aa3158ed 100644 --- a/src/add-ons/kernel/busses/ide/legacy_sata/legacy_sata.c +++ b/src/add-ons/kernel/busses/ide/legacy_sata/legacy_sata.c @@ -51,6 +51,11 @@ /* XXX: To be moved to PCI.h */ #define PCI_command_interrupt 0x400 +static const char * const kChannelNames[] = { + "Primary Channel", "Secondary Channel", + "Tertiary Channel", "Quaternary Channel" +}; + static ide_for_controller_interface* ide; static ide_adapter_interface* ide_adapter; static device_manager_info* dm; @@ -184,10 +189,10 @@ controller_probe(device_node_handle parent) break; } - bus_master_base &= ~PCI_address_space; + bus_master_base &= PCI_address_io_mask; for (index = 0; index < num_channels; index++) { - command_block_base[index] &= ~PCI_address_space; - control_block_base[index] &= ~PCI_address_space; + command_block_base[index] &= PCI_address_io_mask; + control_block_base[index] &= PCI_address_io_mask; } res = ide_adapter->detect_controller(pci, device, parent, bus_master_base, @@ -203,32 +208,16 @@ controller_probe(device_node_handle parent) } // ignore errors during registration of channels - could be a simple rescan collision - res = ide_adapter->detect_channel(pci, device, controller_node, CHANNEL_MODULE_NAME, - true, command_block_base[0], control_block_base[0], bus_master_base, - int_num, true, "Primary Channel", &channels[0], false); - dprintf("Primary Channel: %s\n", strerror(res)); - - res = ide_adapter->detect_channel(pci, device, controller_node, CHANNEL_MODULE_NAME, - true, command_block_base[1], control_block_base[1], bus_master_base, - int_num, false, "Secondary Channel", &channels[1], false); - - dprintf("Secondary Channel: %s\n", strerror(res)); - - if (num_channels == 4) { + for (index = 0; index < num_channels; index++) { res = ide_adapter->detect_channel(pci, device, controller_node, CHANNEL_MODULE_NAME, - true, command_block_base[2], control_block_base[2], bus_master_base, - int_num, true, "Tertiary Channel", &channels[2], false); + true, command_block_base[index], control_block_base[index], bus_master_base, + int_num, index, kChannelNames[index], &channels[index], false); - dprintf("Tertiary Channel: %s\n", strerror(res)); - - res = ide_adapter->detect_channel(pci, device, controller_node, CHANNEL_MODULE_NAME, - true, command_block_base[3], control_block_base[3], bus_master_base, - int_num, false, "Quaternary Channel", &channels[3], false); - - dprintf("Quaternary Channel: %s\n", strerror(res)); + dprintf("%s: %s\n", kChannelNames[index], strerror(res)); } + dm->uninit_driver(parent); TRACE("controller_probe success\n"); diff --git a/src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c b/src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c index fd353cb999..57ae2bf3e6 100644 --- a/src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c +++ b/src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c @@ -274,19 +274,25 @@ probe_controller(device_node_handle parent) bus_master_base = pci->read_pci_config(device, PCI_base_registers + 16, 4); intnum = pci->read_pci_config(device, PCI_interrupt_line, 1); + command_block_base[0] &= PCI_address_io_mask; + control_block_base[0] &= PCI_address_io_mask; + command_block_base[1] &= PCI_address_io_mask; + control_block_base[1] &= PCI_address_io_mask; + bus_master_base &= PCI_address_io_mask; + res = detect_controller(pci, device, parent, bus_master_base, intnum, &controller_node); if (res != B_OK || controller_node == NULL) goto err; ide_adapter->detect_channel(pci, device, controller_node, PROMISE_TX2_CHANNEL_MODULE_NAME, true, - command_block_base[0], control_block_base[0], bus_master_base, intnum, true, - "Primary Channel", &channels[0], false); + command_block_base[0], control_block_base[0], bus_master_base, intnum, + 0, "Primary Channel", &channels[0], false); ide_adapter->detect_channel(pci, device, controller_node, PROMISE_TX2_CHANNEL_MODULE_NAME, true, - command_block_base[1], control_block_base[1], bus_master_base, intnum, false, - "Secondary Channel", &channels[1], false); + command_block_base[1], control_block_base[1], bus_master_base, intnum, + 1, "Secondary Channel", &channels[1], false); pnp->uninit_driver(parent); diff --git a/src/add-ons/kernel/generic/ide_adapter/ide_adapter.c b/src/add-ons/kernel/generic/ide_adapter/ide_adapter.c index e17b1cd106..5e2181976e 100644 --- a/src/add-ons/kernel/generic/ide_adapter/ide_adapter.c +++ b/src/add-ons/kernel/generic/ide_adapter/ide_adapter.c @@ -329,7 +329,7 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel, uint8 intnum; int prdt_size; physical_entry pe[1]; - uint8 is_primary; + uint8 channel_index; status_t res; TRACE("PCI-IDE: init channel...\n"); @@ -338,7 +338,7 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel, if (pnp->get_attr_uint16(node, IDE_ADAPTER_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK || pnp->get_attr_uint16(node, IDE_ADAPTER_CONTROL_BLOCK_BASE, &control_block_base, false) != B_OK || pnp->get_attr_uint8(node, IDE_ADAPTER_INTNUM, &intnum, true) != B_OK - || pnp->get_attr_uint8(node, IDE_ADAPTER_IS_PRIMARY, &is_primary, false) != B_OK) + || pnp->get_attr_uint8(node, IDE_ADAPTER_CHANNEL_INDEX, &channel_index, false) != B_OK) return B_ERROR; if (pnp->init_driver(pnp->get_parent(node), NULL, NULL, (void **)&controller) != B_OK) @@ -356,12 +356,14 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel, channel->lost = false; channel->command_block_base = command_block_base; channel->control_block_base = control_block_base; - channel->bus_master_base = controller->bus_master_base + (is_primary ? 0 : 8); + channel->bus_master_base = controller->bus_master_base + (channel_index * 8); channel->intnum = intnum; channel->ide_channel = ide_channel; channel->dmaing = false; channel->inthand = inthand; + TRACE("PCI-IDE: bus master base %#x\n", channel->bus_master_base); + // PRDT must be contiguous, dword-aligned and must not cross 64K boundary prdt_size = (IDE_ADAPTER_MAX_SG_COUNT * sizeof( prd_entry ) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1); channel->prd_area = create_area("prd", (void **)&channel->prdt, B_ANY_KERNEL_ADDRESS, @@ -442,7 +444,7 @@ static status_t ide_adapter_publish_channel(device_node_handle controller_node, const char *channel_module_name, uint16 command_block_base, uint16 control_block_base, uint8 intnum, bool can_dma, - bool is_primary, const char *name, io_resource_handle *resources, + uint8 channel_index, const char *name, io_resource_handle *resources, device_node_handle *node) { device_attr attrs[] = { @@ -457,7 +459,7 @@ ide_adapter_publish_channel(device_node_handle controller_node, { IDE_ADAPTER_CONTROL_BLOCK_BASE, B_UINT16_TYPE, { ui16: control_block_base }}, { IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: can_dma }}, { IDE_ADAPTER_INTNUM, B_UINT8_TYPE, { ui8: intnum }}, - { IDE_ADAPTER_IS_PRIMARY, B_UINT8_TYPE, { ui8: is_primary }}, + { IDE_ADAPTER_CHANNEL_INDEX, B_UINT8_TYPE, { ui8: channel_index }}, { NULL } }; @@ -473,7 +475,7 @@ static status_t ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device, device_node_handle controller_node, const char *channel_module_name, bool controller_can_dma, uint16 command_block_base, uint16 control_block_base, - uint16 bus_master_base, uint8 intnum, bool is_primary, const char *name, + uint16 bus_master_base, uint8 intnum, uint8 channel_index, const char *name, device_node_handle *node, bool supports_compatibility_mode) { uint8 api; @@ -485,14 +487,14 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device, api = pci->read_pci_config(pci_device, PCI_class_api, 1); if (supports_compatibility_mode - && is_primary && (api & IDE_API_PRIMARY_NATIVE) == 0) { + && channel_index == 0 && (api & IDE_API_PRIMARY_NATIVE) == 0) { command_block_base = 0x1f0; control_block_base = 0x3f6; intnum = 14; TRACE("PCI-IDE: Controller in legacy mode: cmd %#x, ctrl %#x, irq %d\n", command_block_base, control_block_base, intnum); } else if (supports_compatibility_mode - && !is_primary && (api & IDE_API_PRIMARY_NATIVE) == 0) { + && channel_index == 1 && (api & IDE_API_PRIMARY_NATIVE) == 0) { command_block_base = 0x170; control_block_base = 0x376; intnum = 15; @@ -521,7 +523,7 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device, uint8 status = pci->read_io_8(pci_device, bus_master_base + IDE_BM_STATUS_REG); - if (status & IDE_BM_STATUS_SIMPLEX_DMA && !is_primary) { + if (status & IDE_BM_STATUS_SIMPLEX_DMA && channel_index != 0) { // in simplex mode, channels cannot operate independantly of each other; // we simply disable bus mastering of second channel to satisfy that; // better were to use a controller lock, but this had to be done in the IDE @@ -532,10 +534,6 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device, } } - bus_master_base += is_primary ? 0 : 8; - - TRACE("PCI-IDE: bus master base %#x\n", bus_master_base); - { // allocate channel's I/O resources io_resource resources[3] = { @@ -553,7 +551,7 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device, return ide_adapter_publish_channel(controller_node, channel_module_name, command_block_base, control_block_base, intnum, controller_can_dma, - is_primary, name, resource_handles, node); + channel_index, name, resource_handles, node); } @@ -738,11 +736,11 @@ ide_adapter_probe_controller(device_node_handle parent, const char *controller_d bus_master_base = pci->read_pci_config(device, PCI_base_registers + 16, 4); intnum = pci->read_pci_config(device, PCI_interrupt_line, 1); - command_block_base[0] &= ~PCI_address_space; - control_block_base[0] &= ~PCI_address_space; - command_block_base[1] &= ~PCI_address_space; - control_block_base[1] &= ~PCI_address_space; - bus_master_base &= ~PCI_address_space; + command_block_base[0] &= PCI_address_io_mask; + control_block_base[0] &= PCI_address_io_mask; + command_block_base[1] &= PCI_address_io_mask; + control_block_base[1] &= PCI_address_io_mask; + bus_master_base &= PCI_address_io_mask; res = ide_adapter_detect_controller(pci, device, parent, bus_master_base, controller_driver, controller_driver_type, controller_name, can_dma, @@ -755,11 +753,11 @@ ide_adapter_probe_controller(device_node_handle parent, const char *controller_d // ignore errors during registration of channels - could be a simple rescan collision ide_adapter_detect_channel(pci, device, controller_node, channel_module_name, can_dma, command_block_base[0], control_block_base[0], bus_master_base, - intnum, true, "Primary Channel", &channels[0], supports_compatibility_mode); + intnum, 0, "Primary Channel", &channels[0], supports_compatibility_mode); ide_adapter_detect_channel(pci, device, controller_node, channel_module_name, can_dma, command_block_base[1], control_block_base[1], bus_master_base, - intnum, false, "Secondary Channel", &channels[1], supports_compatibility_mode); + intnum, 1, "Secondary Channel", &channels[1], supports_compatibility_mode); pnp->uninit_driver(parent);