Added a generic PCI IDE driver, a specialised one for the Promise TX chips,
and an ISA IDE driver. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7774 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
386c5ff7f6
commit
b7c4739649
@ -1,3 +1,4 @@
|
||||
SubDir OBOS_TOP src add-ons kernel busses ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons kernel busses ide ;
|
||||
SubInclude OBOS_TOP src add-ons kernel busses usb ;
|
||||
|
5
src/add-ons/kernel/busses/ide/Jamfile
Normal file
5
src/add-ons/kernel/busses/ide/Jamfile
Normal file
@ -0,0 +1,5 @@
|
||||
SubDir OBOS_TOP src add-ons kernel busses ide ;
|
||||
|
||||
SubInclude OBOS_TOP src add-ons kernel busses ide generic_ide_pci ;
|
||||
SubInclude OBOS_TOP src add-ons kernel busses ide ide_isa ;
|
||||
SubInclude OBOS_TOP src add-ons kernel busses ide promise_tx2 ;
|
7
src/add-ons/kernel/busses/ide/generic_ide_pci/Jamfile
Normal file
7
src/add-ons/kernel/busses/ide/generic_ide_pci/Jamfile
Normal file
@ -0,0 +1,7 @@
|
||||
SubDir OBOS_TOP src add-ons kernel busses ide generic_ide_pci ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon generic_ide_pci : kernel busses ide :
|
||||
generic_ide_pci.c
|
||||
;
|
221
src/add-ons/kernel/busses/ide/generic_ide_pci/generic_ide_pci.c
Normal file
221
src/add-ons/kernel/busses/ide/generic_ide_pci/generic_ide_pci.c
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Generic IDE PCI controller driver
|
||||
|
||||
Generic PCI bus mastering IDE driver.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bus/ide/ide_adapter.h>
|
||||
|
||||
#define debug_level_flow 0
|
||||
#define debug_level_error 3
|
||||
#define debug_level_info 3
|
||||
|
||||
#define DEBUG_MSG_PREFIX "GENERIC IDE PCI -- "
|
||||
|
||||
#include "wrapper.h"
|
||||
|
||||
#define GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ide/generic_ide_pci/" PCI_DEVICE_TYPE_NAME
|
||||
#define GENERIC_IDE_PCI_CHANNEL_MODULE_NAME "busses/ide/generic_ide_pci/channel/v1"
|
||||
|
||||
#define IDE_PCI_CONTROLLER_TYPE_NAME "ide pci controller"
|
||||
|
||||
ide_for_controller_interface *ide;
|
||||
static ide_adapter_interface *ide_adapter;
|
||||
device_manager_info *pnp;
|
||||
|
||||
|
||||
static int write_command_block_regs( ide_adapter_channel_info *channel, ide_task_file *tf,
|
||||
ide_reg_mask mask )
|
||||
{
|
||||
return ide_adapter->write_command_block_regs( channel, tf, mask );
|
||||
}
|
||||
|
||||
static status_t read_command_block_regs( ide_adapter_channel_info *channel, ide_task_file *tf,
|
||||
ide_reg_mask mask )
|
||||
{
|
||||
return ide_adapter->read_command_block_regs( channel, tf, mask );
|
||||
}
|
||||
|
||||
static uint8 get_altstatus( ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->get_altstatus( channel );
|
||||
}
|
||||
|
||||
static status_t write_device_control( ide_adapter_channel_info *channel, uint8 val )
|
||||
{
|
||||
return ide_adapter->write_device_control( channel, val );
|
||||
}
|
||||
|
||||
static status_t write_pio( ide_adapter_channel_info *channel, uint16 *data, int count,
|
||||
bool force_16bit )
|
||||
{
|
||||
return ide_adapter->write_pio( channel, data, count, force_16bit );
|
||||
}
|
||||
|
||||
static status_t read_pio( ide_adapter_channel_info *channel, uint16 *data, int count,
|
||||
bool force_16bit )
|
||||
{
|
||||
return ide_adapter->read_pio( channel, data, count, force_16bit );
|
||||
}
|
||||
|
||||
static status_t prepare_dma( ide_adapter_channel_info *channel,
|
||||
const physical_entry *sg_list, size_t sg_list_count,
|
||||
bool to_device )
|
||||
{
|
||||
return ide_adapter->prepare_dma( channel, sg_list, sg_list_count, to_device );
|
||||
}
|
||||
|
||||
static status_t start_dma( ide_adapter_channel_info *channel )
|
||||
{
|
||||
return ide_adapter->start_dma( channel );
|
||||
}
|
||||
|
||||
|
||||
static status_t finish_dma( ide_adapter_channel_info *channel )
|
||||
{
|
||||
return ide_adapter->finish_dma( channel );
|
||||
}
|
||||
|
||||
|
||||
static status_t init_channel( pnp_node_handle node, ide_channel ide_channel,
|
||||
ide_adapter_channel_info **cookie )
|
||||
{
|
||||
return ide_adapter->init_channel( node, ide_channel, cookie,
|
||||
sizeof( ide_adapter_channel_info ), ide_adapter->inthand );
|
||||
}
|
||||
|
||||
|
||||
static status_t uninit_channel( ide_adapter_channel_info *channel )
|
||||
{
|
||||
return ide_adapter->uninit_channel( channel );
|
||||
}
|
||||
|
||||
|
||||
static void channel_removed( pnp_node_handle node, ide_adapter_channel_info *channel )
|
||||
{
|
||||
return ide_adapter->channel_removed( node, channel );
|
||||
}
|
||||
|
||||
|
||||
static status_t init_controller( pnp_node_handle node, void *user_cookie,
|
||||
ide_adapter_controller_info **cookie )
|
||||
{
|
||||
return ide_adapter->init_controller( node, user_cookie, cookie,
|
||||
sizeof( ide_adapter_controller_info ));
|
||||
}
|
||||
|
||||
|
||||
static status_t uninit_controller( ide_adapter_controller_info *controller )
|
||||
{
|
||||
return ide_adapter->uninit_controller( controller );
|
||||
}
|
||||
|
||||
|
||||
static void controller_removed(
|
||||
pnp_node_handle node, ide_adapter_controller_info *controller )
|
||||
{
|
||||
return ide_adapter->controller_removed( node, controller );
|
||||
}
|
||||
|
||||
|
||||
static status_t probe_controller( pnp_node_handle parent )
|
||||
{
|
||||
return ide_adapter->probe_controller( parent,
|
||||
GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME, "generic_ide_pci",
|
||||
"Generic IDE PCI Controller",
|
||||
GENERIC_IDE_PCI_CHANNEL_MODULE_NAME,
|
||||
true,
|
||||
true, // assume that command queuing works
|
||||
1, // assume 16 bit alignment is enough
|
||||
0xffff, // boundary is on 64k according to spec
|
||||
0x10000, // up to 64k per S/G block according to spec
|
||||
true // by default, compatibility mode is used
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
module_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
|
||||
{ DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
|
||||
{ IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// exported interface
|
||||
static ide_controller_interface channel_interface = {
|
||||
{
|
||||
{
|
||||
GENERIC_IDE_PCI_CHANNEL_MODULE_NAME,
|
||||
0,
|
||||
module_std_ops
|
||||
},
|
||||
|
||||
(status_t (*)( pnp_node_handle , void *, void ** )) init_channel,
|
||||
(status_t (*)( void * )) uninit_channel,
|
||||
NULL,
|
||||
(void (*)( pnp_node_handle , void * )) channel_removed
|
||||
},
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &write_command_block_regs,
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &read_command_block_regs,
|
||||
|
||||
(uint8 (*)(ide_channel_cookie)) &get_altstatus,
|
||||
(status_t (*)(ide_channel_cookie,uint8)) &write_device_control,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &write_pio,
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &read_pio,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
const physical_entry *,size_t,bool)) &prepare_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &start_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &finish_dma,
|
||||
};
|
||||
|
||||
|
||||
static pnp_driver_info controller_interface = {
|
||||
{
|
||||
GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME,
|
||||
0,
|
||||
module_std_ops
|
||||
},
|
||||
|
||||
(status_t (*)( pnp_node_handle, void *, void ** )) init_controller,
|
||||
(status_t (*)( void * )) uninit_controller,
|
||||
probe_controller,
|
||||
(void (*)( pnp_node_handle, void * )) controller_removed
|
||||
};
|
||||
|
||||
#if !_BUILDING_kernel && !BOOT
|
||||
_EXPORT
|
||||
module_info *modules[] = {
|
||||
(module_info *)&controller_interface,
|
||||
(module_info *)&channel_interface,
|
||||
NULL
|
||||
};
|
||||
#endif
|
89
src/add-ons/kernel/busses/ide/generic_ide_pci/wrapper.h
Normal file
89
src/add-ons/kernel/busses/ide/generic_ide_pci/wrapper.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef _WRAPPER_H
|
||||
#define _WRAPPER_H
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <lock.h>
|
||||
|
||||
|
||||
// benaphores
|
||||
|
||||
#define INIT_BEN(x, prefix) benaphore_init(x, prefix)
|
||||
#define DELETE_BEN(x) benaphore_destroy(x)
|
||||
#define ACQUIRE_BEN(x) benaphore_lock(x)
|
||||
#define RELEASE_BEN(x) benaphore_unlock(x)
|
||||
|
||||
// debug output
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_MSG
|
||||
# define DEBUG_WAIT snooze( DEBUG_WAIT_ON_MSG );
|
||||
#else
|
||||
# define DEBUG_WAIT
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_ERROR
|
||||
# define DEBUG_WAIT_ERROR snooze( DEBUG_WAIT_ON_ERROR );
|
||||
#else
|
||||
# define DEBUG_WAIT_ERROR
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_FLOW
|
||||
# define DEBUG_MAX_LEVEL_FLOW 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_INFO
|
||||
# define DEBUG_MAX_LEVEL_INFO 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_ERROR
|
||||
# define DEBUG_MAX_LEVEL_ERROR 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MSG_PREFIX
|
||||
# define DEBUG_MSG_PREFIX ""
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_flow
|
||||
# define debug_level_flow 3
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_info
|
||||
# define debug_level_info 2
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_error
|
||||
# define debug_level_error 1
|
||||
#endif
|
||||
|
||||
#define FUNC_NAME DEBUG_MSG_PREFIX __FUNCTION__ ": "
|
||||
|
||||
#define SHOW_FLOW(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_FLOW0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#endif /* _BENAPHORE_H */
|
7
src/add-ons/kernel/busses/ide/ide_isa/Jamfile
Normal file
7
src/add-ons/kernel/busses/ide/ide_isa/Jamfile
Normal file
@ -0,0 +1,7 @@
|
||||
SubDir OBOS_TOP src add-ons kernel busses ide ide_isa ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon ide_isa : kernel busses ide :
|
||||
ide_isa.c
|
||||
;
|
457
src/add-ons/kernel/busses/ide/ide_isa/ide_isa.c
Normal file
457
src/add-ons/kernel/busses/ide/ide_isa/ide_isa.c
Normal file
@ -0,0 +1,457 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
IDE ISA controller driver
|
||||
|
||||
This is a testing-only driver. In reality, you want to use
|
||||
the IDE PCI controller driver, but at least under Bochs, there's not
|
||||
much choice as PCI support is very limited there.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bus/IDE.h>
|
||||
#include <bus/ISA.h>
|
||||
#include <device_manager.h>
|
||||
#include <blkman.h>
|
||||
|
||||
#define debug_level_flow 4
|
||||
#define debug_level_error 4
|
||||
#define debug_level_info 4
|
||||
|
||||
#define DEBUG_MSG_PREFIX "IDE ISA -- "
|
||||
|
||||
#include "wrapper.h"
|
||||
|
||||
#define IDE_ISA_MODULE_NAME "busses/ide/ide_isa/"ISA_DEVICE_TYPE_NAME
|
||||
|
||||
// private node item:
|
||||
// io address of command block
|
||||
#define IDE_ISA_COMMAND_BLOCK_BASE "ide_isa/command_block_base"
|
||||
// io address of control block
|
||||
#define IDE_ISA_CONTROL_BLOCK_BASE "ide_isa/control_block_base"
|
||||
// interrupt number
|
||||
#define IDE_ISA_INTNUM "ide_isa/irq"
|
||||
|
||||
//isa2_module_info *isa;
|
||||
ide_for_controller_interface *ide;
|
||||
device_manager_info *pnp;
|
||||
|
||||
|
||||
// info about one channel
|
||||
typedef struct channel_info {
|
||||
isa2_module_info *isa;
|
||||
uint16 command_block_base; // io address command block
|
||||
uint16 control_block_base; // io address control block
|
||||
int intnum; // interrupt number
|
||||
|
||||
uint32 lost; // != 0 if device got removed, i.e. if it must not
|
||||
// be accessed anymore
|
||||
|
||||
ide_channel ide_channel;
|
||||
pnp_node_handle node;
|
||||
} channel_info;
|
||||
|
||||
|
||||
static int
|
||||
write_command_block_regs(channel_info *channel, ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
int i;
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
if( channel->lost )
|
||||
return B_ERROR;
|
||||
|
||||
for( i = 0; i < 7; i++ ) {
|
||||
if( ((1 << (i-7)) & mask) != 0 ) {
|
||||
SHOW_FLOW( 3, "%x->HI(%x)", tf->raw.r[i + 7], i );
|
||||
channel->isa->write_io_8( ioaddr + 1 + i, tf->raw.r[i + 7] );
|
||||
}
|
||||
|
||||
if( ((1 << i) & mask) != 0 ) {
|
||||
SHOW_FLOW( 3, "%x->LO(%x)", tf->raw.r[i], i );
|
||||
channel->isa->write_io_8( ioaddr + 1 + i, tf->raw.r[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
read_command_block_regs(channel_info *channel, ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
int i;
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
if( channel->lost )
|
||||
return B_ERROR;
|
||||
|
||||
for( i = 0; i < 7; i++ ) {
|
||||
if( ((1 << i) & mask) != 0 ) {
|
||||
tf->raw.r[i] = channel->isa->read_io_8( ioaddr + 1 + i );
|
||||
SHOW_FLOW( 3, "%x: %x", i, (int)tf->raw.r[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static uint8
|
||||
get_altstatus(channel_info *channel)
|
||||
{
|
||||
uint16 altstatusaddr = channel->control_block_base;
|
||||
|
||||
if (channel->lost)
|
||||
return B_ERROR;
|
||||
|
||||
return channel->isa->read_io_8(altstatusaddr);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
write_device_control(channel_info *channel, uint8 val)
|
||||
{
|
||||
uint16 device_control_addr = channel->control_block_base;
|
||||
|
||||
SHOW_FLOW( 3, "%x", (int)val );
|
||||
|
||||
if (channel->lost)
|
||||
return B_ERROR;
|
||||
|
||||
channel->isa->write_io_8(device_control_addr, val);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
write_pio_16(channel_info *channel, uint16 *data, int count, bool force_16bit)
|
||||
{
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
if( channel->lost )
|
||||
return B_ERROR;
|
||||
|
||||
// Bochs doesn't support 32 bit accesses;
|
||||
// no real performance impact as this driver is for Bochs only anyway
|
||||
force_16bit = true;
|
||||
|
||||
if( (count & 1) != 0 || force_16bit ) {
|
||||
for( ; count > 0; --count )
|
||||
channel->isa->write_io_16( ioaddr, *(data++) );
|
||||
|
||||
} else {
|
||||
uint32 *cur_data = (uint32 *)data;
|
||||
|
||||
for( ; count > 0; count -= 2 )
|
||||
channel->isa->write_io_32( ioaddr, *(cur_data++) );
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
read_pio_16(channel_info *channel, uint16 *data, int count, bool force_16bit)
|
||||
{
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
if( channel->lost )
|
||||
return B_ERROR;
|
||||
|
||||
force_16bit = true;
|
||||
|
||||
if( (count & 1) != 0 || force_16bit ) {
|
||||
for( ; count > 0; --count )
|
||||
*(data++) = channel->isa->read_io_16( ioaddr );
|
||||
|
||||
} else {
|
||||
uint32 *cur_data = (uint32 *)data;
|
||||
|
||||
for( ; count > 0; count -= 2 )
|
||||
*(cur_data++) = channel->isa->read_io_32( ioaddr );
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
inthand(void *arg)
|
||||
{
|
||||
channel_info *channel = (channel_info *)arg;
|
||||
uint8 status;
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
if (channel->lost)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
// acknowledge IRQ
|
||||
status = channel->isa->read_io_8(channel->command_block_base + 7);
|
||||
|
||||
return ide->irq_handler(channel->ide_channel, status);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
prepare_dma(channel_info *channel, const physical_entry *sg_list, size_t sg_list_count,
|
||||
uint32 startbyte, uint32 blocksize, size_t *numBytes, bool to_device)
|
||||
{
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
start_dma(void *channel)
|
||||
{
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
finish_dma(void *channel)
|
||||
{
|
||||
return B_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_channel(pnp_node_handle node, ide_channel ide_channel, channel_info **cookie)
|
||||
{
|
||||
channel_info *channel;
|
||||
isa2_module_info *isa;
|
||||
void *dummy;
|
||||
uint16 command_block_base, control_block_base;
|
||||
uint8 irq;
|
||||
status_t res;
|
||||
|
||||
// get device data
|
||||
if (pnp->get_attr_uint16(node, IDE_ISA_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK
|
||||
|| pnp->get_attr_uint16(node, IDE_ISA_CONTROL_BLOCK_BASE, &control_block_base, false) != B_OK
|
||||
|| pnp->get_attr_uint8(node, IDE_ISA_INTNUM, &irq, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if (pnp->load_driver(pnp->get_parent(node), NULL, (pnp_driver_info **)&isa, &dummy) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
channel = (channel_info *)malloc(sizeof(channel_info));
|
||||
if (channel == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
channel->isa = isa;
|
||||
channel->node = node;
|
||||
channel->lost = false;
|
||||
channel->command_block_base = command_block_base;
|
||||
channel->control_block_base = control_block_base;
|
||||
channel->intnum = irq;
|
||||
channel->ide_channel = ide_channel;
|
||||
|
||||
res = install_io_interrupt_handler(channel->intnum,
|
||||
inthand, channel, 0);
|
||||
|
||||
if (res < 0) {
|
||||
SHOW_ERROR( 0, "couldn't install irq handler @%d", irq);
|
||||
goto err;
|
||||
}
|
||||
|
||||
// enable interrupts so the channel is ready to run
|
||||
write_device_control(channel, ide_devctrl_bit3);
|
||||
|
||||
*cookie = channel;
|
||||
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
free(channel);
|
||||
|
||||
err0:
|
||||
pnp->unload_driver(pnp->get_parent(node));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
uninit_channel(channel_info *channel)
|
||||
{
|
||||
// disable IRQs
|
||||
write_device_control(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);
|
||||
|
||||
remove_io_interrupt_handler(channel->intnum, inthand, channel);
|
||||
|
||||
pnp->unload_driver(pnp->get_parent(channel->node));
|
||||
|
||||
free(channel);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// publish node of ide channel
|
||||
static status_t
|
||||
publish_channel(pnp_node_handle parent, io_resource_handle *resources, uint16 command_block_base,
|
||||
uint16 control_block_base, uint8 intnum, const char *name)
|
||||
{
|
||||
pnp_node_attr attrs[] = {
|
||||
// info about ourself and our consumer
|
||||
{ PNP_DRIVER_DRIVER, B_STRING_TYPE, { string: IDE_ISA_MODULE_NAME }},
|
||||
{ PNP_DRIVER_TYPE, B_STRING_TYPE, { string: IDE_BUS_TYPE_NAME }},
|
||||
{ PNP_DRIVER_FIXED_CONSUMER, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: name }},
|
||||
{ PNP_DRIVER_DEVICE_IDENTIFIER, B_STRING_TYPE, { string: "ide_isa" }},
|
||||
// don't scan if loaded as we own I/O resources
|
||||
{ PNP_DRIVER_NO_LIVE_RESCAN, B_UINT8_TYPE, { ui8: 1 }},
|
||||
|
||||
// properties of this controller for ide bus manager
|
||||
{ IDE_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { ui8: 2 }},
|
||||
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: 0 }},
|
||||
{ IDE_CONTROLLER_CAN_CQ_ITEM, B_UINT8_TYPE, { ui8: 1 }},
|
||||
{ IDE_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { string: name }},
|
||||
|
||||
// DMA properties; the 16 bit alignment is not necessary as
|
||||
// the ide bus manager handles that very efficiently, but why
|
||||
// not use the block device manager for doing that?
|
||||
{ BLKDEV_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1 }},
|
||||
|
||||
// private data to identify device
|
||||
{ IDE_ISA_COMMAND_BLOCK_BASE, B_UINT16_TYPE, { ui16: command_block_base }},
|
||||
{ IDE_ISA_CONTROL_BLOCK_BASE, B_UINT16_TYPE, { ui16: control_block_base }},
|
||||
{ IDE_ISA_INTNUM, B_UINT8_TYPE, { ui8: intnum }},
|
||||
{ NULL }
|
||||
};
|
||||
pnp_node_handle node;
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
return pnp->register_device(parent, attrs, resources, &node);
|
||||
}
|
||||
|
||||
|
||||
// detect IDE channel
|
||||
static status_t
|
||||
probe_channel(pnp_node_handle parent,
|
||||
uint16 command_block_base, uint16 control_block_base,
|
||||
int intnum, const char *name)
|
||||
{
|
||||
io_resource resources[3] = {
|
||||
{ IO_PORT, command_block_base, 8 },
|
||||
{ IO_PORT, control_block_base, 1 },
|
||||
{}
|
||||
};
|
||||
io_resource_handle resource_handles[3];
|
||||
|
||||
SHOW_FLOW(3, "name = \"%s\"", name);
|
||||
|
||||
// we aren't upset if io-ports are in use already - only
|
||||
// the PCI IDE driver can own them, and if it does, we exit silently
|
||||
if (pnp->acquire_io_resources(resources, resource_handles) != B_OK)
|
||||
return B_OK;
|
||||
|
||||
// we assume that every modern PC has an IDE controller, so no
|
||||
// further testing is done (well - I don't really know how to detect the
|
||||
// controll, but who cares ;)
|
||||
return publish_channel(parent, resource_handles, command_block_base,
|
||||
control_block_base, intnum, name);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scan_parent(pnp_node_handle node)
|
||||
{
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
// our parent device is the isa bus and all device drivers are Universal,
|
||||
// so the pnp_manager tries each ISA driver in turn
|
||||
probe_channel(node, 0x1f0, 0x3f6, 14, "primary IDE channel");
|
||||
probe_channel(node, 0x170, 0x376, 15, "secondary IDE channel");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
channel_removed(pnp_node_handle node, channel_info *channel)
|
||||
{
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
if (channel != NULL)
|
||||
// disable access instantly
|
||||
atomic_or(&channel->lost, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
|
||||
{ DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
|
||||
{}
|
||||
};
|
||||
|
||||
// exported interface
|
||||
ide_controller_interface isa_controller_interface = {
|
||||
{
|
||||
{
|
||||
IDE_ISA_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
(status_t (*)( pnp_node_handle, void *, void ** )) init_channel,
|
||||
(status_t (*)( void * )) uninit_channel,
|
||||
scan_parent,
|
||||
(void (*)( pnp_node_handle, void * )) channel_removed
|
||||
},
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &write_command_block_regs,
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &read_command_block_regs,
|
||||
|
||||
(uint8 (*)(ide_channel_cookie)) &get_altstatus,
|
||||
(status_t (*)(ide_channel_cookie,uint8)) &write_device_control,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &write_pio_16,
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &read_pio_16,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
const physical_entry *,size_t,bool)) &prepare_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &start_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &finish_dma,
|
||||
};
|
||||
|
||||
#if !_BUILDING_kernel && !BOOT
|
||||
_EXPORT
|
||||
module_info *modules[] = {
|
||||
(module_info *)&isa_controller_interface,
|
||||
NULL
|
||||
};
|
||||
#endif
|
89
src/add-ons/kernel/busses/ide/ide_isa/wrapper.h
Normal file
89
src/add-ons/kernel/busses/ide/ide_isa/wrapper.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef _WRAPPER_H
|
||||
#define _WRAPPER_H
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <lock.h>
|
||||
|
||||
|
||||
// benaphores
|
||||
|
||||
#define INIT_BEN(x, prefix) benaphore_init(x, prefix)
|
||||
#define DELETE_BEN(x) benaphore_destroy(x)
|
||||
#define ACQUIRE_BEN(x) benaphore_lock(x)
|
||||
#define RELEASE_BEN(x) benaphore_unlock(x)
|
||||
|
||||
// debug output
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_MSG
|
||||
# define DEBUG_WAIT snooze( DEBUG_WAIT_ON_MSG );
|
||||
#else
|
||||
# define DEBUG_WAIT
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_ERROR
|
||||
# define DEBUG_WAIT_ERROR snooze( DEBUG_WAIT_ON_ERROR );
|
||||
#else
|
||||
# define DEBUG_WAIT_ERROR
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_FLOW
|
||||
# define DEBUG_MAX_LEVEL_FLOW 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_INFO
|
||||
# define DEBUG_MAX_LEVEL_INFO 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_ERROR
|
||||
# define DEBUG_MAX_LEVEL_ERROR 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MSG_PREFIX
|
||||
# define DEBUG_MSG_PREFIX ""
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_flow
|
||||
# define debug_level_flow 3
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_info
|
||||
# define debug_level_info 2
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_error
|
||||
# define debug_level_error 1
|
||||
#endif
|
||||
|
||||
#define FUNC_NAME DEBUG_MSG_PREFIX __FUNCTION__ ": "
|
||||
|
||||
#define SHOW_FLOW(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_FLOW0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#endif /* _BENAPHORE_H */
|
7
src/add-ons/kernel/busses/ide/promise_tx2/Jamfile
Normal file
7
src/add-ons/kernel/busses/ide/promise_tx2/Jamfile
Normal file
@ -0,0 +1,7 @@
|
||||
SubDir OBOS_TOP src add-ons kernel busses ide promise_tx2 ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon promise_tx2 : kernel busses ide :
|
||||
promise_tx2.c
|
||||
;
|
385
src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c
Normal file
385
src/add-ons/kernel/busses/ide/promise_tx2/promise_tx2.c
Normal file
@ -0,0 +1,385 @@
|
||||
/*
|
||||
** Copyright 2002-04, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Promise TX2 series IDE controller driver
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bus/ide/ide_adapter.h>
|
||||
#include <blkman.h>
|
||||
|
||||
#define debug_level_flow 0
|
||||
#define debug_level_error 3
|
||||
#define debug_level_info 3
|
||||
|
||||
#define DEBUG_MSG_PREFIX "PROMISE TX2 -- "
|
||||
|
||||
#include "wrapper.h"
|
||||
|
||||
#define PROMISE_TX2_CONTROLLER_MODULE_NAME "busses/ide/promise_tx2/" PCI_DEVICE_TYPE_NAME
|
||||
#define PROMISE_TX2_CHANNEL_MODULE_NAME "busses/ide/promise_tx2/channel/v1"
|
||||
|
||||
#define PROMISE_TX2_CONTROLLER_TYPE_NAME "promise tx2 controller"
|
||||
|
||||
|
||||
static ide_for_controller_interface *ide;
|
||||
static ide_adapter_interface *ide_adapter;
|
||||
static device_manager_info *pnp;
|
||||
|
||||
|
||||
static int
|
||||
write_command_block_regs(ide_adapter_channel_info *channel,
|
||||
ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
return ide_adapter->write_command_block_regs(channel, tf, mask);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
read_command_block_regs(ide_adapter_channel_info *channel,
|
||||
ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
return ide_adapter->read_command_block_regs(channel, tf, mask);
|
||||
}
|
||||
|
||||
|
||||
static uint8
|
||||
get_altstatus(ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->get_altstatus(channel);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
write_device_control(ide_adapter_channel_info *channel, uint8 val)
|
||||
{
|
||||
return ide_adapter->write_device_control(channel, val);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
write_pio(ide_adapter_channel_info *channel, uint16 *data, int count,
|
||||
bool force_16bit)
|
||||
{
|
||||
return ide_adapter->write_pio(channel, data, count, force_16bit);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
read_pio(ide_adapter_channel_info *channel, uint16 *data, int count,
|
||||
bool force_16bit)
|
||||
{
|
||||
return ide_adapter->read_pio(channel, data, count, force_16bit);
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
inthand(void *arg)
|
||||
{
|
||||
ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg;
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
ide_bm_status bm_status;
|
||||
uint8 status;
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
if (channel->lost)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
// the controller always tells us whether it generated the IRQ, so ask it first
|
||||
pci->write_io_8(device, channel->bus_master_base + 1, 0x0b);
|
||||
if ((pci->read_io_8(device, channel->bus_master_base + 3) & 0x20) == 0)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
|
||||
if (channel->dmaing) {
|
||||
// in DMA mode, there is a safe test
|
||||
// in PIO mode, this doesn't work
|
||||
*(uint8 *)&bm_status = pci->read_io_8( device,
|
||||
channel->bus_master_base + ide_bm_status_reg );
|
||||
|
||||
if (!bm_status.interrupt)
|
||||
return B_UNHANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
// acknowledge IRQ
|
||||
status = pci->read_io_8(device, channel->command_block_base + 7);
|
||||
|
||||
return ide->irq_handler(channel->ide_channel, status);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
prepare_dma(ide_adapter_channel_info *channel, const physical_entry *sg_list,
|
||||
size_t sg_list_count, bool to_device)
|
||||
{
|
||||
return ide_adapter->prepare_dma(channel, sg_list, sg_list_count, to_device);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
start_dma(ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->start_dma(channel);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
finish_dma(ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->finish_dma(channel);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_channel(pnp_node_handle node, ide_channel ide_channel,
|
||||
ide_adapter_channel_info **cookie)
|
||||
{
|
||||
return ide_adapter->init_channel(node, ide_channel, cookie,
|
||||
sizeof( ide_adapter_channel_info ), inthand);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
uninit_channel(ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->uninit_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
static void channel_removed(pnp_node_handle node, ide_adapter_channel_info *channel)
|
||||
{
|
||||
return ide_adapter->channel_removed(node, channel);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_controller(pnp_node_handle node, void *user_cookie,
|
||||
ide_adapter_controller_info **cookie)
|
||||
{
|
||||
return ide_adapter->init_controller(node, user_cookie, cookie,
|
||||
sizeof(ide_adapter_controller_info));
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
uninit_controller(ide_adapter_controller_info *controller)
|
||||
{
|
||||
return ide_adapter->uninit_controller(controller);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
controller_removed(pnp_node_handle node, ide_adapter_controller_info *controller)
|
||||
{
|
||||
return ide_adapter->controller_removed(node, controller);
|
||||
}
|
||||
|
||||
|
||||
// publish node of ide controller
|
||||
|
||||
static status_t
|
||||
publish_controller(pnp_node_handle parent, uint16 bus_master_base, uint8 intnum,
|
||||
io_resource_handle *resources, pnp_node_handle *node)
|
||||
{
|
||||
pnp_node_attr attrs[] = {
|
||||
// info about ourself and our consumer
|
||||
{ PNP_DRIVER_DRIVER, B_STRING_TYPE, { string: PROMISE_TX2_CONTROLLER_MODULE_NAME }},
|
||||
{ PNP_DRIVER_TYPE, B_STRING_TYPE, { string: PROMISE_TX2_CONTROLLER_TYPE_NAME }},
|
||||
// don't scan if loaded as we own I/O resources
|
||||
{ PNP_DRIVER_NO_LIVE_RESCAN, B_UINT8_TYPE, { ui8: 1 }},
|
||||
|
||||
// properties of this controller for ide bus manager
|
||||
// there are always max. 2 devices
|
||||
{ IDE_CONTROLLER_MAX_DEVICES_ITEM, B_UINT8_TYPE, { ui8: 2 }},
|
||||
// of course we can DMA
|
||||
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: 1 }},
|
||||
// command queuing always works
|
||||
{ IDE_CONTROLLER_CAN_CQ_ITEM, B_UINT8_TYPE, { ui8: 1 }},
|
||||
// choose any name here
|
||||
{ IDE_CONTROLLER_CONTROLLER_NAME_ITEM, B_STRING_TYPE, { string: "Promise TX2" }},
|
||||
|
||||
// DMA properties
|
||||
// some say it must be dword-aligned, others that it can be byte-aligned;
|
||||
// stay on the safe side
|
||||
{ BLKDEV_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 3 }},
|
||||
// one S/G block must not cross 64K boundary
|
||||
{ BLKDEV_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
|
||||
// size of S/G block is 16 bits with zero being 64K
|
||||
{ BLKDEV_MAX_SG_BLOCK_SIZE, B_UINT32_TYPE, { ui32: 0x10000 }},
|
||||
// see definition of MAX_SG_COUNT
|
||||
{ BLKDEV_MAX_SG_BLOCKS, B_UINT32_TYPE, { ui32: IDE_ADAPTER_MAX_SG_COUNT }},
|
||||
|
||||
// private data to find controller
|
||||
{ IDE_ADAPTER_BUS_MASTER_BASE, B_UINT16_TYPE, { ui16: bus_master_base }},
|
||||
// store interrupt in controller node
|
||||
{ IDE_ADAPTER_INTNUM, B_UINT8_TYPE, { ui8: intnum }},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
SHOW_FLOW0(2, "");
|
||||
|
||||
return pnp->register_device(parent, attrs, resources, node);
|
||||
}
|
||||
|
||||
|
||||
// detect pure IDE controller, i.e. without channels
|
||||
|
||||
static status_t
|
||||
detect_controller(pci_device_module_info *pci, pci_device pci_device,
|
||||
pnp_node_handle parent, uint16 bus_master_base, int8 intnum,
|
||||
pnp_node_handle *node)
|
||||
{
|
||||
io_resource_handle resource_handles[2];
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if ((bus_master_base & PCI_address_space) != 1)
|
||||
return B_OK;
|
||||
|
||||
bus_master_base &= ~PCI_address_space;
|
||||
|
||||
{
|
||||
io_resource resources[2] = {
|
||||
{ IO_PORT, bus_master_base, 16 },
|
||||
{}
|
||||
};
|
||||
|
||||
if (pnp->acquire_io_resources(resources, resource_handles) != B_OK)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return publish_controller(parent, bus_master_base, intnum, resource_handles, node);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
probe_controller(pnp_node_handle parent)
|
||||
{
|
||||
pci_device_module_info *pci;
|
||||
pci_device device;
|
||||
uint16 command_block_base[2];
|
||||
uint16 control_block_base[2];
|
||||
uint16 bus_master_base;
|
||||
pnp_node_handle controller_node, channels[2];
|
||||
uint8 intnum;
|
||||
status_t res;
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (pnp->load_driver(parent, NULL, (pnp_driver_info **)&pci, (void **)&device) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
command_block_base[0] = pci->read_pci_config(device, PCI_base_registers, 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);
|
||||
bus_master_base = pci->read_pci_config(device, PCI_base_registers + 16, 4);
|
||||
intnum = pci->read_pci_config(device, PCI_interrupt_line, 1);
|
||||
|
||||
res = detect_controller(pci, device, parent, bus_master_base, intnum, &controller_node);
|
||||
if (res != B_OK || controller_node == NULL)
|
||||
goto err;
|
||||
|
||||
ide_adapter->detect_channel(pci, device, controller_node,
|
||||
PROMISE_TX2_CHANNEL_MODULE_NAME, true,
|
||||
command_block_base[0], control_block_base[0], bus_master_base, intnum, true,
|
||||
"Primary Channel", &channels[0], false);
|
||||
|
||||
ide_adapter->detect_channel(pci, device, controller_node,
|
||||
PROMISE_TX2_CHANNEL_MODULE_NAME, true,
|
||||
command_block_base[1], control_block_base[1], bus_master_base, intnum, false,
|
||||
"Secondary Channel", &channels[1], false);
|
||||
|
||||
pnp->unload_driver(parent);
|
||||
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
pnp->unload_driver(parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
|
||||
{ DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
|
||||
{ IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// exported interface
|
||||
static ide_controller_interface channel_interface = {
|
||||
{
|
||||
{
|
||||
PROMISE_TX2_CHANNEL_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
(status_t (*)( pnp_node_handle , void *, void ** )) init_channel,
|
||||
(status_t (*)( void * )) uninit_channel,
|
||||
NULL,
|
||||
(void (*)( pnp_node_handle , void * )) channel_removed
|
||||
},
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &write_command_block_regs,
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
ide_task_file*,ide_reg_mask)) &read_command_block_regs,
|
||||
|
||||
(uint8 (*)(ide_channel_cookie)) &get_altstatus,
|
||||
(status_t (*)(ide_channel_cookie,uint8)) &write_device_control,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &write_pio,
|
||||
(status_t (*)(ide_channel_cookie,uint16*,int,bool)) &read_pio,
|
||||
|
||||
(status_t (*)(ide_channel_cookie,
|
||||
const physical_entry *,size_t,bool)) &prepare_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &start_dma,
|
||||
(status_t (*)(ide_channel_cookie)) &finish_dma,
|
||||
};
|
||||
|
||||
|
||||
static pnp_driver_info controller_interface = {
|
||||
{
|
||||
PROMISE_TX2_CONTROLLER_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
(status_t (*)( pnp_node_handle, void *, void ** )) init_controller,
|
||||
(status_t (*)( void * )) uninit_controller,
|
||||
probe_controller,
|
||||
(void (*)( pnp_node_handle, void * )) controller_removed
|
||||
};
|
||||
|
||||
#if !_BUILDING_kernel && !BOOT
|
||||
_EXPORT
|
||||
module_info *modules[] = {
|
||||
(module_info *)&controller_interface,
|
||||
(module_info *)&channel_interface,
|
||||
NULL
|
||||
};
|
||||
#endif
|
89
src/add-ons/kernel/busses/ide/promise_tx2/wrapper.h
Normal file
89
src/add-ons/kernel/busses/ide/promise_tx2/wrapper.h
Normal file
@ -0,0 +1,89 @@
|
||||
#ifndef _WRAPPER_H
|
||||
#define _WRAPPER_H
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <lock.h>
|
||||
|
||||
|
||||
// benaphores
|
||||
|
||||
#define INIT_BEN(x, prefix) benaphore_init(x, prefix)
|
||||
#define DELETE_BEN(x) benaphore_destroy(x)
|
||||
#define ACQUIRE_BEN(x) benaphore_lock(x)
|
||||
#define RELEASE_BEN(x) benaphore_unlock(x)
|
||||
|
||||
// debug output
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_MSG
|
||||
# define DEBUG_WAIT snooze( DEBUG_WAIT_ON_MSG );
|
||||
#else
|
||||
# define DEBUG_WAIT
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_WAIT_ON_ERROR
|
||||
# define DEBUG_WAIT_ERROR snooze( DEBUG_WAIT_ON_ERROR );
|
||||
#else
|
||||
# define DEBUG_WAIT_ERROR
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_FLOW
|
||||
# define DEBUG_MAX_LEVEL_FLOW 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_INFO
|
||||
# define DEBUG_MAX_LEVEL_INFO 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MAX_LEVEL_ERROR
|
||||
# define DEBUG_MAX_LEVEL_ERROR 4
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_MSG_PREFIX
|
||||
# define DEBUG_MSG_PREFIX ""
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_flow
|
||||
# define debug_level_flow 3
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_info
|
||||
# define debug_level_info 2
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_error
|
||||
# define debug_level_error 1
|
||||
#endif
|
||||
|
||||
#define FUNC_NAME DEBUG_MSG_PREFIX __FUNCTION__ ": "
|
||||
|
||||
#define SHOW_FLOW(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_FLOW0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_flow && seriousness <= DEBUG_MAX_LEVEL_FLOW ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_INFO0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_info && seriousness <= DEBUG_MAX_LEVEL_INFO ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR(seriousness, format, param...) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME, param ); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#define SHOW_ERROR0(seriousness, format) \
|
||||
do { if( seriousness <= debug_level_error && seriousness <= DEBUG_MAX_LEVEL_ERROR ) { \
|
||||
dprintf( "%s"##format"\n", FUNC_NAME); DEBUG_WAIT_ERROR \
|
||||
}} while( 0 )
|
||||
|
||||
#endif /* _BENAPHORE_H */
|
Loading…
Reference in New Issue
Block a user