implemented channel init and uninit

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18797 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen
2006-09-10 21:19:43 +00:00
parent cc51ac4772
commit 59a3c4800b
@@ -59,12 +59,16 @@ static const struct {
#define SI_MASK_2PORT ((1 << 22) | (1 << 23))
#define SI_MASK_4PORT ((1 << 22) | (1 << 23) | (1 << 24) | (1 << 25))
struct channel_data;
typedef struct {
typedef struct controller_data {
pci_device_module_info *pci;
pci_device device;
device_node_handle node;
struct channel_data *channel[4]; // XXX only for interrupt workaround
int channel_count; // XXX only for interrupt workaround
uint32 asic_index;
uint32 int_num;
@@ -77,11 +81,12 @@ typedef struct {
} controller_data;
typedef struct {
typedef struct channel_data {
pci_device_module_info *pci;
device_node_handle node;
pci_device device;
ide_channel ide_channel;
volatile uint8 * task_file;
volatile uint8 * control_block;
@@ -104,6 +109,7 @@ static ide_for_controller_interface * ide;
static ide_adapter_interface * ide_adapter;
static device_manager_info * dm;
static status_t device_control_write(void *channel_cookie, uint8 val);
static int32 handle_interrupt(void *arg);
@@ -275,6 +281,8 @@ controller_init(device_node_handle node, void *user_cookie, void **controller_co
if (!controller)
return B_NO_MEMORY;
FLOW("controller %p\n", controller);
mmio_area = map_physical_memory("Silicon Image SATA regs", (void *)mmio_base,
asic_data[asic_index].mmio_bar_size,
B_ANY_KERNEL_ADDRESS, 0, (void **)&mmio_addr);
@@ -305,6 +313,10 @@ controller_init(device_node_handle node, void *user_cookie, void **controller_co
controller->mmio_addr = mmio_addr;
controller->lost = 0;
controller->channel_count = asic_data[asic_index].channel_count;
for (i = 0; i < asic_data[asic_index].channel_count; i++)
controller->channel[i] = 0;
if (asic_index == ASIC_SI3114) {
// I put a magic spell on you
temp = *(volatile uint32 *)mmio_addr + SI_BMDMA2;
@@ -374,37 +386,76 @@ static status_t
channel_init(device_node_handle node, void *user_cookie, void **channel_cookie)
{
ide_channel ide_channel = user_cookie;
controller_data *controller;
channel_data *channel;
physical_entry pe[1];
size_t prdt_size;
uint32 chan_index;
TRACE("channel_init enter\n");
channel = malloc(sizeof(channel_data));
if (!channel)
return B_NO_MEMORY;
TRACE("channel %p\n", channel);
if (dm->get_attr_uint32(node, "silicon_image_3112/chan_index", &chan_index, false) != B_OK)
return B_ERROR;
TRACE("channel_index %ld", chan_index);
TRACE("channel name: %s\n", controller_channel_data[chan_index].name);
if (dm->init_driver(dm->get_parent(node), NULL, NULL, (void **)&controller) != B_OK)
return B_ERROR;
TRACE("controller %p\n", controller);
TRACE("mmio_addr %p\n", (void *)controller->mmio_addr);
// PRDT must be contiguous, dword-aligned and must not cross 64K boundary
prdt_size = (IDE_ADAPTER_MAX_SG_COUNT * sizeof(prd_entry) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1);
channel->prd_area = create_area("prd", (void **)&channel->prdt, B_ANY_KERNEL_ADDRESS, prdt_size, B_FULL_LOCK | B_CONTIGUOUS, 0);
if (channel->prd_area < B_OK) {
TRACE("creating prd_area failed\n");
goto err2;
}
get_memory_map(channel->prdt, prdt_size, pe, 1);
channel->prdt_phys = (void *)(uint32)pe[0].address;
channel->pci = controller->pci;
channel->device = controller->device;
channel->node = node;
channel->ide_channel = ide_channel;
channel->task_file = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].cmd + 1);
channel->control_block = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].ctl);
channel->command_block = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].cmd);
channel->dev_ctrl = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].ctl);
channel->bm_prdt_address = (volatile uint32 *)(controller->mmio_addr + controller_channel_data[chan_index].bmdma + ide_bm_prdt_address);
channel->bm_status_reg = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].bmdma + ide_bm_status_reg);
channel->bm_command_reg = (volatile uint8 *)(controller->mmio_addr + controller_channel_data[chan_index].bmdma + ide_bm_command_reg);
channel->lost = 0;
channel->dma_active = 0;
/*
channel->
pci_device_module_info *pci;
device_node_handle node;
pci_device device;
controller->channel[chan_index] = channel;
volatile uint8 *task_file (volatile uint8 *)(channel->mmio_addr + channel->command_block_base + 1);
volatile uint8 *control_block (volatile uint8 *)(channel->mmio_addr + channel->control_block_base);
volatile uint8 *command_block
volatile uint8 *dev_ctrl
volatile uint32 * bm_prdt_address = (volatile uint32 *)(channel->mmio_addr + channel->bus_master_base + ata_bm_prdt_address);
volatile uint8 * bm_status_reg = (volatile uint8 *)(channel->mmio_addr + channel->bus_master_base + ata_bm_status_reg);
volatile uint8 * bm_command_reg = (volatile uint8 *)(channel->mmio_addr + channel->bus_master_base + ata_bm_command_reg);
uint32 lost;
prd_entry *prdt;
area_id prd_area;
prd_entry *prdt;
uint32 dma_active;
*/
// enable interrupts so the channel is ready to run
device_control_write(channel, ide_devctrl_bit3);
*channel_cookie = channel;
TRACE("channel_init leave\n");
return B_OK;
err3:
delete_area(channel->prd_area);
err2:
dm->uninit_driver(dm->get_parent(node));
err:
free(channel);
return B_ERROR;
}
@@ -412,7 +463,20 @@ static status_t
channel_uninit(void *channel_cookie)
{
channel_data *channel = channel_cookie;
return B_ERROR;
// disable IRQs
device_control_write(channel, ide_devctrl_bit3 | ide_devctrl_nien);
// catch spurious interrupt
// (some controllers generate an IRQ when you _disable_ interrupts,
// they are delayed by less then 40 µs, so 1 ms is safe)
snooze(1000);
dm->uninit_driver(dm->get_parent(channel->node));
delete_area(channel->prd_area);
free(channel);
return B_OK;
}
@@ -420,6 +484,7 @@ static void
channel_removed(device_node_handle node, void *channel_cookie)
{
channel_data *channel = channel_cookie;
channel->lost = 1;
}
@@ -689,32 +754,30 @@ static int32
handle_interrupt(void *arg)
{
controller_data *controller = arg;
pci_device_module_info *pci = controller->pci;
pci_device device = controller->device;
ide_bm_status bm_status;
uint8 status;
int i;
FLOW("handle_interrupt\n");
return B_UNHANDLED_INTERRUPT;
/*
if (channel->lost)
return B_UNHANDLED_INTERRUPT;
// add test whether this is really our IRQ
if (channel->dma_active) {
// in DMA mode, there is a safe test
// in PIO mode, this doesn't work
*(uint8 *)&bm_status = *channel->bm_status_reg;
if (!bm_status.interrupt)
return B_UNHANDLED_INTERRUPT;
// XXX This is bogus
for (i = 0; i < controller->channel_count; i++) {
channel_data *channel = controller->channel[i];
if (!channel || channel->lost)
continue;
if (channel->dma_active) {
*(uint8 *)&bm_status = *channel->bm_status_reg;
if (!bm_status.interrupt)
continue;
}
// acknowledge IRQ
status = *(channel->command_block + 7);
return ide->irq_handler(channel->ide_channel, status);
}
// acknowledge IRQ
status = *(channel->command_block + 7);
return channel->ata->irq_handler(channel->ata_bus, status);
*/
return B_UNHANDLED_INTERRUPT;
}