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. * Copyright 2002-04, Thomas Kurschel. All rights reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
@@ -11,7 +11,7 @@
IDE adapter library IDE adapter library
Module to simplify writing an IDE adapter driver. Module to simplify writing an IDE adapter driver.
The interface is not very abstract, i.e. the actual driver is The interface is not very abstract, i.e. the actual driver is
free to access any controller or channel data of this library. free to access any controller or channel data of this library.
*/ */
@@ -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