#include <ata_adapter.h>
#include <KernelExport.h>
#include <stdlib.h>
#include <string.h>
#define DRIVER_PRETTY_NAME "Legacy SATA"
#define CONTROLLER_NAME DRIVER_PRETTY_NAME
#define CONTROLLER_MODULE_NAME "busses/ata/legacy_sata/driver_v1"
#define CHANNEL_MODULE_NAME "busses/ata/legacy_sata/channel/v1"
#define TRACE(a...) dprintf(DRIVER_PRETTY_NAME ": " a)
#define FLOW(a...) dprintf(DRIVER_PRETTY_NAME ": " a)
#define PCI_vendor_VIA 0x1106
#define PCI_device_VIA6420 0x3149
#define PCI_device_VIA6421 0x3249
#define PCI_device_VIA8237A 0x0591
#define PCI_vendor_ALI 0x10b9
#define PCI_device_ALI5289 0x5289
#define PCI_device_ALI5287 0x5287
#define PCI_device_ALI5281 0x5281
#define PCI_vendor_NVIDIA 0x10de
#define PCI_device_NF2PROS1 0x008e
#define PCI_device_NF3PROS1 0x00e3
#define PCI_device_NF3PROS2 0x00ee
#define PCI_device_MCP4S1 0x0036
#define PCI_device_MCP4S2 0x003e
#define PCI_device_CK804S1 0x0054
#define PCI_device_CK804S2 0x0055
#define PCI_device_MCP51S1 0x0266
#define PCI_device_MCP51S2 0x0267
#define PCI_device_MCP55S1 0x037e
#define PCI_device_MCP55S2 0x037f
#define PCI_device_MCP61S1 0x03e7
#define PCI_device_MCP61S2 0x03f6
#define PCI_device_MCP61S3 0x03f7
#define ID(v,d) (((v)<< 16) | (d))
static const char * const kChannelNames[] = {
"Primary Channel", "Secondary Channel",
"Tertiary Channel", "Quaternary Channel"
};
static ata_for_controller_interface* sATA;
static ata_adapter_interface* sATAAdapter;
static device_manager_info* sDeviceManager;
static float
controller_supports(device_node *parent)
{
uint16 vendor_id;
uint16 device_id;
status_t res;
const char *bus = NULL;
if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK)
return B_ERROR;
if (strcmp(bus, "pci") != 0) {
return B_ERROR;
}
if ((res = sDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendor_id, false)) != B_OK
|| (res = sDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &device_id, false)) != B_OK) {
return res;
}
switch (ID(vendor_id, device_id)) {
case ID(PCI_vendor_VIA, PCI_device_VIA6420):
case ID(PCI_vendor_VIA, PCI_device_VIA6421):
case ID(PCI_vendor_VIA, PCI_device_VIA8237A):
break;
case ID(PCI_vendor_ALI, PCI_device_ALI5281):
case ID(PCI_vendor_ALI, PCI_device_ALI5287):
case ID(PCI_vendor_ALI, PCI_device_ALI5289):
break;
case ID(PCI_vendor_NVIDIA, PCI_device_NF2PROS1):
case ID(PCI_vendor_NVIDIA, PCI_device_NF3PROS1):
case ID(PCI_vendor_NVIDIA, PCI_device_NF3PROS2):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP4S1):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP4S2):
case ID(PCI_vendor_NVIDIA, PCI_device_CK804S1):
case ID(PCI_vendor_NVIDIA, PCI_device_CK804S2):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP51S1):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP51S2):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP55S1):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP55S2):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP61S1):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP61S2):
case ID(PCI_vendor_NVIDIA, PCI_device_MCP61S3):
break;
default:
return 0.0f;
}
TRACE("controller found! vendor 0x%04x, device 0x%04x\n", vendor_id, device_id);
return 0.8f;
}
static status_t
controller_probe(device_node *parent)
{
device_node *controller_node;
device_node *channels[4];
uint16 command_block_base[4];
uint16 control_block_base[4];
pci_device_module_info *pci;
uint8 num_channels = 2;
uint32 bus_master_base;
pci_device *device = NULL;
uint16 device_id;
uint16 vendor_id;
uint8 int_num;
status_t res;
uint8 index;
TRACE("controller_probe\n");
sDeviceManager->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
device_id = pci->read_pci_config(device, PCI_device_id, 2);
vendor_id = pci->read_pci_config(device, PCI_vendor_id, 2);
int_num = pci->read_pci_config(device, PCI_interrupt_line, 1);
bus_master_base = pci->read_pci_config(device, PCI_base_registers + 16, 4);
command_block_base[0] = pci->read_pci_config(device, PCI_base_registers + 0, 4);
control_block_base[0] = pci->read_pci_config(device, PCI_base_registers + 4, 4);
command_block_base[1] = pci->read_pci_config(device, PCI_base_registers + 8, 4);
control_block_base[1] = pci->read_pci_config(device, PCI_base_registers + 12, 4);
pci->write_pci_config(device, PCI_command, 2,
pci->read_pci_config(device, PCI_command, 2) & ~PCI_command_int_disable);
if (vendor_id == PCI_vendor_NVIDIA) {
pci->write_pci_config(device, 0x50, 1,
pci->read_pci_config(device, 0x50, 1) | 0x04);
}
switch (ID(vendor_id, device_id)) {
case ID(PCI_vendor_VIA,PCI_device_VIA6421):
num_channels = 4;
command_block_base[0] = pci->read_pci_config(device, PCI_base_registers + 0, 4);
control_block_base[0] = command_block_base[0] + 8;
command_block_base[1] = pci->read_pci_config(device, PCI_base_registers + 4, 4);
control_block_base[1] = command_block_base[1] + 8;
command_block_base[2] = pci->read_pci_config(device, PCI_base_registers + 8, 4);
control_block_base[2] = command_block_base[2] + 8;
command_block_base[3] = pci->read_pci_config(device, PCI_base_registers + 12, 4);
control_block_base[3] = command_block_base[3] + 8;
break;
case ID(PCI_vendor_ALI, PCI_device_ALI5287):
num_channels = 4;
command_block_base[2] = pci->read_pci_config(device, PCI_base_registers + 0, 4) + 8;
control_block_base[2] = pci->read_pci_config(device, PCI_base_registers + 4, 4) + 4;
command_block_base[3] = pci->read_pci_config(device, PCI_base_registers + 8, 4) + 8;
control_block_base[3] = pci->read_pci_config(device, PCI_base_registers + 12, 4) + 4;
break;
}
bus_master_base &= PCI_address_io_mask;
for (index = 0; index < num_channels; index++) {
command_block_base[index] &= PCI_address_io_mask;
control_block_base[index] &= PCI_address_io_mask;
}
res = sATAAdapter->detect_controller(pci, device, parent, bus_master_base,
CONTROLLER_MODULE_NAME, "" , CONTROLLER_NAME, true,
true, 1, 0xffff, 0x10000, &controller_node);
if (res != B_OK)
goto err;
if (controller_node == NULL) {
res = B_IO_ERROR;
goto err;
}
for (index = 0; index < num_channels; index++) {
res = sATAAdapter->detect_channel(pci, device, controller_node, CHANNEL_MODULE_NAME,
true, command_block_base[index], control_block_base[index], bus_master_base,
int_num, index, kChannelNames[index], &channels[index], false);
dprintf("%s: %s\n", kChannelNames[index], strerror(res));
}
TRACE("controller_probe success\n");
return B_OK;
err:
TRACE("controller_probe failed (%s)\n", strerror(res));
return res;
}
static status_t
controller_init(device_node *node, void **controller_cookie)
{
return sATAAdapter->init_controller(
node, (ata_adapter_controller_info**)controller_cookie,
sizeof(ata_adapter_controller_info));
}
static void
controller_uninit(void *controller_cookie)
{
sATAAdapter->uninit_controller((ata_adapter_controller_info*)controller_cookie);
}
static void
controller_removed(void *controller_cookie)
{
sATAAdapter->controller_removed((ata_adapter_controller_info*)controller_cookie);
}
static status_t
channel_init(device_node *node, void **channel_cookie)
{
return sATAAdapter->init_channel(node,
(ata_adapter_channel_info**)channel_cookie,
sizeof(ata_adapter_channel_info), sATAAdapter->inthand);
}
static void
channel_uninit(void *channel_cookie)
{
sATAAdapter->uninit_channel((ata_adapter_channel_info*)channel_cookie);
}
static void
channel_removed(void *channel_cookie)
{
sATAAdapter->channel_removed((ata_adapter_channel_info*)channel_cookie);
}
static void
channel_set(void *channel_cookie, ata_channel channel)
{
sATAAdapter->set_channel((ata_adapter_channel_info*)channel_cookie,
channel);
}
static status_t
task_file_write(void *channel_cookie, ata_task_file *tf, ata_reg_mask mask)
{
return sATAAdapter->write_command_block_regs(
(ata_adapter_channel_info*)channel_cookie, tf, mask);
}
static status_t
task_file_read(void *channel_cookie, ata_task_file *tf, ata_reg_mask mask)
{
return sATAAdapter->read_command_block_regs(
(ata_adapter_channel_info*)channel_cookie, tf, mask);
}
static uint8
altstatus_read(void *channel_cookie)
{
return sATAAdapter->get_altstatus(
(ata_adapter_channel_info*)channel_cookie);
}
static status_t
device_control_write(void *channel_cookie, uint8 val)
{
return sATAAdapter->write_device_control(
(ata_adapter_channel_info*)channel_cookie, val);
}
static status_t
pio_write(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return sATAAdapter->write_pio((ata_adapter_channel_info*)channel_cookie,
data, count, force_16bit);
}
static status_t
pio_read(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return sATAAdapter->read_pio((ata_adapter_channel_info*)channel_cookie,
data, count, force_16bit);
}
static status_t
dma_prepare(void *channel_cookie, const physical_entry *sg_list,
size_t sg_list_count, bool write)
{
return sATAAdapter->prepare_dma((ata_adapter_channel_info*)channel_cookie,
sg_list, sg_list_count, write);
}
static status_t
dma_start(void *channel_cookie)
{
return sATAAdapter->start_dma((ata_adapter_channel_info*)channel_cookie);
}
static status_t
dma_finish(void *channel_cookie)
{
return sATAAdapter->finish_dma((ata_adapter_channel_info*)channel_cookie);
}
module_dependency module_dependencies[] = {
{ ATA_FOR_CONTROLLER_MODULE_NAME, (module_info **)&sATA },
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
{ ATA_ADAPTER_MODULE_NAME, (module_info **)&sATAAdapter },
{}
};
static ata_controller_interface sChannelInterface = {
{
{
CHANNEL_MODULE_NAME,
0,
NULL
},
NULL,
NULL,
channel_init,
channel_uninit,
NULL,
NULL,
channel_removed,
},
channel_set,
task_file_write,
task_file_read,
altstatus_read,
device_control_write,
pio_write,
pio_read,
dma_prepare,
dma_start,
dma_finish,
};
static driver_module_info sControllerInterface = {
{
CONTROLLER_MODULE_NAME,
0,
NULL
},
controller_supports,
controller_probe,
controller_init,
controller_uninit,
NULL,
NULL,
controller_removed,
};
module_info *modules[] = {
(module_info *)&sControllerInterface,
(module_info *)&sChannelInterface,
NULL
};