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:
parent
a24251b49b
commit
70eb0da7e0
@ -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
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user