added controller probing and channel publishing
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18787 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,13 +6,57 @@
|
|||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <device_manager.h>
|
||||||
#include <bus/ide/ide_adapter.h>
|
#include <bus/ide/ide_adapter.h>
|
||||||
#include <block_io.h>
|
#include <block_io.h>
|
||||||
|
|
||||||
|
#define TRACE(a...) dprintf("si-3112 " a)
|
||||||
|
|
||||||
|
|
||||||
|
#define DRIVER_PRETTY_NAME "Silicon Image SATA"
|
||||||
|
#define CONTROLLER_DRIVER "silicon_image_3112"
|
||||||
|
#define CONTROLLER_NAME DRIVER_PRETTY_NAME
|
||||||
#define CONTROLLER_MODULE_NAME "busses/ide/silicon_image_3112/device_v1"
|
#define CONTROLLER_MODULE_NAME "busses/ide/silicon_image_3112/device_v1"
|
||||||
#define CHANNEL_MODULE_NAME "busses/ide/silicon_image_3112/channel/v1"
|
#define CHANNEL_MODULE_NAME "busses/ide/silicon_image_3112/channel/v1"
|
||||||
|
|
||||||
|
enum asic_type {
|
||||||
|
ASIC_SI3112 = 0,
|
||||||
|
ASIC_SI3114 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *adapter_asic_names[] = {
|
||||||
|
"si3112",
|
||||||
|
"si3114",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
uint16 channel_count;
|
||||||
|
uint32 mmio_bar_size;
|
||||||
|
} asic_data[2] = {
|
||||||
|
{ 2, 0x200 },
|
||||||
|
{ 4, 0x400 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
uint16 cmd;
|
||||||
|
uint16 ctl;
|
||||||
|
uint16 bmdma;
|
||||||
|
uint16 sien;
|
||||||
|
const char *name;
|
||||||
|
} controller_channel_data[] = {
|
||||||
|
{ 0x80, 0x8A, 0x00, 0x148, "Primary Channel" },
|
||||||
|
{ 0xC0, 0xCA, 0x08, 0x1C8, "Secondary Channel" },
|
||||||
|
{ 0x280, 0x28A, 0x200, 0x348, "Tertiary Channel" },
|
||||||
|
{ 0x2C0, 0x2CA, 0x208, 0x3C8, "Quaternary Channel" },
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SI_SYSCFG 0x48
|
||||||
|
#define SI_BMDMA2 0x200
|
||||||
|
#define SI_INT_STEERING 0x02
|
||||||
|
#define SI_MASK_2PORT ((1 << 22) | (1 << 23))
|
||||||
|
#define SI_MASK_4PORT ((1 << 22) | (1 << 23) | (1 << 24) | (1 << 25))
|
||||||
|
|
||||||
|
|
||||||
static ide_for_controller_interface * ide;
|
static ide_for_controller_interface * ide;
|
||||||
static ide_adapter_interface * ide_adapter;
|
static ide_adapter_interface * ide_adapter;
|
||||||
@@ -22,10 +66,142 @@ static device_manager_info * dm;
|
|||||||
static status_t
|
static status_t
|
||||||
controller_probe(device_node_handle parent)
|
controller_probe(device_node_handle parent)
|
||||||
{
|
{
|
||||||
|
pci_device device;
|
||||||
|
pci_device_module_info *pci;
|
||||||
|
device_node_handle controller_node;
|
||||||
|
uint32 mmio_base;
|
||||||
|
uint16 device_id;
|
||||||
|
uint8 int_num;
|
||||||
|
int asic_index;
|
||||||
|
int chan_index;
|
||||||
|
status_t res;
|
||||||
|
|
||||||
|
TRACE("controller_probe\n");
|
||||||
|
|
||||||
|
if (dm->init_driver(parent, NULL, (driver_module_info **)&pci, (void **)&device) != B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
device_id = pci->read_pci_config(device, PCI_device_id, 2);
|
||||||
|
int_num = pci->read_pci_config(device, PCI_interrupt_line, 1);
|
||||||
|
mmio_base = pci->read_pci_config(device, PCI_base_registers + 20, 4);
|
||||||
|
mmio_base &= PCI_address_io_mask;
|
||||||
|
|
||||||
|
switch (device_id) {
|
||||||
|
case 0x3112:
|
||||||
|
asic_index = ASIC_SI3112;
|
||||||
|
break;
|
||||||
|
case 0x3114:
|
||||||
|
asic_index = ASIC_SI3114;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TRACE("unsupported asic\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mmio_base) {
|
||||||
|
TRACE("mmio not configured\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int_num == 0 || int_num == 0xff) {
|
||||||
|
TRACE("irq not configured\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
io_resource_handle resource_handles[2];
|
||||||
|
io_resource resources[2] = {
|
||||||
|
{ IO_MEM, mmio_base, asic_data[asic_index].mmio_bar_size },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dm->acquire_io_resources(resources, resource_handles) != B_OK) {
|
||||||
|
TRACE("acquire_io_resources failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
|
||||||
|
device_attr controller_attrs[] = {
|
||||||
|
// info about ourself and our consumer
|
||||||
|
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: CONTROLLER_DRIVER }},
|
||||||
|
|
||||||
|
// properties of this controller for ide bus manager
|
||||||
|
// there are always max. 2 devices
|
||||||
|
// (unless this is a Compact Flash Card with a built-in IDE controller,
|
||||||
|
// which has exactly 1 device)
|
||||||
|
{ IDE_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { ui8: asic_data[asic_index].channel_count }},
|
||||||
|
// of course we can DMA
|
||||||
|
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: true }},
|
||||||
|
// command queuing always works
|
||||||
|
{ IDE_CONTROLLER_CAN_CQ_ITEM, B_UINT8_TYPE, { ui8: true }},
|
||||||
|
// choose any name here
|
||||||
|
{ IDE_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { string: CONTROLLER_NAME }},
|
||||||
|
|
||||||
|
// DMA properties
|
||||||
|
// data must be word-aligned;
|
||||||
|
// warning: some controllers are more picky!
|
||||||
|
{ B_BLOCK_DEVICE_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1}},
|
||||||
|
// one S/G block must not cross 64K boundary
|
||||||
|
{ B_BLOCK_DEVICE_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
|
||||||
|
// max size of S/G block is 16 bits with zero being 64K
|
||||||
|
{ B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, B_UINT32_TYPE, { ui32: 0x10000 }},
|
||||||
|
// see definition of MAX_SG_COUNT
|
||||||
|
{ B_BLOCK_DEVICE_MAX_SG_BLOCKS, B_UINT32_TYPE, { ui32: IDE_ADAPTER_MAX_SG_COUNT }},
|
||||||
|
|
||||||
|
// private data to find controller
|
||||||
|
{ "silicon_image_3112/asic_index", B_UINT32_TYPE, { ui32: asic_index }},
|
||||||
|
{ "silicon_image_3112/int_num", B_UINT32_TYPE, { ui32: int_num }},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
TRACE("publishing controller");
|
||||||
|
|
||||||
|
res = dm->register_device(parent, controller_attrs, resource_handles, &controller_node);
|
||||||
|
if (res != B_OK || controller_node == NULL) {
|
||||||
|
TRACE("register controller failed\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// publish channel nodes
|
||||||
|
for (chan_index = 0; chan_index < asic_data[asic_index].channel_count; chan_index++) {
|
||||||
|
device_attr channel_attrs[] = {
|
||||||
|
// info about ourself and our consumer
|
||||||
|
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: CHANNEL_MODULE_NAME }},
|
||||||
|
{ B_DRIVER_PRETTY_NAME, B_STRING_TYPE, { string: DRIVER_PRETTY_NAME }},
|
||||||
|
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: controller_channel_data[chan_index].name }},
|
||||||
|
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
|
||||||
|
|
||||||
|
// private data to identify channel
|
||||||
|
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: true }},
|
||||||
|
{ "silicon_image_3112/chan_index", B_UINT32_TYPE, { ui32: chan_index }},
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
device_node_handle channel_node;
|
||||||
|
|
||||||
|
TRACE("publishing %s\n", controller_channel_data[chan_index].name );
|
||||||
|
|
||||||
|
dm->register_device(controller_node, channel_attrs, resource_handles, &channel_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dm->uninit_driver(parent);
|
||||||
|
|
||||||
|
TRACE("controller_probe success\n");
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err:
|
||||||
|
dm->uninit_driver(parent);
|
||||||
|
TRACE("controller_probe failed\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
controller_init(device_node_handle node, void *user_cookie, void **_cookie)
|
controller_init(device_node_handle node, void *user_cookie, void **_cookie)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user