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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user