ide: Remove last ide fragments.

* Missed in previous commit.
This commit is contained in:
Alexander von Gluck IV
2017-06-28 08:51:24 -05:00
parent 7600fdd8e2
commit 402ec26eda
20 changed files with 0 additions and 4215 deletions
-200
View File
@@ -1,200 +0,0 @@
/*
* Copyright 2005-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef _IDE_PCI_H
#define _IDE_PCI_H
/*
IDE adapter library
Module to simplify writing an IDE adapter driver.
The interface is not very abstract, i.e. the actual driver is
free to access any controller or channel data of this library.
*/
#include <bus/PCI.h>
#include <bus/IDE.h>
#include <ide_types.h>
#include <device_manager.h>
// one Physical Region Descriptor (PRD)
// (one region must not cross 64K boundary;
// the PRD table must not cross a 64K boundary)
typedef struct prd_entry {
uint32 address; // physical address of block (must be even)
uint16 count; // size of block, 0 stands for 65536 (must be even)
uint8 res6;
LBITFIELD8_2(
res7_0 : 7,
EOT : 1 // 1 for last entry
);
} prd_entry;
// IDE bus master command register
#define IDE_BM_COMMAND_START_STOP 0x01
#define IDE_BM_COMMAND_READ_FROM_DEVICE 0x08
// IDE bus master status register
#define IDE_BM_STATUS_ACTIVE 0x01
#define IDE_BM_STATUS_ERROR 0x02
#define IDE_BM_STATUS_INTERRUPT 0x04
#define IDE_BM_STATUS_MASTER_DMA 0x20
#define IDE_BM_STATUS_SLAVE_DMA 0x40
#define IDE_BM_STATUS_SIMPLEX_DMA 0x80
// offset of bus master registers
enum {
IDE_BM_COMMAND_REG = 0,
IDE_BM_STATUS_REG = 2,
IDE_BM_PRDT_ADDRESS = 4
// offset of PRDT register; content must be dword-aligned
};
// (maximum) size of S/G table
// there are so many restrictions that we want to keep it inside one page
// to be sure that we fulfill them all
#define IDE_ADAPTER_MAX_SG_COUNT (B_PAGE_SIZE / sizeof( prd_entry ))
// channel node items
// io address of command block (uint16)
#define IDE_ADAPTER_COMMAND_BLOCK_BASE "ide_adapter/command_block_base"
// io address of control block (uint16)
#define IDE_ADAPTER_CONTROL_BLOCK_BASE "ide_adapter/control_block_base"
// interrupt number (uint8)
// can also be defined in controller node if both channels use same IRQ!
#define IDE_ADAPTER_INTNUM "ide_adapter/irq"
// 0 if primary channel, 1 if secondary channel, 2 if tertiary, ... (uint8)
#define IDE_ADAPTER_CHANNEL_INDEX "ide_adapter/channel_index"
// controller node items
// io address of bus master registers (uint16)
#define IDE_ADAPTER_BUS_MASTER_BASE "ide_adapter/bus_master_base"
// info about one channel
typedef struct ide_adapter_channel_info {
pci_device_module_info *pci;
pci_device *device;
uint16 command_block_base; // io address command block
uint16 control_block_base; // io address control block
uint16 bus_master_base;
int intnum; // interrupt number
uint32 lost; // != 0 if device got removed, i.e. if it must not
// be accessed anymore
ide_channel ideChannel;
device_node *node;
int32 (*inthand)( void *arg );
area_id prd_area;
prd_entry *prdt;
uint32 prdt_phys;
uint32 dmaing;
} ide_adapter_channel_info;
// info about controller
typedef struct ide_adapter_controller_info {
pci_device_module_info *pci;
pci_device *device;
uint16 bus_master_base;
uint32 lost; // != 0 if device got removed, i.e. if it must not
// be accessed anymore
device_node *node;
} ide_adapter_controller_info;
// interface of IDE adapter library
typedef struct {
module_info info;
void (*set_channel)(ide_adapter_channel_info *channel,
ide_channel ideChannel);
// function calls that can be forwarded from actual driver
status_t (*write_command_block_regs)(ide_adapter_channel_info *channel,
ide_task_file *tf, ide_reg_mask mask);
status_t (*read_command_block_regs)(ide_adapter_channel_info *channel,
ide_task_file *tf, ide_reg_mask mask);
uint8 (*get_altstatus) (ide_adapter_channel_info *channel);
status_t (*write_device_control) (ide_adapter_channel_info *channel, uint8 val);
status_t (*write_pio)(ide_adapter_channel_info *channel, uint16 *data, int count, bool force_16bit);
status_t (*read_pio)(ide_adapter_channel_info *channel, uint16 *data, int count, bool force_16bit);
status_t (*prepare_dma)(ide_adapter_channel_info *channel, const physical_entry *sg_list,
size_t sg_list_count, bool to_device);
status_t (*start_dma)(ide_adapter_channel_info *channel);
status_t (*finish_dma)(ide_adapter_channel_info *channel);
// default functions that should be replaced by a more specific version
// (copy them from source code of this library and modify them at will)
int32 (*inthand)(void *arg);
// functions that must be called by init/uninit etc. of channel driver
status_t (*init_channel)(device_node *node,
ide_adapter_channel_info **cookie, size_t total_data_size,
int32 (*inthand)(void *arg));
void (*uninit_channel)(ide_adapter_channel_info *channel);
void (*channel_removed)(ide_adapter_channel_info *channel);
// publish channel node
status_t (*publish_channel)(device_node *controller_node,
const char *channel_module_name, uint16 command_block_base,
uint16 control_block_base, uint8 intnum, bool can_dma,
uint8 channel_index, const char *name,
const io_resource *resources, device_node **node);
// verify channel configuration and publish node on success
status_t (*detect_channel)(pci_device_module_info *pci, pci_device *pciDevice,
device_node *controller_node, const char *channel_module_name,
bool controller_can_dma, uint16 command_block_base,
uint16 control_block_base, uint16 bus_master_base,
uint8 intnum, uint8 channel_index, const char *name,
device_node **node, bool supports_compatibility_mode);
// functions that must be called by init/uninit etc. of controller driver
status_t (*init_controller)(device_node *node,
ide_adapter_controller_info **cookie, size_t total_data_size);
void (*uninit_controller)(ide_adapter_controller_info *controller);
void (*controller_removed)(ide_adapter_controller_info *controller);
// publish controller node
status_t (*publish_controller)(device_node *parent, uint16 bus_master_base,
io_resource *resources, const char *controller_driver,
const char *controller_driver_type, const char *controller_name,
bool can_dma, bool can_cq, uint32 dma_alignment, uint32 dma_boundary,
uint32 max_sg_block_size, device_node **node);
// verify controller configuration and publish node on success
status_t (*detect_controller)(pci_device_module_info *pci, pci_device *pciDevice,
device_node *parent, uint16 bus_master_base,
const char *controller_driver, const char *controller_driver_type,
const char *controller_name, bool can_dma, bool can_cq,
uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
device_node **node);
// standard master probe for controller that registers controller and channel nodes
status_t (*probe_controller)(device_node *parent, const char *controller_driver,
const char *controller_driver_type, const char *controller_name,
const char *channel_module_name, bool can_dma, bool can_cq,
uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
bool supports_compatibility_mode);
} ide_adapter_interface;
#define IDE_ADAPTER_MODULE_NAME "generic/ide_adapter/v1"
#endif /* _IDE_PCI_H */
-294
View File
@@ -1,294 +0,0 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef __IDE_TYPES_H__
#define __IDE_TYPES_H__
#include <iovec.h>
#include <lendian_bitfield.h>
// IDE task file.
// contains the command block interpreted under different conditions with
// first byte being first command register, second byte second command register
// etc.; for lba48, registers must be written twice, therefore there
// are twice as many bytes as registers - the first eight bytes are those
// that must be written first, the second eight bytes are those that
// must be written second.
union ide_task_file {
struct {
uint8 features;
uint8 sector_count;
uint8 sector_number;
uint8 cylinder_0_7;
uint8 cylinder_8_15;
LBITFIELD8_3(
head : 4,
device : 1,
mode : 3
);
uint8 command;
} chs;
struct {
uint8 features;
uint8 sector_count;
uint8 lba_0_7;
uint8 lba_8_15;
uint8 lba_16_23;
LBITFIELD8_3(
lba_24_27 : 4,
device : 1,
mode : 3
);
uint8 command;
} lba;
struct {
LBITFIELD8_3(
dma : 1,
ovl : 1,
_0_res2 : 6
);
LBITFIELD8_2(
_1_res0 : 3,
tag : 5
);
uint8 _2_res;
uint8 byte_count_0_7;
uint8 byte_count_8_15;
LBITFIELD8_6(
lun : 3,
_5_res3 : 1,
device : 1,
_5_one5 : 1,
_5_res6 : 1,
_5_one7 : 1
);
uint8 command;
} packet;
struct {
LBITFIELD8_5(
ili : 1,
eom : 1,
abrt : 1,
_0_res3 : 1,
sense_key : 4
);
LBITFIELD8_4(
cmd_or_data : 1, // 1 - cmd, 0 - data
input_or_output : 1, // 0 - input (to device), 1 - output
release : 1,
tag : 5
);
uint8 _2_res;
uint8 byte_count_0_7;
uint8 byte_count_8_15;
LBITFIELD8_5(
_4_res0 : 4,
device : 1,
_4_obs5 : 1,
_4_res6 : 1,
_4_obs7 : 1
);
LBITFIELD8_7(
chk : 1,
_7_res1 : 2,
drq : 1,
serv : 1,
dmrd : 1,
drdy : 1,
bsy : 1
);
} packet_res;
struct {
uint8 sector_count;
LBITFIELD8_4( // only <tag> is defined for write
cmd_or_data : 1, // 1 - cmd, 0 - data
input_or_output : 1, // 0 - input (to device), 1 - output
release : 1,
tag : 5
);
uint8 lba_0_7;
uint8 lba_8_15;
uint8 lba_16_23;
LBITFIELD8_3(
lba_24_27 : 4,
device : 1,
mode : 3
);
uint8 command;
} queued;
struct {
// low order bytes
uint8 features;
uint8 sector_count_0_7;
uint8 lba_0_7;
uint8 lba_8_15;
uint8 lba_16_23;
LBITFIELD8_3(
_5low_res0 : 4,
device : 1,
mode : 3
);
uint8 command;
// high order bytes
uint8 _0high_res;
uint8 sector_count_8_15;
uint8 lba_24_31;
uint8 lba_32_39;
uint8 lba_40_47;
} lba48;
struct {
// low order bytes
uint8 sector_count_0_7;
LBITFIELD8_4(
cmd_or_data : 1, // 1 - cmd, 0 - data
input_or_output : 1, // 0 - input (to device), 1 - output
release : 1,
tag : 5
);
uint8 lba_0_7;
uint8 lba_8_15;
uint8 lba_16_23;
LBITFIELD8_3(
_5low_res0 : 4,
device : 1,
mode : 3
);
uint8 command;
// high order bytes
uint8 sector_count_8_15;
uint8 _1high_res;
uint8 lba_24_31;
uint8 lba_32_39;
uint8 lba_40_47;
} queued48;
struct {
uint8 _0_res[3];
uint8 ver; // RMSN version
LBITFIELD8_3(
pena : 1, // previously enabled
lock : 1, // capable of locking
pej : 1 // can physically eject
);
} set_MSN_res;
struct {
uint8 r[7+5];
} raw;
struct {
uint8 features;
uint8 sector_count;
uint8 sector_number;
uint8 cylinder_low;
uint8 cylinder_high;
uint8 device_head;
uint8 command;
} write;
struct {
uint8 error;
uint8 sector_count;
uint8 sector_number;
uint8 cylinder_low;
uint8 cylinder_high;
uint8 device_head;
uint8 status;
} read;
};
typedef union ide_task_file ide_task_file;
// content of "mode" field
enum {
ide_mode_chs = 5,
ide_mode_lba = 7
};
// mask for ide_task_file fields to be written
enum {
ide_mask_features = 0x01,
ide_mask_sector_count = 0x02,
// CHS
ide_mask_sector_number = 0x04,
ide_mask_cylinder_low = 0x08,
ide_mask_cylinder_high = 0x10,
// LBA
ide_mask_LBA_low = 0x04,
ide_mask_LBA_mid = 0x08,
ide_mask_LBA_high = 0x10,
// packet
ide_mask_byte_count = 0x18,
// packet and dma queued result
ide_mask_error = 0x01,
ide_mask_ireason = 0x02,
ide_mask_device_head = 0x20,
ide_mask_command = 0x40,
ide_mask_status = 0x40,
// for 48 bits, the following flags tell which registers to load twice
ide_mask_features_48 = 0x80 | ide_mask_features,
ide_mask_sector_count_48 = 0x100 | ide_mask_sector_count,
ide_mask_LBA_low_48 = 0x200 | ide_mask_LBA_low,
ide_mask_LBA_mid_48 = 0x400 | ide_mask_LBA_mid,
ide_mask_LBA_high_48 = 0x800 | ide_mask_LBA_high,
ide_mask_HOB = 0xf80
}; // ide_reg_mask
// status register
enum {
ide_status_err = 0x01, // error
ide_status_index = 0x02, // obsolete
ide_status_corr = 0x04, // obsolete
ide_status_drq = 0x08, // data request
ide_status_dsc = 0x10, // reserved
ide_status_service = 0x10, // ready to service device
ide_status_dwf = 0x20, // reserved
ide_status_dma = 0x20, // reserved
ide_status_dmrd = 0x20, // packet: DMA ready
ide_status_df = 0x20, // packet: disk failure
ide_status_drdy = 0x40, // device ready
ide_status_bsy = 0x80 // busy
}; // ide_status_mask
// device control register
enum {
// bit 0 must be zero
ide_devctrl_nien = 0x02, // disable INTRQ
ide_devctrl_srst = 0x04, // software device reset
ide_devctrl_bit3 = 0x08, // don't know, but must be set
// bits inbetween are reserved
ide_devctrl_hob = 0x80 // read high order byte (for 48-bit lba)
}; // ide_devcntrl_mask
// error register - most bits are command specific
enum {
// always used
ide_error_abrt = 0x04, // command aborted
// used for Ultra DMA modes
ide_error_icrc = 0x80, // interface CRC error
// used by reading data transfers
ide_error_unc = 0x40, // uncorrectable data error
// used by writing data transfers
ide_error_wp = 0x40, // media write protect
// used by all data transfer commands
ide_error_mc = 0x20, // medium changed
ide_error_idnf = 0x10, // CHS translation not init./ invalid CHS address
ide_error_mcr = 0x08, // media change requested
ide_error_nm = 0x02, // no media (for removable media devices)
}; // ide_error_mask
typedef struct ide_channel_info *ide_channel_cookie;
#endif /* __IDE_H__ */
-8
View File
@@ -1,8 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide ;
SubInclude HAIKU_TOP src add-ons kernel busses ide generic_ide_pci ;
SubInclude HAIKU_TOP src add-ons kernel busses ide ide_isa ;
SubInclude HAIKU_TOP src add-ons kernel busses ide it8211 ;
SubInclude HAIKU_TOP src add-ons kernel busses ide promise_tx2 ;
SubInclude HAIKU_TOP src add-ons kernel busses ide silicon_image_3112 ;
SubInclude HAIKU_TOP src add-ons kernel busses ide legacy_sata ;
@@ -1,7 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide generic_ide_pci ;
UsePrivateHeaders drivers kernel ;
KernelAddon generic_ide_pci :
generic_ide_pci.c
;
@@ -1,247 +0,0 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
/*! Generic PCI bus mastering IDE driver. */
#include <KernelExport.h>
#include <stdlib.h>
#include <string.h>
#include <ide_adapter.h>
#define GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ide/generic_ide_pci/driver_v1"
#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 void
set_channel(void *cookie, ide_channel channel)
{
ide_adapter->set_channel((ide_adapter_channel_info *)cookie, channel);
}
static status_t
write_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->write_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
}
static status_t
read_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->read_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
}
static uint8
get_altstatus(void *channel_cookie)
{
return ide_adapter->get_altstatus((ide_adapter_channel_info *)channel_cookie);
}
static status_t
write_device_control(void *channel_cookie, uint8 val)
{
return ide_adapter->write_device_control((ide_adapter_channel_info *)channel_cookie, val);
}
static status_t
write_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->write_pio((ide_adapter_channel_info *)channel_cookie, data, count, force_16bit);
}
static status_t
read_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->read_pio((ide_adapter_channel_info *)channel_cookie, data, count, force_16bit);
}
static status_t
prepare_dma(void *channel_cookie,
const physical_entry *sg_list, size_t sg_list_count,
bool to_device)
{
return ide_adapter->prepare_dma((ide_adapter_channel_info *)channel_cookie, sg_list, sg_list_count, to_device);
}
static status_t
start_dma(void *channel_cookie)
{
return ide_adapter->start_dma((ide_adapter_channel_info *)channel_cookie);
}
static status_t
finish_dma(void *channel_cookie)
{
return ide_adapter->finish_dma((ide_adapter_channel_info *)channel_cookie);
}
static status_t
init_channel(device_node *node, void **channel_cookie)
{
return ide_adapter->init_channel(node,
(ide_adapter_channel_info **)channel_cookie,
sizeof(ide_adapter_channel_info), ide_adapter->inthand);
}
static void
uninit_channel(void *channel_cookie)
{
ide_adapter->uninit_channel((ide_adapter_channel_info *)channel_cookie);
}
static void
channel_removed(void *channel_cookie)
{
ide_adapter->channel_removed((ide_adapter_channel_info *)channel_cookie);
}
static status_t
init_controller(device_node *node, ide_adapter_controller_info **cookie)
{
return ide_adapter->init_controller(node, cookie,
sizeof( ide_adapter_controller_info));
}
static void
uninit_controller(ide_adapter_controller_info *controller)
{
ide_adapter->uninit_controller(controller);
}
static void
controller_removed(ide_adapter_controller_info *controller)
{
return ide_adapter->controller_removed(controller);
}
static status_t
probe_controller(device_node *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 float
supports_device(device_node *parent)
{
const char *bus;
uint16 baseClass, subClass;
// make sure parent is an PCI IDE mass storage host adapter device node
if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
|| pnp->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass, false) != B_OK
|| pnp->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass, false) != B_OK)
return -1;
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage)
return 0.0f;
if (subClass == PCI_ide)
return 0.3f;
// vendor 105a: Promise Technology, Inc.; device 4d69: 20269 (Ultra133TX2)
// has subClass set to PCI_mass_storage_other, and there are others as well.
if (subClass == PCI_mass_storage_other)
return 0.3f;
return 0.0f;
}
module_dependency module_dependencies[] = {
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
{ B_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,
NULL
},
NULL, // supports device
NULL, // register device
init_channel,
uninit_channel,
NULL, // register child devices
NULL, // rescan
channel_removed,
},
&set_channel,
&write_command_block_regs,
&read_command_block_regs,
&get_altstatus,
&write_device_control,
&write_pio,
&read_pio,
&prepare_dma,
&start_dma,
&finish_dma,
};
static driver_module_info controller_interface = {
{
GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME,
0,
NULL
},
supports_device,
probe_controller,
(status_t (*)(device_node *, void **)) init_controller,
(void (*)(void *)) uninit_controller,
NULL, // register child devices
NULL, // rescan
(void (*)(void *)) controller_removed,
};
module_info *modules[] = {
(module_info *)&controller_interface,
(module_info *)&channel_interface,
NULL
};
@@ -1,12 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide ide_isa ;
UsePrivateHeaders drivers kernel ;
# disable debug output, if debugging is disabled
if $(DEBUG) = 0 {
SubDirCcFlags [ FDefines DEBUG_MAX_LEVEL_FLOW=0 DEBUG_MAX_LEVEL_INFO=0 ] ;
}
KernelAddon ide_isa :
ide_isa.c
;
@@ -1,462 +0,0 @@
/*
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT 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/ISA.h>
#include <bus/IDE.h>
#include <ide_types.h>
#include <device_manager.h>
//#define TRACE_IDE_ISA
#ifdef TRACE_IDE_ISA
# define TRACE(x...) dprintf("ide_isa: " x)
#else
# define TRACE(x...) ;
#endif
#define IDE_ISA_MODULE_NAME "busses/ide/ide_isa/driver_v1"
// 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"
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;
device_node *node;
} channel_info;
/*! publish node of an ide channel */
static status_t
publish_channel(device_node *parent, uint16 command_block_base,
uint16 control_block_base, uint8 intnum, const char *name)
{
device_attr attrs[] = {
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
// 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?
{ B_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1 }},
{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
// 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 }
};
io_resource resources[3] = {
{ B_IO_PORT, command_block_base, 8 },
{ B_IO_PORT, control_block_base, 1 },
{}
};
TRACE("publishing %s, resources %#x %#x %d\n",
name, command_block_base, control_block_base, intnum);
return pnp->register_node(parent, IDE_ISA_MODULE_NAME, attrs, resources,
NULL);
}
// #pragma mark -
static void
set_channel(void *cookie, ide_channel ideChannel)
{
channel_info *channel = cookie;
channel->ide_channel = ideChannel;
}
static status_t
write_command_block_regs(void *channel_cookie, ide_task_file *tf,
ide_reg_mask mask)
{
channel_info *channel = channel_cookie;
uint16 ioaddr = channel->command_block_base;
int i;
if (channel->lost)
return B_ERROR;
for (i = 0; i < 7; i++) {
if (((1 << (i + 7)) & mask) != 0) {
TRACE("write_command_block_regs(): %x->HI(%x)\n",
tf->raw.r[i + 7], i);
channel->isa->write_io_8(ioaddr + 1 + i, tf->raw.r[i + 7]);
}
if (((1 << i) & mask) != 0 ) {
TRACE("write_comamnd_block_regs(): %x->LO(%x)\n", 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(void *channel_cookie, ide_task_file *tf,
ide_reg_mask mask)
{
channel_info *channel = channel_cookie;
uint16 ioaddr = channel->command_block_base;
int i;
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);
TRACE("read_command_block_regs(%x): %x\n", i, (int)tf->raw.r[i]);
}
}
return B_OK;
}
static uint8
get_altstatus(void *channel_cookie)
{
channel_info *channel = channel_cookie;
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(void *channel_cookie, uint8 val)
{
channel_info *channel = channel_cookie;
uint16 device_control_addr = channel->control_block_base;
TRACE("write_device_control(%x)\n", (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(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
channel_info *channel = channel_cookie;
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(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
channel_info *channel = channel_cookie;
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;
TRACE("interrupt handler()\n");
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(void *channel_cookie, const physical_entry *sg_list,
size_t sg_list_count, bool write)
{
return B_NOT_ALLOWED;
}
static status_t
start_dma(void *channel_cookie)
{
return B_NOT_ALLOWED;
}
static status_t
finish_dma(void *channel_cookie)
{
return B_NOT_ALLOWED;
}
// #pragma mark -
static float
supports_device(device_node *parent)
{
const char *bus;
// make sure parent is really the ISA bus manager
if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
return B_ERROR;
if (strcmp(bus, "isa"))
return 0.0;
// 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
// controller, but who cares ;)
return 0.6;
}
static status_t
init_channel(device_node *node, void **_cookie)
{
channel_info *channel;
device_node *parent;
isa2_module_info *isa;
uint16 command_block_base, control_block_base;
uint8 irq;
status_t res;
TRACE("ISA-IDE: channel init\n");
// 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;
parent = pnp->get_parent_node(node);
pnp->get_driver(parent, (driver_module_info **)&isa, NULL);
pnp->put_node(parent);
channel = (channel_info *)malloc(sizeof(channel_info));
if (channel == NULL)
return B_NO_MEMORY;
TRACE("ISA-IDE: channel init, resources %#x %#x %d\n",
command_block_base, control_block_base, irq);
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 = NULL;
res = install_io_interrupt_handler(channel->intnum,
inthand, channel, 0);
if (res < 0) {
TRACE("ISA-IDE: couldn't install irq handler for int %d\n", 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);
return res;
}
static void
uninit_channel(void *channel_cookie)
{
channel_info *channel = channel_cookie;
TRACE("ISA-IDE: channel uninit\n");
// 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);
free(channel);
}
static status_t
register_device(device_node *parent)
{
status_t primaryStatus;
status_t secondaryStatus;
TRACE("register_device()\n");
// our parent device is the isa bus and all device drivers are Universal,
// so the pnp_manager tries each ISA driver in turn
primaryStatus = publish_channel(parent, 0x1f0, 0x3f6, 14,
"primary IDE channel");
secondaryStatus = publish_channel(parent, 0x170, 0x376, 15,
"secondary IDE channel");
if (primaryStatus == B_OK || secondaryStatus == B_OK)
return B_OK;
return primaryStatus;
}
static void
channel_removed(void *cookie)
{
channel_info *channel = cookie;
TRACE("channel_removed()\n");
// disable access instantly
atomic_or(&channel->lost, 1);
}
module_dependency module_dependencies[] = {
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
{}
};
// exported interface
static ide_controller_interface sISAControllerInterface = {
{
{
IDE_ISA_MODULE_NAME,
0,
NULL
},
supports_device,
register_device,
init_channel,
uninit_channel,
NULL, // register child devices
NULL, // rescan
channel_removed,
},
&set_channel,
&write_command_block_regs,
&read_command_block_regs,
&get_altstatus,
&write_device_control,
&write_pio_16,
&read_pio_16,
&prepare_dma,
&start_dma,
&finish_dma,
};
module_info *modules[] = {
(module_info *)&sISAControllerInterface,
NULL
};
@@ -1,8 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide it8211 ;
UsePrivateHeaders kernel ;
UsePrivateHeaders drivers ;
KernelAddon it8211 :
it8211.c
;
@@ -1,242 +0,0 @@
/*
* Copyright 2008, Michael Lotz. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <stdlib.h>
#include <string.h>
#include <ide_adapter.h>
#define IT8211_CONTROLLER_MODULE_NAME "busses/ide/it8211/driver_v1"
#define IT8211_CHANNEL_MODULE_NAME "busses/ide/it8211/channel/v1"
#define PCI_VENDOR_ITE 0x1283
#define PCI_DEVICE_ITE_IT8211 0x8211
static ide_adapter_interface *sIDEAdapter;
static device_manager_info *sDeviceManager;
static void
it8211_set_channel(void *channelCookie, ide_channel channel)
{
sIDEAdapter->set_channel((ide_adapter_channel_info *)channelCookie,
channel);
}
static status_t
it8211_write_command_block_regs(void *channelCookie, ide_task_file *taskFile,
ide_reg_mask registerMask)
{
return sIDEAdapter->write_command_block_regs(
(ide_adapter_channel_info *)channelCookie, taskFile, registerMask);
}
static status_t
it8211_read_command_block_regs(void *channelCookie, ide_task_file *taskFile,
ide_reg_mask registerMask)
{
return sIDEAdapter->read_command_block_regs(
(ide_adapter_channel_info *)channelCookie, taskFile, registerMask);
}
static uint8
it8211_get_altstatus(void *channelCookie)
{
return sIDEAdapter->get_altstatus((ide_adapter_channel_info *)channelCookie);
}
static status_t
it8211_write_device_control(void *channelCookie, uint8 value)
{
return sIDEAdapter->write_device_control(
(ide_adapter_channel_info *)channelCookie, value);
}
static status_t
it8211_write_pio(void *channelCookie, uint16 *data, int count, bool force16bit)
{
return sIDEAdapter->write_pio(
(ide_adapter_channel_info *)channelCookie, data, count, force16bit);
}
static status_t
it8211_read_pio(void *channelCookie, uint16 *data, int count, bool force16bit)
{
return sIDEAdapter->read_pio(
(ide_adapter_channel_info *)channelCookie, data, count, force16bit);
}
static status_t
it8211_prepare_dma(void *channelCookie, const physical_entry *sgList,
size_t sgListCount, bool toDevice)
{
return sIDEAdapter->prepare_dma((ide_adapter_channel_info *)channelCookie,
sgList, sgListCount, toDevice);
}
static status_t
it8211_start_dma(void *channelCookie)
{
return sIDEAdapter->start_dma((ide_adapter_channel_info *)channelCookie);
}
static status_t
it8211_finish_dma(void *channelCookie)
{
return sIDEAdapter->finish_dma((ide_adapter_channel_info *)channelCookie);
}
static status_t
init_channel(device_node *node, void **channelCookie)
{
return sIDEAdapter->init_channel(node,
(ide_adapter_channel_info **)channelCookie,
sizeof(ide_adapter_channel_info), sIDEAdapter->inthand);
}
static void
uninit_channel(void *channelCookie)
{
sIDEAdapter->uninit_channel((ide_adapter_channel_info *)channelCookie);
}
static void
channel_removed(void *channelCookie)
{
sIDEAdapter->channel_removed((ide_adapter_channel_info *)channelCookie);
}
static status_t
init_controller(device_node *node, void **cookie)
{
return sIDEAdapter->init_controller(node,
(ide_adapter_controller_info **)cookie,
sizeof(ide_adapter_controller_info));
}
static void
uninit_controller(void *cookie)
{
sIDEAdapter->uninit_controller((ide_adapter_controller_info *)cookie);
}
static void
controller_removed(void *cookie)
{
sIDEAdapter->controller_removed((ide_adapter_controller_info *)cookie);
}
static status_t
probe_controller(device_node *parent)
{
return sIDEAdapter->probe_controller(parent,
IT8211_CONTROLLER_MODULE_NAME, "it8211",
"ITE IT8211", IT8211_CHANNEL_MODULE_NAME,
true, /* DMA */
true, /* command queuing */
1, /* 16 bit alignment */
0xffff, /* 64k boundary */
0x10000, /* up to 64k per scatter/gather block */
false); /* no compatibility mode */
}
static float
supports_device(device_node *parent)
{
const char *bus;
uint16 vendorID;
uint16 deviceID;
if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorID, false) != B_OK
|| sDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, false) != B_OK) {
return -1.0f;
}
if (strcmp(bus, "pci") != 0 || vendorID != PCI_VENDOR_ITE
|| deviceID != PCI_DEVICE_ITE_IT8211)
return 0.0f;
return 1.0f;
}
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
{ IDE_ADAPTER_MODULE_NAME, (module_info **)&sIDEAdapter },
{}
};
// exported interface
static ide_controller_interface sChannelInterface = {
{
{
IT8211_CHANNEL_MODULE_NAME,
0,
NULL
},
NULL, // supports device
NULL, // register device
&init_channel,
&uninit_channel,
NULL, // register child devices
NULL, // rescan
&channel_removed
},
&it8211_set_channel,
&it8211_write_command_block_regs,
&it8211_read_command_block_regs,
&it8211_get_altstatus,
&it8211_write_device_control,
&it8211_write_pio,
&it8211_read_pio,
&it8211_prepare_dma,
&it8211_start_dma,
&it8211_finish_dma
};
static driver_module_info sControllerInterface = {
{
IT8211_CONTROLLER_MODULE_NAME,
0,
NULL
},
&supports_device,
&probe_controller,
&init_controller,
&uninit_controller,
NULL, // register child devices
NULL, // rescan
&controller_removed
};
module_info *modules[] = {
(module_info *)&sControllerInterface,
(module_info *)&sChannelInterface,
NULL
};
@@ -1,8 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide legacy_sata ;
UsePrivateHeaders drivers kernel ;
KernelAddon legacy_sata :
legacy_sata.c
;
@@ -1,403 +0,0 @@
/*
* Copyright 2007, Ithamar R. Adema. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <stdlib.h>
#include <string.h>
#include <device_manager.h>
#include <bus/IDE.h>
#include <ide_adapter.h>
#define DRIVER_PRETTY_NAME "Legacy SATA"
#define CONTROLLER_NAME DRIVER_PRETTY_NAME
#define CONTROLLER_MODULE_NAME "busses/ide/legacy_sata/driver_v1"
#define CHANNEL_MODULE_NAME "busses/ide/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))
/* XXX: To be moved to PCI.h */
#define PCI_command_interrupt 0x400
static const char * const kChannelNames[] = {
"Primary Channel", "Secondary Channel",
"Tertiary Channel", "Quaternary Channel"
};
static ide_for_controller_interface* ide;
static ide_adapter_interface* ide_adapter;
static device_manager_info* dm;
static float
controller_supports(device_node *parent)
{
uint16 vendor_id;
uint16 device_id;
status_t res;
const char *bus = NULL;
// get the bus (should be PCI)
if (dm->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK)
return B_ERROR;
if (strcmp(bus, "pci") != 0) {
return B_ERROR;
}
// get vendor and device ID
if ((res=dm->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendor_id, false)) != B_OK
|| (res=dm->get_attr_uint16(parent, B_DEVICE_ID, &device_id, false)) != B_OK) {
return res;
}
switch (ID(vendor_id, device_id)) {
/* VIA SATA chipsets */
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;
/* ALI SATA chipsets */
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;
/* NVidia NForce chipsets */
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");
dm->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);
/* Default PCI assigments */
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);
/* enable PCI interrupt */
pci->write_pci_config(device, PCI_command, 2,
pci->read_pci_config(device, PCI_command, 2) & ~PCI_command_interrupt);
if (vendor_id == PCI_vendor_NVIDIA) {
/* enable control access */
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):
/* newer SATA chips has resources in one BAR for each channel */
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 = ide_adapter->detect_controller(pci, device, parent, bus_master_base,
CONTROLLER_MODULE_NAME, "" /* XXX: unused: controller_driver_type*/, CONTROLLER_NAME, true,
true, 1, 0xffff, 0x10000, &controller_node);
// don't register if controller is already registered!
// (happens during rescan; registering new channels would kick out old channels)
if (res != B_OK)
goto err;
if (controller_node == NULL) {
res = B_IO_ERROR;
goto err;
}
// ignore errors during registration of channels - could be a simple rescan collision
for (index = 0; index < num_channels; index++) {
res = ide_adapter->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 ide_adapter->init_controller(
node, (ide_adapter_controller_info**)controller_cookie,
sizeof(ide_adapter_controller_info));
}
static void
controller_uninit(void *controller_cookie)
{
ide_adapter->uninit_controller(controller_cookie);
}
static void
controller_removed(void *controller_cookie)
{
ide_adapter->controller_removed(
(ide_adapter_controller_info*)controller_cookie);
}
static status_t
channel_init(device_node *node, void **channel_cookie)
{
return ide_adapter->init_channel(node,
(ide_adapter_channel_info**)channel_cookie,
sizeof(ide_adapter_channel_info),
ide_adapter->inthand);
}
static void
channel_uninit(void *channel_cookie)
{
ide_adapter->uninit_channel(channel_cookie);
}
static void
channel_removed(void *channel_cookie)
{
ide_adapter->channel_removed(channel_cookie);
}
static void
channel_set(void *cookie, ide_channel channel)
{
ide_adapter->set_channel((ide_adapter_channel_info *)cookie, channel);
}
static status_t
task_file_write(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->write_command_block_regs(channel_cookie,tf,mask);
}
static status_t
task_file_read(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->read_command_block_regs(channel_cookie,tf,mask);
}
static uint8
altstatus_read(void *channel_cookie)
{
return ide_adapter->get_altstatus(channel_cookie);
}
static status_t
device_control_write(void *channel_cookie, uint8 val)
{
return ide_adapter->write_device_control(channel_cookie,val);
}
static status_t
pio_write(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->write_pio(channel_cookie,data,count,force_16bit);
}
static status_t
pio_read(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->read_pio(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 ide_adapter->prepare_dma(channel_cookie,sg_list,sg_list_count,write);
}
static status_t
dma_start(void *channel_cookie)
{
return ide_adapter->start_dma(channel_cookie);
}
static status_t
dma_finish(void *channel_cookie)
{
return ide_adapter->finish_dma(channel_cookie);
}
module_dependency module_dependencies[] = {
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&dm },
{ IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
{}
};
static ide_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
},
.init_driver = &controller_init,
.uninit_driver = &controller_uninit,
.supports_device = &controller_supports,
.register_device = &controller_probe,
.device_removed = &controller_removed,
};
module_info *modules[] = {
(module_info *)&sControllerInterface,
(module_info *)&sChannelInterface,
NULL
};
@@ -1,7 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide promise_tx2 ;
UsePrivateHeaders drivers kernel ;
KernelAddon promise_tx2 :
promise_tx2.c
;
@@ -1,378 +0,0 @@
/*
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
/*
Promise TX2 series IDE controller 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 "PROMISE TX2 -- "
#include "wrapper.h"
#define PROMISE_TX2_CONTROLLER_MODULE_NAME "busses/ide/promise_tx2/device_v1"
#define PROMISE_TX2_CHANNEL_MODULE_NAME "busses/ide/promise_tx2/channel/v1"
static ide_for_controller_interface *ide;
static ide_adapter_interface *ide_adapter;
static device_manager_info *pnp;
static status_t
write_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->write_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
}
static status_t
read_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
{
return ide_adapter->read_command_block_regs((ide_adapter_channel_info *)channel_cookie, tf, mask);
}
static uint8
get_altstatus(void *channel_cookie)
{
return ide_adapter->get_altstatus((ide_adapter_channel_info *)channel_cookie);
}
static status_t
write_device_control(void *channel_cookie, uint8 val)
{
return ide_adapter->write_device_control((ide_adapter_channel_info *)channel_cookie, val);
}
static status_t
write_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->write_pio((ide_adapter_channel_info *)channel_cookie, data, count, force_16bit);
}
static status_t
read_pio(void *channel_cookie, uint16 *data, int count, bool force_16bit)
{
return ide_adapter->read_pio((ide_adapter_channel_info *)channel_cookie, 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(void *channel_cookie, const physical_entry *sg_list,
size_t sg_list_count, bool to_device)
{
return ide_adapter->prepare_dma((ide_adapter_channel_info *)channel_cookie, sg_list, sg_list_count, to_device);
}
static status_t
start_dma(void *channel_cookie)
{
return ide_adapter->start_dma((ide_adapter_channel_info *)channel_cookie);
}
static status_t
finish_dma(void *channel_cookie)
{
return ide_adapter->finish_dma((ide_adapter_channel_info *)channel_cookie);
}
static status_t
init_channel(device_node_handle node, ide_channel ide_channel,
void **channel_cookie)
{
return ide_adapter->init_channel(node, ide_channel, (ide_adapter_channel_info **)channel_cookie,
sizeof(ide_adapter_channel_info), inthand);
}
static status_t
uninit_channel(void *channel_cookie)
{
return ide_adapter->uninit_channel((ide_adapter_channel_info *)channel_cookie);
}
static void channel_removed(device_node_handle node, void *channel_cookie)
{
return ide_adapter->channel_removed(node, (ide_adapter_channel_info *)channel_cookie);
}
static status_t
init_controller(device_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(device_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(device_node_handle parent, uint16 bus_master_base, uint8 intnum,
io_resource_handle *resources, device_node_handle *node)
{
device_attr attrs[] = {
// info about ourself and our consumer
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: PROMISE_TX2_CONTROLLER_MODULE_NAME }},
// 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
{ B_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 3 }},
// one S/G block must not cross 64K boundary
{ B_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
// size of S/G block is 16 bits with zero being 64K
{ B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: 0x10000 }},
{ B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
{ ui32: IDE_ADAPTER_MAX_SG_COUNT }},
{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
// 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,
device_node_handle parent, uint16 bus_master_base, int8 intnum,
device_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(device_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;
device_node_handle controller_node, channels[2];
uint8 intnum;
status_t res;
SHOW_FLOW0(3, "");
if (pnp->init_driver(parent, NULL, (driver_module_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);
command_block_base[0] &= PCI_address_io_mask;
control_block_base[0] &= PCI_address_io_mask;
command_block_base[1] &= PCI_address_io_mask;
control_block_base[1] &= PCI_address_io_mask;
bus_master_base &= PCI_address_io_mask;
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,
0, "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,
1, "Secondary Channel", &channels[1], false);
pnp->uninit_driver(parent);
return B_OK;
err:
pnp->uninit_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 },
{ B_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
},
NULL, // supported devices
NULL,
(status_t (*)( device_node_handle , void *, void ** )) init_channel,
uninit_channel,
channel_removed
},
&write_command_block_regs,
&read_command_block_regs,
&get_altstatus,
&write_device_control,
&write_pio,
&read_pio,
&prepare_dma,
&start_dma,
&finish_dma,
};
static driver_module_info controller_interface = {
{
PROMISE_TX2_CONTROLLER_MODULE_NAME,
0,
std_ops
},
NULL,
probe_controller,
(status_t (*)(device_node_handle, void *, void **)) init_controller,
(status_t (*)(void *)) uninit_controller,
(void (*)(device_node_handle, void *)) controller_removed
};
module_info *modules[] = {
(module_info *)&controller_interface,
(module_info *)&channel_interface,
NULL
};
@@ -1,90 +0,0 @@
#ifndef _WRAPPER_H
#define _WRAPPER_H
#include <KernelExport.h>
#include <lock.h>
// benaphores
#define INIT_BEN(x, prefix) (mutex_init_etc(x, prefix, MUTEX_FLAG_CLONE_NAME), \
B_OK)
#define DELETE_BEN(x) mutex_destroy(x)
#define ACQUIRE_BEN(x) mutex_lock(x)
#define RELEASE_BEN(x) mutex_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 */
@@ -1,7 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel busses ide silicon_image_3112 ;
UsePrivateHeaders drivers kernel ;
KernelAddon silicon_image_3112 :
silicon_image_3112.c
;
@@ -1,898 +0,0 @@
/*
* Copyright 2006, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <stdlib.h>
#include <string.h>
#include <KernelExport.h>
#include <device_manager.h>
#include <bus/IDE.h>
#include <ide_adapter.h>
#define TRACE(x...) dprintf("si-3112: " x)
//#define FLOW(x...) dprintf("si-3112: " x)
#define FLOW(x...)
#define DRIVER_PRETTY_NAME "Silicon Image SATA"
#define CONTROLLER_NAME DRIVER_PRETTY_NAME
#define CONTROLLER_MODULE_NAME "busses/ide/silicon_image_3112/driver_v1"
#define CHANNEL_MODULE_NAME "busses/ide/silicon_image_3112/channel/v1"
enum asic_type {
ASIC_SI3112 = 0,
ASIC_SI3114 = 1,
};
#if 0
static const char *adapter_asic_names[] = {
"si3112",
"si3114",
NULL
};
#endif
static const struct {
uint16 channel_count;
uint32 mmio_bar_size;
} kASICData[2] = {
{ 2, 0x200 },
{ 4, 0x400 },
};
static const struct {
uint16 cmd;
uint16 ctl;
uint16 bmdma;
uint16 sien;
uint16 stat;
const char *name;
} kControllerChannelData[] = {
{ 0x80, 0x8A, 0x00, 0x148, 0xA0, "Primary Channel" },
{ 0xC0, 0xCA, 0x08, 0x1C8, 0xE0, "Secondary Channel" },
{ 0x280, 0x28A, 0x200, 0x348, 0x2A0, "Tertiary Channel" },
{ 0x2C0, 0x2CA, 0x208, 0x3C8, 0x2E0, "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))
struct channel_data;
typedef struct controller_data {
pci_device_module_info *pci;
pci_device *device;
device_node *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;
area_id mmio_area;
uint32 mmio_addr;
uint32 lost; // != 0 if device got removed, i.e. if it must not
// be accessed anymore
} controller_data;
typedef struct channel_data {
pci_device_module_info *pci;
device_node * node;
pci_device * device;
ide_channel ide_channel;
volatile uint8 * task_file;
volatile uint8 * control_block;
volatile uint8 * command_block;
volatile uint8 * dev_ctrl;
volatile uint8 * bm_status_reg;
volatile uint8 * bm_command_reg;
volatile uint32 * bm_prdt_address;
volatile uint32 * stat;
area_id prd_area;
prd_entry * prdt;
phys_addr_t prdt_phys;
uint32 dma_active;
uint32 lost;
} channel_data;
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);
static float
controller_supports(device_node *parent)
{
const char *bus;
uint16 vendorID;
uint16 deviceID;
// get the bus (should be PCI)
if (dm->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
|| strcmp(bus, "pci") != 0)
return B_ERROR;
// get vendor and device ID
if (dm->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, &vendorID, false) != B_OK
|| dm->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, false) != B_OK) {
return B_ERROR;
}
#define ID(v, d) (((v) << 16) | (d))
switch (ID(vendorID, deviceID)) {
case ID(0x1095, 0x0240):
case ID(0x1095, 0x3112):
case ID(0x1095, 0x3114):
case ID(0x1095, 0x3512):
case ID(0x1002, 0x436e): // ATI
case ID(0x1002, 0x4379): // ATI
case ID(0x1002, 0x437a): // ATI
break;
default:
return 0.0f;
}
TRACE("controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
return 0.8f;
}
static status_t
controller_probe(device_node *parent)
{
pci_device *device;
pci_device_module_info *pci;
uint32 mmioBase;
uint16 deviceID;
uint16 vendorID;
uint8 interruptNumber;
int asicIndex;
TRACE("controller_probe\n");
dm->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
deviceID = pci->read_pci_config(device, PCI_device_id, 2);
vendorID = pci->read_pci_config(device, PCI_vendor_id, 2);
interruptNumber = pci->read_pci_config(device, PCI_interrupt_line, 1);
mmioBase = pci->read_pci_config(device, PCI_base_registers + 20, 4)
& PCI_address_io_mask;
switch (ID(vendorID, deviceID)) {
case ID(0x1095, 0x0240):
case ID(0x1095, 0x3112):
case ID(0x1095, 0x3512):
case ID(0x1002, 0x436e): // ATI
case ID(0x1002, 0x4379): // ATI
case ID(0x1002, 0x437a): // ATI
asicIndex = ASIC_SI3112;
break;
case ID(0x1095, 0x3114):
asicIndex = ASIC_SI3114;
break;
default:
TRACE("unsupported asic\n");
return B_ERROR;
}
if (!mmioBase) {
TRACE("mmio not configured\n");
return B_ERROR;
}
if (interruptNumber == 0 || interruptNumber == 0xff) {
TRACE("irq not configured\n");
return B_ERROR;
}
{
io_resource resources[2] = {
{ B_IO_MEMORY, mmioBase, kASICData[asicIndex].mmio_bar_size },
{}
};
device_attr attrs[] = {
// 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: kASICData[asicIndex].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_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: 1}},
// one S/G block must not cross 64K boundary
{ B_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: 0xffff }},
// max size of S/G block is 16 bits with zero being 64K
{ B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: 0x10000 }},
{ B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
{ ui32: IDE_ADAPTER_MAX_SG_COUNT }},
{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
// private data to find controller
{ "silicon_image_3112/asic_index", B_UINT32_TYPE, { ui32: asicIndex }},
{ "silicon_image_3112/mmio_base", B_UINT32_TYPE, { ui32: mmioBase }},
{ "silicon_image_3112/int_num", B_UINT32_TYPE, { ui32: interruptNumber }},
{ NULL }
};
TRACE("publishing controller\n");
return dm->register_node(parent, CONTROLLER_MODULE_NAME, attrs,
resources, NULL);
}
}
static status_t
controller_init(device_node *node, void **_controllerCookie)
{
controller_data *controller;
device_node *parent;
pci_device_module_info *pci;
pci_device *device;
uint32 asicIndex;
uint32 mmioBase;
uint32 mmioAddr;
area_id mmioArea;
uint32 interruptNumber;
status_t res;
uint32 temp;
int i;
TRACE("controller_init\n");
if (dm->get_attr_uint32(node, "silicon_image_3112/asic_index", &asicIndex, false) != B_OK)
return B_ERROR;
if (dm->get_attr_uint32(node, "silicon_image_3112/mmio_base", &mmioBase, false) != B_OK)
return B_ERROR;
if (dm->get_attr_uint32(node, "silicon_image_3112/int_num", &interruptNumber, false) != B_OK)
return B_ERROR;
controller = malloc(sizeof(controller_data));
if (!controller)
return B_NO_MEMORY;
FLOW("controller %p\n", controller);
mmioArea = map_physical_memory("Silicon Image SATA regs", mmioBase,
kASICData[asicIndex].mmio_bar_size, B_ANY_KERNEL_ADDRESS, 0,
(void **)&mmioAddr);
if (mmioArea < B_OK) {
TRACE("controller_init: mapping memory failed\n");
free(controller);
return B_ERROR;
}
parent = dm->get_parent_node(node);
dm->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
dm->put_node(parent);
TRACE("asic %ld\n", asicIndex);
TRACE("int_num %ld\n", interruptNumber);
TRACE("mmio_addr %p\n", (void *)mmioAddr);
controller->pci = pci;
controller->device = device;
controller->node = node;
controller->asic_index = asicIndex;
controller->int_num = interruptNumber;
controller->mmio_area = mmioArea;
controller->mmio_addr = mmioAddr;
controller->lost = 0;
controller->channel_count = kASICData[asicIndex].channel_count;
for (i = 0; i < kASICData[asicIndex].channel_count; i++)
controller->channel[i] = 0;
if (asicIndex == ASIC_SI3114) {
// I put a magic spell on you
temp = *(volatile uint32 *)(mmioAddr + SI_BMDMA2);
*(volatile uint32 *)(mmioAddr + SI_BMDMA2) = temp | SI_INT_STEERING;
*(volatile uint32 *)(mmioAddr + SI_BMDMA2); // flush
}
// disable all sata phy interrupts
for (i = 0; i < kASICData[asicIndex].channel_count; i++)
*(volatile uint32 *)(mmioAddr + kControllerChannelData[i].sien) = 0;
*(volatile uint32 *)(mmioAddr + kControllerChannelData[0].sien); // flush
// install interrupt handler
res = install_io_interrupt_handler(interruptNumber, handle_interrupt,
controller, 0);
if (res < B_OK) {
TRACE("controller_init: installing interrupt handler failed\n");
delete_area(mmioArea);
free(controller);
return res;
}
// unmask interrupts
temp = *(volatile uint32 *)(mmioAddr + SI_SYSCFG);
temp &= (asicIndex == ASIC_SI3114) ? (~SI_MASK_4PORT) : (~SI_MASK_2PORT);
*(volatile uint32 *)(mmioAddr + SI_SYSCFG) = temp;
*(volatile uint32 *)(mmioAddr + SI_SYSCFG); // flush
*_controllerCookie = controller;
TRACE("controller_init success\n");
return B_OK;
}
static void
controller_uninit(void *controllerCookie)
{
controller_data *controller = controllerCookie;
uint32 temp;
TRACE("controller_uninit enter\n");
// disable interrupts
temp = *(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG);
temp |= (controller->asic_index == ASIC_SI3114) ? SI_MASK_4PORT : SI_MASK_2PORT;
*(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG) = temp;
*(volatile uint32 *)(controller->mmio_addr + SI_SYSCFG); // flush
remove_io_interrupt_handler(controller->int_num, handle_interrupt,
controller);
delete_area(controller->mmio_area);
free(controller);
TRACE("controller_uninit leave\n");
}
static status_t
controller_register_channels(void *cookie)
{
controller_data *controller = cookie;
int index;
// publish channel nodes
for (index = 0; index < kASICData[controller->asic_index].channel_count;
index++) {
device_attr attrs[] = {
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: DRIVER_PRETTY_NAME }},
// { PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: kControllerChannelData[channelIndex].name }},
{ B_DEVICE_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: index }},
{ NULL }
};
TRACE("publishing %s\n", kControllerChannelData[index].name);
dm->register_node(controller->node, CHANNEL_MODULE_NAME, attrs,
NULL, NULL);
}
return B_OK;
}
static void
controller_removed(void *controllerCookie)
{
controller_data *controller = controllerCookie;
controller->lost = 1;
}
// #pragma mark -
static status_t
channel_init(device_node *node, void **_channelCookie)
{
controller_data *controller;
device_node *parent;
channel_data *channel;
physical_entry entry;
size_t prdtSize;
uint32 channelIndex;
TRACE("channel_init enter\n");
channel = malloc(sizeof(channel_data));
if (!channel)
return B_NO_MEMORY;
if (dm->get_attr_uint32(node, "silicon_image_3112/chan_index", &channelIndex, false) != B_OK)
goto err;
#if 0
if (1 /* debug */){
uint8 bus, device, function;
uint16 vendorID, deviceID;
dm->get_attr_uint8(node, PCI_DEVICE_BUS_ITEM, &bus, true);
dm->get_attr_uint8(node, PCI_DEVICE_DEVICE_ITEM, &device, true);
dm->get_attr_uint8(node, PCI_DEVICE_FUNCTION_ITEM, &function, true);
dm->get_attr_uint16(node, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, true);
dm->get_attr_uint16(node, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, true);
TRACE("bus %3d, device %2d, function %2d: vendor %04x, device %04x\n",
bus, device, function, vendorID, deviceID);
}
#endif
TRACE("channel_index %ld\n", channelIndex);
TRACE("channel name: %s\n", kControllerChannelData[channelIndex].name);
TRACE("channel %p\n", channel);
parent = dm->get_parent_node(node);
dm->get_driver(parent, NULL, (void **)&controller);
dm->put_node(parent);
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
// TODO: Where's the handling for the 64 K boundary? create_area_etc() can be
// used.
prdtSize = (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, prdtSize, B_32_BIT_CONTIGUOUS, 0);
if (channel->prd_area < B_OK) {
TRACE("creating prd_area failed\n");
goto err;
}
get_memory_map(channel->prdt, prdtSize, &entry, 1);
channel->prdt_phys = entry.address;
channel->pci = controller->pci;
channel->device = controller->device;
channel->node = node;
channel->ide_channel = NULL;
channel->task_file = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].cmd + 1);
channel->control_block = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].ctl);
channel->command_block = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].cmd);
channel->dev_ctrl = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].ctl);
channel->bm_prdt_address = (volatile uint32 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_PRDT_ADDRESS);
channel->bm_status_reg = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_STATUS_REG);
channel->bm_command_reg = (volatile uint8 *)(controller->mmio_addr + kControllerChannelData[channelIndex].bmdma + IDE_BM_COMMAND_REG);
channel->stat = (volatile uint32 *)(controller->mmio_addr + kControllerChannelData[channelIndex].stat);
channel->lost = 0;
channel->dma_active = 0;
controller->channel[channelIndex] = channel;
// enable interrupts so the channel is ready to run
device_control_write(channel, ide_devctrl_bit3);
*_channelCookie = channel;
TRACE("channel_init leave\n");
return B_OK;
err:
free(channel);
return B_ERROR;
}
static void
channel_uninit(void *channelCookie)
{
channel_data *channel = channelCookie;
TRACE("channel_uninit enter\n");
// 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);
delete_area(channel->prd_area);
free(channel);
TRACE("channel_uninit leave\n");
}
static void
channel_removed(void *channelCookie)
{
channel_data *channel = channelCookie;
channel->lost = 1;
}
static void
set_channel(void *channelCookie, ide_channel ideChannel)
{
channel_data *channel = channelCookie;
channel->ide_channel = ideChannel;
}
static status_t
task_file_write(void *channelCookie, ide_task_file *tf, ide_reg_mask mask)
{
channel_data *channel = channelCookie;
int i;
FLOW("task_file_write\n");
if (channel->lost)
return B_ERROR;
for (i = 0; i < 7; i++) {
if( ((1 << (i+7)) & mask) != 0 ) {
FLOW("%x->HI(%x)\n", tf->raw.r[i + 7], i );
channel->task_file[i] = tf->raw.r[i + 7];
}
if (((1 << i) & mask) != 0) {
FLOW("%x->LO(%x)\n", tf->raw.r[i], i );
channel->task_file[i] = tf->raw.r[i];
}
}
*channel->dev_ctrl; // read altstatus to flush
return B_OK;
}
static status_t
task_file_read(void *channelCookie, ide_task_file *tf, ide_reg_mask mask)
{
channel_data *channel = channelCookie;
int i;
FLOW("task_file_read\n");
if (channel->lost)
return B_ERROR;
for (i = 0; i < 7; i++) {
if (((1 << i) & mask) != 0) {
tf->raw.r[i] = channel->task_file[i];
FLOW("%x: %x\n", i, (int)tf->raw.r[i] );
}
}
return B_OK;
}
static uint8
altstatus_read(void *channelCookie)
{
channel_data *channel = channelCookie;
FLOW("altstatus_read\n");
if (channel->lost)
return 0x01; // Error bit
return *channel->dev_ctrl;
}
static status_t
device_control_write(void *channelCookie, uint8 val)
{
channel_data *channel = channelCookie;
FLOW("device_control_write 0x%x\n", val);
if (channel->lost)
return B_ERROR;
*channel->dev_ctrl = val;
*channel->dev_ctrl; // read altstatus to flush
return B_OK;
}
static status_t
pio_write(void *channelCookie, uint16 *data, int count, bool force_16bit)
{
channel_data *channel = channelCookie;
if (channel->lost)
return B_ERROR;
FLOW("pio_write force_16bit = %d, (count & 1) = %d\n", force_16bit, (count & 1));
// The data port is only 8 bit wide in the command register block.
if ((count & 1) != 0 || force_16bit) {
volatile uint16 * base = (volatile uint16 *)channel->command_block;
for ( ; count > 0; --count)
*base = *(data++);
} else {
volatile uint32 * base = (volatile uint32 *)channel->command_block;
uint32 *cur_data = (uint32 *)data;
for ( ; count > 0; count -= 2 )
*base = *(cur_data++);
}
*channel->dev_ctrl; // read altstatus to flush
return B_OK;
}
static status_t
pio_read(void *channelCookie, uint16 *data, int count, bool force_16bit)
{
channel_data *channel = channelCookie;
if (channel->lost)
return B_ERROR;
FLOW("pio_read force_16bit = %d, (count & 1) = %d\n", force_16bit, (count & 1));
// The data port is only 8 bit wide in the command register block.
// We are memory mapped and read using 16 or 32 bit access from this 8 bit location.
if ((count & 1) != 0 || force_16bit) {
volatile uint16 * base = (volatile uint16 *)channel->command_block;
for ( ; count > 0; --count)
*(data++) = *base;
} else {
volatile uint32 * base = (volatile uint32 *)channel->command_block;
uint32 *cur_data = (uint32 *)data;
for ( ; count > 0; count -= 2 )
*(cur_data++) = *base;
}
return B_OK;
}
static status_t
dma_prepare(void *channelCookie, const physical_entry *sg_list,
size_t sg_list_count, bool write)
{
channel_data *channel = channelCookie;
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
prd_entry *prd = channel->prdt;
uint8 command;
uint8 status;
uint32 temp;
int i;
FLOW("dma_prepare enter\n");
for (i = sg_list_count - 1, prd = channel->prdt; i >= 0;
--i, ++prd, ++sg_list ) {
prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device,
(void*)(addr_t)sg_list->address));
// 0 means 64K - this is done automatically by discarding upper 16 bits
prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sg_list->size);
prd->EOT = i == 0;
FLOW("%x, %x, %d\n", (int)prd->address, prd->count, prd->EOT);
}
// XXX move this to chan init?
temp = (*channel->bm_prdt_address) & 3;
temp |= B_HOST_TO_LENDIAN_INT32(pci->ram_address(device,
(void *)(addr_t)channel->prdt_phys)) & ~3;
*channel->bm_prdt_address = temp;
*channel->dev_ctrl; // read altstatus to flush
// reset interrupt and error signal
status = *channel->bm_status_reg | IDE_BM_STATUS_INTERRUPT
| IDE_BM_STATUS_ERROR;
*channel->bm_status_reg = status;
*channel->dev_ctrl; // read altstatus to flush
// set data direction
command = *channel->bm_command_reg;
if (write)
command &= ~IDE_BM_COMMAND_READ_FROM_DEVICE;
else
command |= IDE_BM_COMMAND_READ_FROM_DEVICE;
*channel->bm_command_reg = command;
*channel->dev_ctrl; // read altstatus to flush
FLOW("dma_prepare leave\n");
return B_OK;
}
static status_t
dma_start(void *channelCookie)
{
channel_data *channel = channelCookie;
uint8 command;
FLOW("dma_start enter\n");
command = *channel->bm_command_reg | IDE_BM_COMMAND_START_STOP;
channel->dma_active = true;
*channel->bm_command_reg = command;
*channel->dev_ctrl; // read altstatus to flush
FLOW("dma_start leave\n");
return B_OK;
}
static status_t
dma_finish(void *channelCookie)
{
channel_data *channel = channelCookie;
uint8 command;
uint8 status;
FLOW("dma_finish enter\n");
command = *channel->bm_command_reg & ~IDE_BM_COMMAND_START_STOP;
channel->dma_active = false;
*channel->bm_command_reg = command;
status = *channel->bm_status_reg;
*channel->bm_status_reg = status | IDE_BM_STATUS_INTERRUPT
| IDE_BM_STATUS_ERROR;
*channel->dev_ctrl; // read altstatus to flush
if ((status & IDE_BM_STATUS_ERROR) != 0) {
FLOW("dma_finish: failed\n");
return B_ERROR;
}
if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
TRACE("dma_finish: transfer aborted\n");
return B_ERROR;
} else {
TRACE("dma_finish: buffer underrun\n");
return B_DEV_DATA_UNDERRUN;
}
} else {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
TRACE("dma_finish: buffer too large\n");
return B_DEV_DATA_OVERRUN;
} else {
FLOW("dma_finish leave\n");
return B_OK;
}
}
}
static int32
handle_interrupt(void *arg)
{
controller_data *controller = arg;
uint8 status;
int32 result, ret;
int i;
// FLOW("handle_interrupt\n");
result = B_UNHANDLED_INTERRUPT;
for (i = 0; i < controller->channel_count; i++) {
channel_data *channel = controller->channel[i];
if (!channel || channel->lost)
continue;
if (channel->dma_active) {
if ((*channel->bm_status_reg & IDE_BM_STATUS_INTERRUPT) == 0)
continue;
} else {
// for PIO, read the "Task File Configuration + Status" Interrupt
// status
if (!(*channel->stat & (1 << 11)))
continue;
}
// acknowledge IRQ
status = *(channel->command_block + 7);
ret = ide->irq_handler(channel->ide_channel, status);
if (ret == B_INVOKE_SCHEDULER || result == B_UNHANDLED_INTERRUPT)
result = ret;
}
return result;
}
module_dependency module_dependencies[] = {
{ IDE_FOR_CONTROLLER_MODULE_NAME, (module_info **)&ide },
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&dm },
{ IDE_ADAPTER_MODULE_NAME, (module_info **)&ide_adapter },
{}
};
static ide_controller_interface sChannelInterface = {
{
{
CHANNEL_MODULE_NAME,
0,
NULL
},
.supports_device = NULL,
.register_device = NULL,
.init_driver = &channel_init,
.uninit_driver = &channel_uninit,
.register_child_devices = NULL,
.device_removed = &channel_removed,
},
.set_channel = &set_channel,
.write_command_block_regs = &task_file_write,
.read_command_block_regs = &task_file_read,
.get_altstatus = &altstatus_read,
.write_device_control = &device_control_write,
.write_pio = &pio_write,
.read_pio = &pio_read,
.prepare_dma = &dma_prepare,
.start_dma = &dma_start,
.finish_dma = &dma_finish,
};
static driver_module_info sControllerInterface = {
{
CONTROLLER_MODULE_NAME,
0,
NULL
},
.supports_device = &controller_supports,
.register_device = &controller_probe,
.init_driver = &controller_init,
.uninit_driver = &controller_uninit,
.register_child_devices = &controller_register_channels,
.device_removed = &controller_removed,
};
module_info *modules[] = {
(module_info *)&sControllerInterface,
(module_info *)&sChannelInterface,
NULL
};
-1
View File
@@ -4,7 +4,6 @@ SubInclude HAIKU_TOP src add-ons kernel generic ata_adapter ;
SubInclude HAIKU_TOP src add-ons kernel generic atomizer ; SubInclude HAIKU_TOP src add-ons kernel generic atomizer ;
SubInclude HAIKU_TOP src add-ons kernel generic bios ; SubInclude HAIKU_TOP src add-ons kernel generic bios ;
SubInclude HAIKU_TOP src add-ons kernel generic dpc ; SubInclude HAIKU_TOP src add-ons kernel generic dpc ;
SubInclude HAIKU_TOP src add-ons kernel generic ide_adapter ;
SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ; SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ;
SubInclude HAIKU_TOP src add-ons kernel generic mpu401 ; SubInclude HAIKU_TOP src add-ons kernel generic mpu401 ;
SubInclude HAIKU_TOP src add-ons kernel generic scsi_periph ; SubInclude HAIKU_TOP src add-ons kernel generic scsi_periph ;
@@ -1,8 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel generic ide_adapter ;
UsePrivateHeaders drivers kernel ;
KernelAddon ide_adapter :
ide_adapter.cpp
;
@@ -1,845 +0,0 @@
/*
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
* Distributed under the terms of the MIT License.
*/
/*
Generic IDE adapter library.
The correct name would be ATA adapter, but I chose the old name as it's
more widely known.
*/
#include <KernelExport.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <device_manager.h>
#include <bus/PCI.h>
#include <bus/IDE.h>
#include <ide_types.h>
#include <ide_adapter.h>
#include <lendian_bitfield.h>
#define debug_level_flow 0
#define debug_level_error 3
#define debug_level_info 3
#define DEBUG_MSG_PREFIX "IDE PCI -- "
#include "wrapper.h"
#define TRACE dprintf
static ide_for_controller_interface *ide;
static device_manager_info *pnp;
static void
set_channel(ide_adapter_channel_info *channel, ide_channel ideChannel)
{
channel->ideChannel = ideChannel;
}
static status_t
ide_adapter_write_command_block_regs(ide_adapter_channel_info *channel,
ide_task_file *tf, ide_reg_mask mask)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
int i;
uint16 ioaddr = channel->command_block_base;
if (channel->lost)
return B_ERROR;
for (i = 0; i < 7; i++) {
// LBA48 registers must be written twice
if (((1 << (i + 7)) & mask) != 0) {
SHOW_FLOW( 4, "%x->HI(%x)", tf->raw.r[i + 7], i );
pci->write_io_8(device, ioaddr + 1 + i, tf->raw.r[i + 7]);
}
if (((1 << i) & mask) != 0) {
SHOW_FLOW( 4, "%x->LO(%x)", tf->raw.r[i], i );
pci->write_io_8(device, ioaddr + 1 + i, tf->raw.r[i]);
}
}
return B_OK;
}
static status_t
ide_adapter_read_command_block_regs(ide_adapter_channel_info *channel,
ide_task_file *tf, ide_reg_mask mask)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
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] = pci->read_io_8(device, ioaddr + 1 + i);
SHOW_FLOW( 4, "%x: %x", i, (int)tf->raw.r[i] );
}
}
return B_OK;
}
static uint8
ide_adapter_get_altstatus(ide_adapter_channel_info *channel)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint16 altstatusaddr = channel->control_block_base;
if (channel->lost)
return 0x01; // Error bit
return pci->read_io_8(device, altstatusaddr);
}
static status_t
ide_adapter_write_device_control(ide_adapter_channel_info *channel, uint8 val)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint16 device_control_addr = channel->control_block_base;
SHOW_FLOW(3, "%x", (int)val);
if (channel->lost)
return B_ERROR;
pci->write_io_8(device, device_control_addr, val);
return B_OK;
}
static status_t
ide_adapter_write_pio(ide_adapter_channel_info *channel, uint16 *data,
int count, bool force_16bit)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
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)
pci->write_io_16(device, ioaddr, *(data++));
} else {
uint32 *cur_data = (uint32 *)data;
for (; count > 0; count -= 2)
pci->write_io_32(device, ioaddr, *(cur_data++));
}
return B_OK;
}
static status_t
ide_adapter_read_pio(ide_adapter_channel_info *channel, uint16 *data,
int count, bool force_16bit)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
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++) = pci->read_io_16(device, ioaddr );
} else {
uint32 *cur_data = (uint32 *)data;
for (; count > 0; count -= 2)
*(cur_data++) = pci->read_io_32(device, ioaddr);
}
return B_OK;
}
static int32
ide_adapter_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;
uint8 status;
SHOW_FLOW0(3, "");
if (channel->lost)
return B_UNHANDLED_INTERRUPT;
// add test whether this is really our IRQ
if (channel->dmaing) {
// in DMA mode, there is a safe test
// in PIO mode, this don't work
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
if ((status & IDE_BM_STATUS_INTERRUPT) == 0)
return B_UNHANDLED_INTERRUPT;
}
// acknowledge IRQ
status = pci->read_io_8(device, channel->command_block_base + 7);
return ide->irq_handler(channel->ideChannel, status);
}
static status_t
ide_adapter_prepare_dma(ide_adapter_channel_info *channel,
const physical_entry *sgList, size_t sgListCount, bool writeToDevice)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 command;
uint8 status;
prd_entry *prd = channel->prdt;
int i;
for (i = sgListCount - 1, prd = channel->prdt; i >= 0; --i, ++prd, ++sgList) {
prd->address = B_HOST_TO_LENDIAN_INT32(pci->ram_address(device,
(void*)(addr_t)sgList->address));
// 0 means 64K - this is done automatically be discarding upper 16 bits
prd->count = B_HOST_TO_LENDIAN_INT16((uint16)sgList->size);
prd->EOT = i == 0;
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->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));
// reset interrupt and error signal
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG) | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
pci->write_io_8(device,
channel->bus_master_base + IDE_BM_STATUS_REG, status);
// set data direction
command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
if (writeToDevice)
command &= ~IDE_BM_COMMAND_READ_FROM_DEVICE;
else
command |= IDE_BM_COMMAND_READ_FROM_DEVICE;
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
return B_OK;
}
static status_t
ide_adapter_start_dma(ide_adapter_channel_info *channel)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 command;
command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
command |= IDE_BM_COMMAND_START_STOP;
channel->dmaing = true;
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
return B_OK;
}
static status_t
ide_adapter_finish_dma(ide_adapter_channel_info *channel)
{
pci_device_module_info *pci = channel->pci;
pci_device *device = channel->device;
uint8 command;
uint8 status, newStatus;
command = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_COMMAND_REG);
command &= ~IDE_BM_COMMAND_START_STOP;
channel->dmaing = false;
pci->write_io_8(device, channel->bus_master_base + IDE_BM_COMMAND_REG,
command);
status = pci->read_io_8(device, channel->bus_master_base
+ IDE_BM_STATUS_REG);
// reset interrupt/error flags
newStatus = status | IDE_BM_STATUS_INTERRUPT | IDE_BM_STATUS_ERROR;
pci->write_io_8(device, channel->bus_master_base + IDE_BM_STATUS_REG,
newStatus);
if ((status & IDE_BM_STATUS_ERROR) != 0)
return B_ERROR;
if ((status & IDE_BM_STATUS_INTERRUPT) == 0) {
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer aborted" );
return B_ERROR;
}
SHOW_ERROR0( 2, "DMA transfer: buffer underrun" );
return B_DEV_DATA_UNDERRUN;
}
if ((status & IDE_BM_STATUS_ACTIVE) != 0) {
SHOW_ERROR0( 2, "DMA transfer: buffer too large" );
return B_DEV_DATA_OVERRUN;
}
return B_OK;
}
static status_t
ide_adapter_init_channel(device_node *node,
ide_adapter_channel_info **cookie, size_t total_data_size,
int32 (*inthand)(void *arg))
{
ide_adapter_controller_info *controller;
ide_adapter_channel_info *channel;
uint16 command_block_base, control_block_base;
uint8 intnum;
int prdt_size;
physical_entry pe[1];
uint8 channel_index;
status_t res;
TRACE("PCI-IDE: init channel...\n");
#if 0
if (1 /* debug */){
uint8 bus, device, function;
uint16 vendorID, deviceID;
pnp->get_attr_uint8(node, PCI_DEVICE_BUS_ITEM, &bus, true);
pnp->get_attr_uint8(node, PCI_DEVICE_DEVICE_ITEM, &device, true);
pnp->get_attr_uint8(node, PCI_DEVICE_FUNCTION_ITEM, &function, true);
pnp->get_attr_uint16(node, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, true);
pnp->get_attr_uint16(node, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, true);
TRACE("PCI-IDE: bus %3d, device %2d, function %2d: vendor %04x, device %04x\n",
bus, device, function, vendorID, deviceID);
}
#endif
// get device data
if (pnp->get_attr_uint16(node, IDE_ADAPTER_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK
|| pnp->get_attr_uint16(node, IDE_ADAPTER_CONTROL_BLOCK_BASE, &control_block_base, false) != B_OK
|| pnp->get_attr_uint8(node, IDE_ADAPTER_INTNUM, &intnum, true) != B_OK
|| pnp->get_attr_uint8(node, IDE_ADAPTER_CHANNEL_INDEX, &channel_index, false) != B_OK)
return B_ERROR;
{
device_node *parent = pnp->get_parent_node(node);
pnp->get_driver(parent, NULL, (void **)&controller);
pnp->put_node(parent);
}
channel = (ide_adapter_channel_info *)malloc(total_data_size);
if (channel == NULL) {
res = B_NO_MEMORY;
goto err;
}
TRACE("PCI-IDE: channel index %d\n", channel_index);
channel->node = node;
channel->pci = controller->pci;
channel->device = controller->device;
channel->lost = false;
channel->command_block_base = command_block_base;
channel->control_block_base = control_block_base;
channel->bus_master_base = controller->bus_master_base + (channel_index * 8);
channel->intnum = intnum;
channel->dmaing = false;
channel->inthand = inthand;
TRACE("PCI-IDE: bus master base %#x\n", channel->bus_master_base);
// PRDT must be contiguous, dword-aligned and must not cross 64K boundary
// TODO: Where's the handling for the 64 K boundary? create_area_etc() can be
// used.
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_32_BIT_CONTIGUOUS, 0);
if (channel->prd_area < B_OK) {
res = channel->prd_area;
goto err2;
}
get_memory_map(channel->prdt, prdt_size, pe, 1);
channel->prdt_phys = (uint32)pe[0].address;
SHOW_FLOW(3, "virt=%p, phys=%x", channel->prdt, (int)channel->prdt_phys);
res = install_io_interrupt_handler(channel->intnum,
inthand, channel, 0);
if (res < 0) {
SHOW_ERROR(0, "couldn't install irq handler @%d", channel->intnum);
goto err3;
}
TRACE("PCI-IDE: init channel done\n");
// enable interrupts so the channel is ready to run
ide_adapter_write_device_control(channel, ide_devctrl_bit3);
*cookie = channel;
return B_OK;
err3:
delete_area(channel->prd_area);
err2:
err:
free(channel);
return res;
}
static void
ide_adapter_uninit_channel(ide_adapter_channel_info *channel)
{
// disable IRQs
ide_adapter_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, channel->inthand, channel);
delete_area(channel->prd_area);
free(channel);
}
static void
ide_adapter_channel_removed(ide_adapter_channel_info *channel)
{
SHOW_FLOW0( 3, "" );
if (channel != NULL)
// disable access instantly
atomic_or((int32*)&channel->lost, 1);
}
/** publish node of ide channel */
static status_t
ide_adapter_publish_channel(device_node *controller_node,
const char *channel_module_name, uint16 command_block_base,
uint16 control_block_base, uint8 intnum, bool can_dma,
uint8 channel_index, const char *name, const io_resource *resources,
device_node **node)
{
char prettyName[25];
sprintf(prettyName, "IDE Channel %" B_PRIu8, channel_index);
device_attr attrs[] = {
// info about ourself and our consumer
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
{ string: prettyName }},
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
{ string: IDE_FOR_CONTROLLER_MODULE_NAME }},
// private data to identify channel
{ IDE_ADAPTER_COMMAND_BLOCK_BASE, B_UINT16_TYPE,
{ ui16: command_block_base }},
{ IDE_ADAPTER_CONTROL_BLOCK_BASE, B_UINT16_TYPE,
{ ui16: control_block_base }},
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: can_dma }},
{ IDE_ADAPTER_INTNUM, B_UINT8_TYPE, { ui8: intnum }},
{ IDE_ADAPTER_CHANNEL_INDEX, B_UINT8_TYPE, { ui8: channel_index }},
{ NULL }
};
SHOW_FLOW0(2, "");
return pnp->register_node(controller_node, channel_module_name, attrs,
resources, node);
}
/** detect IDE channel */
static status_t
ide_adapter_detect_channel(pci_device_module_info *pci, pci_device *pci_device,
device_node *controller_node, const char *channel_module_name,
bool controller_can_dma, uint16 command_block_base, uint16 control_block_base,
uint16 bus_master_base, uint8 intnum, uint8 channel_index, const char *name,
device_node **node, bool supports_compatibility_mode)
{
uint8 api;
SHOW_FLOW0( 3, "" );
// if channel works in compatibility mode, addresses and interrupt are fixed
api = pci->read_pci_config(pci_device, PCI_class_api, 1);
if (supports_compatibility_mode
&& channel_index == 0 && (api & PCI_ide_primary_native) == 0) {
command_block_base = 0x1f0;
control_block_base = 0x3f6;
intnum = 14;
TRACE("PCI-IDE: Controller in legacy mode: cmd %#x, ctrl %#x, irq %d\n",
command_block_base, control_block_base, intnum);
} else if (supports_compatibility_mode
&& channel_index == 1 && (api & PCI_ide_secondary_native) == 0) {
command_block_base = 0x170;
control_block_base = 0x376;
intnum = 15;
TRACE("PCI-IDE: Controller in legacy mode: cmd %#x, ctrl %#x, irq %d\n",
command_block_base, control_block_base, intnum);
} else {
if (command_block_base == 0 || control_block_base == 0) {
TRACE("PCI-IDE: Command/Control Block base is not configured\n");
return B_ERROR;
}
if (intnum == 0 || intnum == 0xff) {
TRACE("PCI-IDE: Interrupt is not configured\n");
return B_ERROR;
}
// historically, they start at 3f6h/376h, but PCI spec requires registers
// to be aligned at 4 bytes, so only 3f4h/374h can be specified; thus
// PCI IDE defines that control block starts at offset 2
control_block_base += 2;
TRACE("PCI-IDE: Controller in native mode: cmd %#x, ctrl %#x, irq %d\n",
command_block_base, control_block_base, intnum);
}
if (supports_compatibility_mode) {
// read status of primary(!) channel to detect simplex
uint8 status = pci->read_io_8(pci_device, bus_master_base
+ IDE_BM_STATUS_REG);
if (status & IDE_BM_STATUS_SIMPLEX_DMA && channel_index != 0) {
// in simplex mode, channels cannot operate independantly of each other;
// 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
// bus manager, and I don't see any reason to add extra code for old
// simplex controllers
TRACE("PCI-IDE: Simplex controller - disabling DMA of secondary channel\n");
controller_can_dma = false;
}
}
{
io_resource resources[3] = {
{ B_IO_PORT, command_block_base, 8 },
{ B_IO_PORT, control_block_base, 1 },
{}
};
return ide_adapter_publish_channel(controller_node, channel_module_name,
command_block_base, control_block_base, intnum, controller_can_dma,
channel_index, name, resources, node);
}
}
static status_t
ide_adapter_init_controller(device_node *node,
ide_adapter_controller_info **cookie, size_t total_data_size)
{
pci_device_module_info *pci;
pci_device *device;
ide_adapter_controller_info *controller;
uint16 bus_master_base;
// uint16 pcicmd;
// get device data
if (pnp->get_attr_uint16(node, IDE_ADAPTER_BUS_MASTER_BASE, &bus_master_base, false) != B_OK)
return B_ERROR;
{
device_node *parent = pnp->get_parent_node(node);
pnp->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
pnp->put_node(parent);
}
controller = (ide_adapter_controller_info *)malloc(total_data_size);
if (controller == NULL)
return B_NO_MEMORY;
#if 0
pcicmd = pci->read_pci_config(node, PCI_command, 2);
TRACE("PCI-IDE: adapter init: pcicmd old setting 0x%04x\n", pcicmd);
if ((pcicmd & PCI_command_io) == 0) {
TRACE("PCI-IDE: adapter init: enabling io decoder\n");
pcicmd |= PCI_command_io;
}
if ((pcicmd & PCI_command_master) == 0) {
TRACE("PCI-IDE: adapter init: enabling bus mastering\n");
pcicmd |= PCI_command_master;
}
pci->write_pci_config(node, PCI_command, 2, pcicmd);
TRACE("PCI-IDE: adapter init: pcicmd new setting 0x%04x\n", pci->read_pci_config(node, PCI_command, 2));
#endif
controller->node = node;
controller->pci = pci;
controller->device = device;
controller->lost = false;
controller->bus_master_base = bus_master_base;
*cookie = controller;
return B_OK;
}
static void
ide_adapter_uninit_controller(ide_adapter_controller_info *controller)
{
free(controller);
}
static void
ide_adapter_controller_removed(ide_adapter_controller_info *controller)
{
SHOW_FLOW0(3, "");
if (controller != NULL) {
// disable access instantly; unit_device takes care of unregistering ioports
atomic_or((int32*)&controller->lost, 1);
}
}
/** publish node of ide controller */
static status_t
ide_adapter_publish_controller(device_node *parent, uint16 bus_master_base,
io_resource *resources, const char *controller_driver,
const char *controller_driver_type, const char *controller_name, bool can_dma,
bool can_cq, uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
device_node **node)
{
device_attr attrs[] = {
// 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: 2 }},
// of course we can DMA
{ IDE_CONTROLLER_CAN_DMA_ITEM, B_UINT8_TYPE, { ui8: can_dma }},
// command queuing always works (unless controller is buggy)
{ IDE_CONTROLLER_CAN_CQ_ITEM, B_UINT8_TYPE, { ui8: can_cq }},
// 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_DMA_ALIGNMENT, B_UINT32_TYPE, { ui32: dma_alignment /*1*/}},
// one S/G block must not cross 64K boundary
{ B_DMA_BOUNDARY, B_UINT32_TYPE, { ui32: dma_boundary/*0xffff*/ }},
// max size of S/G block is 16 bits with zero being 64K
{ B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE,
{ ui32: max_sg_block_size/*0x10000*/ }},
{ B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
{ ui32: IDE_ADAPTER_MAX_SG_COUNT }},
{ B_DMA_HIGH_ADDRESS, B_UINT64_TYPE, { ui64: 0x100000000LL }},
// private data to find controller
{ IDE_ADAPTER_BUS_MASTER_BASE, B_UINT16_TYPE, { ui16: bus_master_base }},
{ NULL }
};
SHOW_FLOW0( 2, "" );
return pnp->register_node(parent, controller_driver, attrs, resources, node);
}
/** detect pure IDE controller, i.e. without channels */
static status_t
ide_adapter_detect_controller(pci_device_module_info *pci, pci_device *pci_device,
device_node *parent, uint16 bus_master_base, const char *controller_driver,
const char *controller_driver_type, const char *controller_name, bool can_dma,
bool can_cq, uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
device_node **node)
{
io_resource resources[2] = {
{ B_IO_PORT, bus_master_base, 16 },
{}
};
SHOW_FLOW0( 3, "" );
if (bus_master_base == 0) {
TRACE("PCI-IDE: Controller detection failed! bus master base not configured\n");
return B_ERROR;
}
return ide_adapter_publish_controller(parent, bus_master_base, resources,
controller_driver, controller_driver_type, controller_name, can_dma, can_cq,
dma_alignment, dma_boundary, max_sg_block_size, node);
}
static status_t
ide_adapter_probe_controller(device_node *parent, const char *controller_driver,
const char *controller_driver_type, const char *controller_name,
const char *channel_module_name, bool can_dma, bool can_cq, uint32 dma_alignment,
uint32 dma_boundary, uint32 max_sg_block_size, bool supports_compatibility_mode)
{
pci_device_module_info *pci;
pci_device *device;
uint16 command_block_base[2];
uint16 control_block_base[2];
uint16 bus_master_base;
device_node *controller_node;
device_node *channels[2];
uint8 intnum;
status_t res;
SHOW_FLOW0( 3, "" );
pnp->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
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);
command_block_base[0] &= PCI_address_io_mask;
control_block_base[0] &= PCI_address_io_mask;
command_block_base[1] &= PCI_address_io_mask;
control_block_base[1] &= PCI_address_io_mask;
bus_master_base &= PCI_address_io_mask;
res = ide_adapter_detect_controller(pci, device, parent, bus_master_base,
controller_driver, controller_driver_type, controller_name, can_dma,
can_cq, dma_alignment, dma_boundary, max_sg_block_size, &controller_node);
// don't register if controller is already registered!
// (happens during rescan; registering new channels would kick out old channels)
if (res != B_OK || controller_node == NULL)
return res;
// ignore errors during registration of channels - could be a simple rescan collision
ide_adapter_detect_channel(pci, device, controller_node, channel_module_name,
can_dma, command_block_base[0], control_block_base[0], bus_master_base,
intnum, 0, "Primary Channel", &channels[0], supports_compatibility_mode);
ide_adapter_detect_channel(pci, device, controller_node, channel_module_name,
can_dma, command_block_base[1], control_block_base[1], bus_master_base,
intnum, 1, "Secondary Channel", &channels[1], supports_compatibility_mode);
return B_OK;
}
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 },
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
{}
};
static ide_adapter_interface adapter_interface = {
{
IDE_ADAPTER_MODULE_NAME,
0,
std_ops
},
set_channel,
ide_adapter_write_command_block_regs,
ide_adapter_read_command_block_regs,
ide_adapter_get_altstatus,
ide_adapter_write_device_control,
ide_adapter_write_pio,
ide_adapter_read_pio,
ide_adapter_prepare_dma,
ide_adapter_start_dma,
ide_adapter_finish_dma,
ide_adapter_inthand,
ide_adapter_init_channel,
ide_adapter_uninit_channel,
ide_adapter_channel_removed,
ide_adapter_publish_channel,
ide_adapter_detect_channel,
ide_adapter_init_controller,
ide_adapter_uninit_controller,
ide_adapter_controller_removed,
ide_adapter_publish_controller,
ide_adapter_detect_controller,
ide_adapter_probe_controller
};
module_info *modules[] = {
&adapter_interface.info,
NULL
};
@@ -1,90 +0,0 @@
#ifndef _WRAPPER_H
#define _WRAPPER_H
#include <KernelExport.h>
#include <lock.h>
// benaphores
#define INIT_BEN(x, prefix) (mutex_init_etc(x, prefix, MUTEX_FLAG_CLONE_NAME), \
B_OK)
#define DELETE_BEN(x) mutex_destroy(x)
#define ACQUIRE_BEN(x) mutex_lock(x)
#define RELEASE_BEN(x) mutex_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 4
#endif
#ifndef debug_level_info
# define debug_level_info 4
#endif
#ifndef debug_level_error
# define debug_level_error 4
#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%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%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%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%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%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%s: "format"\n", FUNC_NAME); DEBUG_WAIT_ERROR \
}} while( 0 )
#endif /* _BENAPHORE_H */