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
This commit is contained in:
Marcus Overhagen 2008-01-01 20:31:14 +00:00
parent a24251b49b
commit 70eb0da7e0
5 changed files with 50 additions and 58 deletions

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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);

View File

@ -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);