No wonder no one noticed that the silicon_image_3112 driver was broken; I

actually forgot to commit the changes I made to the ide_adapter...
* the IDE bus master command/status stuff is now used via flags; it's no
  bitfield anymore.
* Changed a few constants to upper case.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22842 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-11-06 02:26:44 +00:00
parent a81e874ffb
commit 6405549873
2 changed files with 75 additions and 89 deletions
+19 -33
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2005-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2002-04, Thomas Kurschel. All rights reserved. * Copyright 2002-04, Thomas Kurschel. All rights reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
@@ -36,47 +36,33 @@ typedef struct prd_entry {
); );
} prd_entry; } prd_entry;
// IDE bus master command register
#define IDE_BM_COMMAND_START_STOP 0x01
#define IDE_BM_COMMAND_READ_FROM_DEVICE 0x08
// command register // IDE bus master status register
typedef struct ide_bm_command { #define IDE_BM_STATUS_ACTIVE 0x01
LBITFIELD8_4( #define IDE_BM_STATUS_ERROR 0x02
start_stop : 1, // start BM by changing from 0 to 1; #define IDE_BM_STATUS_INTERRUPT 0x04
// stop BM by changing from 1 to 0 #define IDE_BM_STATUS_MASTER_DMA 0x20
res0_1 : 2, #define IDE_BM_STATUS_SLAVE_DMA 0x40
from_device : 1, // true - read from device, false - write to device #define IDE_BM_STATUS_SIMPLEX_DMA 0x80
res0_4 : 4
);
} ide_bm_command;
// status register
typedef struct ide_bm_status {
LBITFIELD8_7(
active : 1, // 1, if BM is active
error : 1, // 1, if error occured; write 1 to reset
interrupt : 1, // 1, if INTRQ was raised, write 1 to reset
res0_3 : 2,
device0_dma : 1, // 1, if BIOS/driver has setup DMA for device 0
device1_dma : 1, // 1, if BIOS/driver has setup DMA for device 1
simplex : 1 // 1, if only one channel can use DMA at a time
);
} ide_bm_status;
// offset of bus master registers // offset of bus master registers
enum { enum {
ide_bm_command_reg = 0, // see ide_bm_command IDE_BM_COMMAND_REG = 0,
ide_bm_status_reg = 2, // see ide_bm_status IDE_BM_STATUS_REG = 2,
ide_bm_prdt_address = 4 // offset of PRDT register; content must be dword-aligned IDE_BM_PRDT_ADDRESS = 4
// offset of PRDT register; content must be dword-aligned
}; };
// bit mask in class_api of PCI configuration // bit mask in class_api of PCI configuration
// (for adapters that can run in compatability mode) // (for adapters that can run in compatability mode)
enum { enum {
ide_api_primary_native = 1, // primary channel is in native mode IDE_API_PRIMARY_NATIVE = 1, // primary channel is in native mode
ide_api_primary_fixed = 2, // primary channel can be switched to native mode IDE_API_PRIMARY_FIXED = 2, // primary channel can be switched to native mode
ide_api_secondary_native = 4, // secondary channel is in native mode IDE_API_SECONDARY_NATIVE = 4, // secondary channel is in native mode
ide_api_secondary_fixed = 8 // secondary channel can be switched to native mode IDE_API_SECONDARY_FIXED = 8 // secondary channel can be switched to native mode
}; };
@@ -180,10 +180,9 @@ ide_adapter_inthand(void *arg)
ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg; ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg;
pci_device_module_info *pci = channel->pci; pci_device_module_info *pci = channel->pci;
pci_device device = channel->device; pci_device device = channel->device;
ide_bm_status bm_status;
uint8 status; uint8 status;
SHOW_FLOW0( 3, "" ); SHOW_FLOW0(3, "");
if (channel->lost) if (channel->lost)
return B_UNHANDLED_INTERRUPT; return B_UNHANDLED_INTERRUPT;
@@ -192,10 +191,9 @@ ide_adapter_inthand(void *arg)
if (channel->dmaing) { if (channel->dmaing) {
// in DMA mode, there is a safe test // in DMA mode, there is a safe test
// in PIO mode, this don't work // in PIO mode, this don't work
*(uint8 *)&bm_status = pci->read_io_8(device, status = pci->read_io_8(device, channel->bus_master_base
channel->bus_master_base + ide_bm_status_reg); + IDE_BM_STATUS_REG);
if ((status & IDE_BM_STATUS_INTERRUPT) == 0)
if (!bm_status.interrupt)
return B_UNHANDLED_INTERRUPT; return B_UNHANDLED_INTERRUPT;
} }
@@ -207,47 +205,45 @@ ide_adapter_inthand(void *arg)
static status_t static status_t
ide_adapter_prepare_dma(ide_adapter_channel_info *channel, const physical_entry *sg_list, ide_adapter_prepare_dma(ide_adapter_channel_info *channel,
size_t sg_list_count, bool to_device) const physical_entry *sgList, size_t sgListCount, bool writeToDevice)
{ {
pci_device_module_info *pci = channel->pci; pci_device_module_info *pci = channel->pci;
pci_device device = channel->device; pci_device device = channel->device;
ide_bm_command command; uint8 command;
ide_bm_status status; uint8 status;
prd_entry *prd = channel->prdt; prd_entry *prd = channel->prdt;
int i; int i;
for (i = sg_list_count - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sg_list) { for (i = sgListCount - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sgList) {
prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, sg_list->address)); prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, sgList->address));
// 0 means 64K - this is done automatically be discarding upper 16 bits // 0 means 64K - this is done automatically be discarding upper 16 bits
prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sg_list->size); prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sgList->size);
prd->EOT = i == 0; prd->EOT = i == 0;
SHOW_FLOW( 4, "%x, %x, %d", (int)prd->address, prd->count, prd->EOT); SHOW_FLOW( 4, "%x, %x, %d", (int)prd->address, prd->count, prd->EOT);
} }
pci->write_io_32(device, channel->bus_master_base + ide_bm_prdt_address, pci->write_io_32(device, channel->bus_master_base + IDE_BM_PRDT_ADDRESS,
(pci->read_io_32(device, channel->bus_master_base + ide_bm_prdt_address) & 3) (pci->read_io_32(device, channel->bus_master_base + IDE_BM_PRDT_ADDRESS) & 3)
| (B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, (void *)channel->prdt_phys)) & ~3)); | (B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, (void *)channel->prdt_phys)) & ~3));
// reset interrupt and error signal // reset interrupt and error signal
*(uint8 *)&status = pci->read_io_8(device, status = pci->read_io_8(device, channel->bus_master_base
channel->bus_master_base + ide_bm_status_reg); + IDE_BM_STATUS_REG) | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
status.interrupt = 1;
status.error = 1;
pci->write_io_8(device, pci->write_io_8(device,
channel->bus_master_base + ide_bm_status_reg, *(uint8 *)&status); channel->bus_master_base + IDE_BM_STATUS_REG, status);
// set data direction // set data direction
*(uint8 *)&command = pci->read_io_8(device, command = pci->read_io_8(device, channel->bus_master_base
channel->bus_master_base + ide_bm_command_reg); + IDE_BM_COMMAND_REG);
if (writeToDevice)
command &= ~IDE_BM_COMMAND_READ_FROM_DEVICE;
else
command |= IDE_BM_COMMAND_READ_FROM_DEVICE;
command.from_device = !to_device; pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
pci->write_io_8(device,
channel->bus_master_base + ide_bm_command_reg, *(uint8 *)&command);
return B_OK; return B_OK;
} }
@@ -258,14 +254,16 @@ ide_adapter_start_dma(ide_adapter_channel_info *channel)
{ {
pci_device_module_info *pci = channel->pci; pci_device_module_info *pci = channel->pci;
pci_device device = channel->device; pci_device device = channel->device;
ide_bm_command command; uint8 command;
*(uint8 *)&command = pci->read_io_8(device, channel->bus_master_base + ide_bm_command_reg); command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
command.start_stop = 1; command |= IDE_BM_COMMAND_START_STOP;
channel->dmaing = true; channel->dmaing = true;
pci->write_io_8(device, channel->bus_master_base + ide_bm_command_reg, *(uint8 *)&command); pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
return B_OK; return B_OK;
} }
@@ -276,30 +274,31 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
{ {
pci_device_module_info *pci = channel->pci; pci_device_module_info *pci = channel->pci;
pci_device device = channel->device; pci_device device = channel->device;
ide_bm_command command; uint8 command;
ide_bm_status status, new_status; uint8 status, newStatus;
*(uint8 *)&command = pci->read_io_8(device, channel->bus_master_base + ide_bm_command_reg); command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
command.start_stop = 0; command &= ~IDE_BM_COMMAND_START_STOP;
channel->dmaing = false; channel->dmaing = false;
pci->write_io_8(device, channel->bus_master_base + ide_bm_command_reg, *(uint8 *)&command); pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
*(uint8 *)&status = pci->read_io_8(device, channel->bus_master_base + ide_bm_status_reg); status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
new_status = status; // reset interrupt/error flags
new_status.interrupt = 1; newStatus = status | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
new_status.error = 1; pci->write_io_8(device, channel->bus_master_base + IDE_BM_STATUS_REG,
newStatus);
pci->write_io_8(device, channel->bus_master_base + ide_bm_status_reg, if ((status & IDE_BM_STATUS_ERROR) != 0)
*(uint8 *)&new_status);
if (status.error)
return B_ERROR; return B_ERROR;
if (!status.interrupt) { if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
if (status.active) { if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer aborted" ); SHOW_ERROR0( 2, "DMA transfer aborted" );
return B_ERROR; return B_ERROR;
} }
@@ -308,7 +307,7 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
return B_DEV_DATA_UNDERRUN; return B_DEV_DATA_UNDERRUN;
} }
if (status.active) { if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer: buffer too large" ); SHOW_ERROR0( 2, "DMA transfer: buffer too large" );
return B_DEV_DATA_OVERRUN; return B_DEV_DATA_OVERRUN;
} }
@@ -473,7 +472,6 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
device_node_handle *node, bool supports_compatibility_mode) device_node_handle *node, bool supports_compatibility_mode)
{ {
uint8 api; uint8 api;
ide_bm_status status;
io_resource_handle resource_handles[3]; io_resource_handle resource_handles[3];
SHOW_FLOW0( 3, "" ); SHOW_FLOW0( 3, "" );
@@ -482,12 +480,12 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
api = pci->read_pci_config(pci_device, PCI_class_api, 1); api = pci->read_pci_config(pci_device, PCI_class_api, 1);
if (supports_compatibility_mode if (supports_compatibility_mode
&& is_primary && (api & ide_api_primary_native) == 0) { && is_primary && (api & IDE_API_PRIMARY_NATIVE) == 0) {
command_block_base = 0x1f0; command_block_base = 0x1f0;
control_block_base = 0x3f6; control_block_base = 0x3f6;
intnum = 14; intnum = 14;
} else if (supports_compatibility_mode } else if (supports_compatibility_mode
&& !is_primary && (api & ide_api_primary_native) == 0) { && !is_primary && (api & IDE_API_PRIMARY_NATIVE) == 0) {
command_block_base = 0x170; command_block_base = 0x170;
control_block_base = 0x376; control_block_base = 0x376;
intnum = 15; intnum = 15;
@@ -509,9 +507,10 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
if (supports_compatibility_mode) { if (supports_compatibility_mode) {
// read status of primary(!) channel to detect simplex // read status of primary(!) channel to detect simplex
*(uint8 *)&status = pci->read_io_8(pci_device, bus_master_base + ide_bm_status_reg); uint8 status = pci->read_io_8(pci_device, bus_master_base
+ IDE_BM_STATUS_REG);
if (status.simplex && !is_primary) { if (status & IDE_BM_STATUS_SIMPLEX_DMA && !is_primary) {
// in simplex mode, channels cannot operate independantly of each other; // in simplex mode, channels cannot operate independantly of each other;
// we simply disable bus mastering of second channel to satisfy that; // 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 // better were to use a controller lock, but this had to be done in the IDE
@@ -588,9 +587,10 @@ ide_adapter_uninit_controller(ide_adapter_controller_info *controller)
static void static void
ide_adapter_controller_removed(device_node_handle node, ide_adapter_controller_info *controller) ide_adapter_controller_removed(device_node_handle node,
ide_adapter_controller_info *controller)
{ {
SHOW_FLOW0( 3, "" ); SHOW_FLOW0(3, "");
if (controller != NULL) if (controller != NULL)
// disable access instantly; unit_device takes care of unregistering ioports // disable access instantly; unit_device takes care of unregistering ioports