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
+20 -34
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.
@@ -11,7 +11,7 @@
IDE adapter library
Module to simplify writing an IDE adapter driver.
The interface is not very abstract, i.e. the actual driver is
free to access any controller or channel data of this library.
*/
@@ -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