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.
*
* Distributed under the terms of the MIT License.
@@ -36,47 +36,33 @@ typedef struct 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
typedef struct ide_bm_command {
LBITFIELD8_4(
start_stop : 1, // start BM by changing from 0 to 1;
// stop BM by changing from 1 to 0
res0_1 : 2,
from_device : 1, // true - read from device, false - write to device
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;
// IDE bus master status register
#define IDE_BM_STATUS_ACTIVE 0x01
#define IDE_BM_STATUS_ERROR 0x02
#define IDE_BM_STATUS_INTERRUPT 0x04
#define IDE_BM_STATUS_MASTER_DMA 0x20
#define IDE_BM_STATUS_SLAVE_DMA 0x40
#define IDE_BM_STATUS_SIMPLEX_DMA 0x80
// offset of bus master registers
enum {
ide_bm_command_reg = 0, // see ide_bm_command
ide_bm_status_reg = 2, // see ide_bm_status
ide_bm_prdt_address = 4 // offset of PRDT register; content must be dword-aligned
IDE_BM_COMMAND_REG = 0,
IDE_BM_STATUS_REG = 2,
IDE_BM_PRDT_ADDRESS = 4
// offset of PRDT register; content must be dword-aligned
};
// bit mask in class_api of PCI configuration
// (for adapters that can run in compatability mode)
enum {
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_secondary_native = 4, // secondary channel is in native mode
ide_api_secondary_fixed = 8 // secondary channel can be switched to 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_SECONDARY_NATIVE = 4, // secondary channel is in 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;
pci_device_module_info *pci = channel->pci;
pci_device device = channel->device;
ide_bm_status bm_status;
uint8 status;
SHOW_FLOW0( 3, "" );
SHOW_FLOW0(3, "");
if (channel->lost)
return B_UNHANDLED_INTERRUPT;
@@ -192,10 +191,9 @@ ide_adapter_inthand(void *arg)
if (channel->dmaing) {
// in DMA mode, there is a safe test
// in PIO mode, this don't work
*(uint8 *)&bm_status = pci->read_io_8(device,
channel->bus_master_base + ide_bm_status_reg);
if (!bm_status.interrupt)
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
if ((status & IDE_BM_STATUS_INTERRUPT) == 0)
return B_UNHANDLED_INTERRUPT;
}
@@ -207,47 +205,45 @@ ide_adapter_inthand(void *arg)
static status_t
ide_adapter_prepare_dma(ide_adapter_channel_info *channel, const physical_entry *sg_list,
size_t sg_list_count, bool to_device)
ide_adapter_prepare_dma(ide_adapter_channel_info *channel,
const physical_entry *sgList, size_t sgListCount, bool writeToDevice)
{
pci_device_module_info *pci = channel->pci;
pci_device device = channel->device;
ide_bm_command command;
ide_bm_status status;
uint8 command;
uint8 status;
prd_entry *prd = channel->prdt;
int i;
for (i = sg_list_count - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sg_list) {
prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, sg_list->address));
for (i = sgListCount - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sgList) {
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
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;
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->read_io_32(device, channel->bus_master_base + ide_bm_prdt_address) & 3)
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)
| (B_HOST_TO_LENDIAN_INT32(pci->ram_address(device, (void *)channel->prdt_phys)) & ~3));
// reset interrupt and error signal
*(uint8 *)&status = pci->read_io_8(device,
channel->bus_master_base + ide_bm_status_reg);
status.interrupt = 1;
status.error = 1;
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG) | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
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
*(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);
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, *(uint8 *)&command);
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
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 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;
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;
}
@@ -276,30 +274,31 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
{
pci_device_module_info *pci = channel->pci;
pci_device device = channel->device;
ide_bm_command command;
ide_bm_status status, new_status;
uint8 command;
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;
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;
new_status.interrupt = 1;
new_status.error = 1;
// reset interrupt/error flags
newStatus = status | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
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,
*(uint8 *)&new_status);
if (status.error)
if ((status & IDE_BM_STATUS_ERROR) != 0)
return B_ERROR;
if (!status.interrupt) {
if (status.active) {
if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer aborted" );
return B_ERROR;
}
@@ -308,7 +307,7 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
return B_DEV_DATA_UNDERRUN;
}
if (status.active) {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer: buffer too large" );
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)
{
uint8 api;
ide_bm_status status;
io_resource_handle resource_handles[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);
if (supports_compatibility_mode
&& is_primary && (api & ide_api_primary_native) == 0) {
&& is_primary && (api & IDE_API_PRIMARY_NATIVE) == 0) {
command_block_base = 0x1f0;
control_block_base = 0x3f6;
intnum = 14;
} 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;
control_block_base = 0x376;
intnum = 15;
@@ -509,9 +507,10 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
if (supports_compatibility_mode) {
// 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;
// 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
@@ -588,9 +587,10 @@ ide_adapter_uninit_controller(ide_adapter_controller_info *controller)
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)
// disable access instantly; unit_device takes care of unregistering ioports