More headers for the new modules and PnP/device system - note, this

is a work in progress; the name as well as the contents will change :-)


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7769 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2004-06-06 23:52:08 +00:00
parent cc5bfcb2e9
commit 0d59a3d2a9
13 changed files with 2878 additions and 0 deletions

View File

@ -0,0 +1,29 @@
/*
** Copyright 2002-04, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open SCSI bus manager
Devfs entry for raw bus access.
This interface will go away. It's used by scsi_probe as
long as we have no proper pnpfs where all the info can
be retrieved from.
*/
#ifndef _SCSI_BUS_RAW_DRIVER_H
#define _SCSI_BUS_RAW_DRIVER_H
#include <Drivers.h>
// we start with +300 to not collide with any other SCSI opcode defined
// in scsiprobe_driver.h or scsi.h;
// all ioctl calls return the subsystem status (see SCSI.h)
enum {
B_SCSI_BUS_RAW_RESET = B_DEVICE_OP_CODES_END + 300,
B_SCSI_BUS_RAW_PATH_INQUIRY
};
#endif

102
headers/os/drivers/blkman.h Normal file
View File

@ -0,0 +1,102 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open block device manager
Block devices can be easily written by providing the interface
specified hereinafter. The block device manager takes care of
DMA and other restrictions imposed by underlying controller or
protocol and transparently handles transmission of partial blocks
by using a buffer (performance will suffer, though).
*/
#ifndef __BLKMAN_H__
#define __BLKMAN_H__
#include <KernelExport.h>
#include <device_manager.h>
// cookies issued by blkman
typedef struct blkman_device_info *blkman_device;
typedef struct blkman_handle_info *blkman_handle;
// cookies issued by device driver
typedef struct blkdev_device_cookie *blkdev_device_cookie;
typedef struct blkdev_handle_cookie *blkdev_handle_cookie;
// two reason why to use array of size 1:
// 1. zero-sized arrays aren't standard C
// 2. it's handy if you need a temporary global variable with num=1
typedef struct phys_vecs {
size_t num;
size_t total_len;
physical_entry vec[1];
} phys_vecs;
#define PHYS_VECS(name, size) \
uint8 name[sizeof(phys_vecs) + (size - 1)*sizeof(phys_vec)]; \
phys_vecs *name = (phys_vecs *)name
// Block Device Node
// attributes:
// type code for block devices
#define BLKDEV_TYPE_NAME "blkdev"
// if true, this device may be a BIOS drive (uint8, optional, default: false)
#define BLKDEV_IS_BIOS_DRIVE "blkdev/is_bios_drive"
// address bits that must be 0 - must be 2^i-1 for some i (uint32, optional, default: 0)
#define BLKDEV_DMA_ALIGNMENT "blkdev/dma_alignment"
// maximum number of blocks per transfer (uint32, optional, default: unlimited)
#define BLKDEV_MAX_BLOCKS_ITEM "blkdev/max_blocks"
// mask of bits that can change in one sg block (uint32, optional, default: ~0)
#define BLKDEV_DMA_BOUNDARY "blkdev/dma_boundary"
// maximum size of one block in scatter/gather list (uint32, optional, default: ~0)
#define BLKDEV_MAX_SG_BLOCK_SIZE "blkdev/max_sg_block_size"
// maximum number of scatter/gather blocks (uint32, optional, default: unlimited)
#define BLKDEV_MAX_SG_BLOCKS "blkdev/max_sg_blocks"
// interface to be provided by device driver
typedef struct blkdev_interface {
pnp_driver_info dinfo;
// iovecs are physical address here
// pos and num_blocks are in blocks; bytes_transferred in bytes
// vecs are guaranteed to describe enough data for given block count
status_t (*open)(blkdev_device_cookie device, blkdev_handle_cookie *handle);
status_t (*close)(blkdev_handle_cookie handle);
status_t (*free)(blkdev_handle_cookie handle);
status_t (*read)(blkdev_handle_cookie handle, const phys_vecs *vecs, off_t pos,
size_t num_blocks, uint32 block_size, size_t *bytes_transferred);
status_t (*write)(blkdev_handle_cookie handle, const phys_vecs *vecs, off_t pos,
size_t num_blocks, uint32 block_size, size_t *bytes_transferred);
status_t (*ioctl)(blkdev_handle_cookie handle, int op, void *buf, size_t len);
} blkdev_interface;
#define BLKMAN_MODULE_NAME "generic/blkman/v1"
// Interface for Drivers
// blkman interface used for callbacks done by driver
typedef struct blkman_for_driver_interface {
module_info minfo;
// block_size - block size in bytes
// ld_block_size - log2( block_size) (set to zero if block_size is not power of two)
// capacity - capacity in blocks
void (*set_media_params)(blkman_device device, uint32 block_size, uint32 ld_block_size,
uint64 capacity);
} blkman_for_driver_interface;
#define BLKMAN_FOR_DRIVER_MODULE_NAME "generic/blkman/driver/v1"
#endif

View File

@ -0,0 +1,363 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open IDE bus manager
IDE bus manager interface
*/
#ifndef __IDE_H__
#define __IDE_H__
#include <bus_manager.h>
#include <iovec.h>
#include <lendian_bitfield.h>
#include <device_manager.h>
#include <KernelExport.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.
typedef union {
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;
} 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
typedef 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 = 0x80 | ide_mask_sector_count,
ide_mask_LBA_low_48 = 0x100 | ide_mask_LBA_low,
ide_mask_LBA_mid_48 = 0x200 | ide_mask_LBA_mid,
ide_mask_LBA_high_48 = 0x400 | ide_mask_LBA_high,
ide_mask_HOB = 0x780
//ide_mask_all = 0x7f
} 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;
// Controller Driver Node
// attributes:
// node type
#define IDE_BUS_TYPE_NAME "bus/ide/v1"
// maximum number of devices connected to controller (uint8, optional, default:2)
#define IDE_CONTROLLER_MAX_DEVICES_ITEM "ide/max_devices"
// set to not-0 if DMA is supported (uint8, optional, default:0)
// (if so, publish necessary blkdev restriction too)
#define IDE_CONTROLLER_CAN_DMA_ITEM "ide/can_DMA"
// set to not-0 if CQ is supported (uint8, optional, default:1)
#define IDE_CONTROLLER_CAN_CQ_ITEM "ide/can_CQ"
// name of controller (string, required)
#define IDE_CONTROLLER_CONTROLLER_NAME_ITEM "ide/controller_name"
// interface of controller driver
typedef struct {
pnp_driver_info dinfo;
status_t (*write_command_block_regs)
(ide_channel_cookie channel, ide_task_file *tf, ide_reg_mask mask);
status_t (*read_command_block_regs)
(ide_channel_cookie channel, ide_task_file *tf, ide_reg_mask mask);
uint8 (*get_altstatus) (ide_channel_cookie channel);
status_t (*write_device_control) (ide_channel_cookie channel, uint8 val);
status_t (*write_pio) (ide_channel_cookie channel, uint16 *data, int count, bool force_16bit );
status_t (*read_pio) (ide_channel_cookie channel, uint16 *data, int count, bool force_16bit );
status_t (*prepare_dma)(ide_channel_cookie channel,
const physical_entry *sg_list, size_t sg_list_count,
bool write);
status_t (*start_dma)(ide_channel_cookie channel);
status_t (*finish_dma)(ide_channel_cookie channel);
} ide_controller_interface;
// channel cookie, issued by ide bus manager
typedef struct ide_bus_info *ide_channel;
// Interface for Controller Driver
// interface of bus manager as seen from controller driver
// use this interface as the fixed consumer of your controller driver
typedef struct {
pnp_driver_info dinfo;
// status - status read from controller (_not_ alt_status, as reading
// normal status acknowledges IRQ request of device)
status_t (*irq_handler)( ide_channel channel, uint8 status );
} ide_for_controller_interface;
#define IDE_FOR_CONTROLLER_MODULE_NAME "bus_managers/ide/controller/v1"
#endif

View File

@ -0,0 +1,72 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
ISA bus manager
This is an improper name - this bus manager uses the PnP manager to
load device drivers, but calling it ISA PnP manager would be wrong as
ISA PnP information isn't used at all.
All ISA drivers must be Universal driver (see pnp_manager.h), as they
are all direct children of the ISA bus node. Having an ISA PnP bus manager
(which we don't), one node would be created per ISA device and thus you
could write Specific drivers, but under normal ISA we don't even know
how many devices are there, therefore the Universal driver trick.
Apart from the loading, the main change is the resource manager. In
a driver, you must allocate the resources before registering the node and
deallocate it when your node is removed and if the driver isn't loaded at
this time. If it is, you must delay deallocation until the driver gets
unloaded to make sure no new driver touches the same resources like you
meanwhile.
*/
#ifndef _ISA2_H
#define _ISA2_H
#include <device_manager.h>
enum {
B_8_BIT_TRANSFER,
B_16_BIT_TRANSFER
};
// maximum size of one dma transfer
// (in bytes for 8 bit transfer, in words for 16 bit transfer)
#define B_MAX_ISA_DMA_COUNT 0x10000
typedef struct isa2_module_info {
pnp_bus_info binfo;
uint8 (*read_io_8)( int mapped_io_addr );
void (*write_io_8)( int mapped_io_addr, uint8 value );
uint16 (*read_io_16)( int mapped_io_addr );
void (*write_io_16)( int mapped_io_addr, uint16 value );
uint32 (*read_io_32)( int mapped_io_addr );
void (*write_io_32)( int mapped_io_addr, uint32 value );
// don't know what it's for, remains for compatibility
void *(*ram_address)( const void *physical_address_in_system_memory );
// start dma transfer (scattered DMA is not supported as it's EISA specific)
status_t (*start_isa_dma)(
long channel, // dma channel to use
void *buf, // buffer to transfer
long transfer_count, // # transfers
uchar mode, // mode flags
uchar e_mode // extended mode flags
);
} isa2_module_info;
// type of isa device
#define ISA_DEVICE_TYPE_NAME "isa/device/v1"
// directory of ISA drivers
// (there is only one device node, so put all drivers under "universal")
#define ISA_DRIVERS_DIR "isa"
#endif

View File

@ -0,0 +1,165 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
PCI bus manager
*/
#ifndef _PCI2_H
#define _PCI2_H
#include <device_manager.h>
//#include "r5_wrapper.h"
#include <PCI.h>
// currently, this structure is disables to avoid collision with R5 header
#if 0
typedef struct pci_info {
ushort vendor_id; /* vendor id */
ushort device_id; /* device id */
uchar bus; /* bus number */
uchar device; /* device number on bus */
uchar function; /* function number in device */
uchar revision; /* revision id */
uchar class_api; /* specific register interface type */
uchar class_sub; /* specific device function */
uchar class_base; /* device type (display vs network, etc) */
uchar line_size; /* cache line size in 32 bit words */
uchar latency; /* latency timer */
uchar header_type; /* header type */
uchar bist; /* built-in self-test */
uchar reserved; /* filler, for alignment */
union {
struct {
ulong cardbus_cis; /* CardBus CIS pointer */
ushort subsystem_id; /* subsystem (add-in card) id */
ushort subsystem_vendor_id; /* subsystem (add-in card) vendor id */
ulong rom_base; /* rom base address, viewed from host */
ulong rom_base_pci; /* rom base addr, viewed from pci */
ulong rom_size; /* rom size */
ulong base_registers[6]; /* base registers, viewed from host */
ulong base_registers_pci[6]; /* base registers, viewed from pci */
ulong base_register_sizes[6]; /* size of what base regs point to */
uchar base_register_flags[6]; /* flags from base address fields */
uchar interrupt_line; /* interrupt line */
uchar interrupt_pin; /* interrupt pin */
uchar min_grant; /* burst period @ 33 Mhz */
uchar max_latency; /* how often PCI access needed */
} h0;
struct {
ulong base_registers[2]; /* base registers, viewed from host */
ulong base_registers_pci[2]; /* base registers, viewed from pci */
ulong base_register_sizes[2]; /* size of what base regs point to */
uchar base_register_flags[2]; /* flags from base address fields */
uchar primary_bus;
uchar secondary_bus;
uchar subordinate_bus;
uchar secondary_latency;
uchar io_base;
uchar io_limit;
ushort secondary_status;
ushort memory_base;
ushort memory_limit;
ushort prefetchable_memory_base;
ushort prefetchable_memory_limit;
ulong prefetchable_memory_base_upper32;
ulong prefetchable_memory_limit_upper32;
ushort io_base_upper16;
ushort io_limit_upper16;
ulong rom_base; /* rom base address, viewed from host */
ulong rom_base_pci; /* rom base addr, viewed from pci */
uchar interrupt_line; /* interrupt line */
uchar interrupt_pin; /* interrupt pin */
ushort bridge_control;
} h1;
} u;
} pci_info;
#endif
typedef struct pci_device_info *pci_device;
// Interface to one PCI device.
// Actually, this is a _function_ of a device only, but
// pci_function_module_info would be a bit non-intuitive
typedef struct pci_device_module_info {
pnp_driver_info dinfo;
uint8 (*read_io_8) (pci_device device, int mapped_io_addr);
void (*write_io_8) (pci_device device, int mapped_io_addr, uint8 value);
uint16 (*read_io_16) (pci_device device, int mapped_io_addr);
void (*write_io_16) (pci_device device, int mapped_io_addr, uint16 value);
uint32 (*read_io_32) (pci_device device, int mapped_io_addr);
void (*write_io_32) (pci_device device, int mapped_io_addr, uint32 value);
uint32 (*read_pci_config) (
pci_device device,
uchar offset, /* offset in configuration space */
uchar size /* # bytes to read (1, 2 or 4) */
);
void (*write_pci_config) (
pci_device device,
uchar offset, /* offset in configuration space */
uchar size, /* # bytes to write (1, 2 or 4) */
uint32 value /* value to write */
);
void * (*ram_address) (pci_device device, const void *physical_address_in_system_memory);
/* status_t (*allocate_iomem)( void *base, size_t len, const char *name );
status_t (*release_iomem)( void *base, size_t len );
status_t (*allocate_ioports)( uint16 ioport_base, size_t len, const char *name );
status_t (*release_ioports)( uint16 ioport_base, size_t len );*/
} pci_device_module_info;
// type of PCI device
#define PCI_DEVICE_TYPE_NAME "pci/device/v1"
// directory of PCI drivers
#define PCI_DRIVERS_DIR "pci"
// attributes of PCI device nodes
// bus idx (uint8)
#define PCI_DEVICE_BUS_ITEM "pci/bus"
// device idx (uint8)
#define PCI_DEVICE_DEVICE_ITEM "pci/device"
// function idx (uint8)
#define PCI_DEVICE_FUNCTION_ITEM "pci/function"
// vendor id (uint16)
#define PCI_DEVICE_VENDOR_ID_ITEM "pci/vendor_id"
// device id (uint16)
#define PCI_DEVICE_DEVICE_ID_ITEM "pci/device_id"
// subsystem id (uint16)
#define PCI_DEVICE_SUBSYSTEM_ID_ITEM "pci/subsystem_id"
// subvendor id (uint16)
#define PCI_DEVICE_SUBVENDOR_ID_ITEM "pci/subvendor_id"
// device base class (uint16)
#define PCI_DEVICE_BASE_CLASS_ID_ITEM "pci/class/base_id"
// device subclass (uint16)
#define PCI_DEVICE_SUB_CLASS_ID_ITEM "pci/class/sub_id"
// device api (uint16)
#define PCI_DEVICE_API_ID_ITEM "pci/class/api_id"
// dynamic consumer patterns for PCI devices
#define PCI_DEVICE_DYNAMIC_CONSUMER_0 \
PCI_DRIVERS_DIR "/" \
"vendor %" PCI_DEVICE_VENDOR_ID_ITEM "%|" \
", device %" PCI_DEVICE_DEVICE_ID_ITEM "%|" \
", subsystem %" PCI_DEVICE_SUBSYSTEM_ID_ITEM "%|" \
", subvendor %" PCI_DEVICE_SUBVENDOR_ID_ITEM "%"
#define PCI_DEVICE_DYNAMIC_CONSUMER_1 \
PCI_DRIVERS_DIR "/" \
"base_class %" PCI_DEVICE_BASE_CLASS_ID_ITEM "%|" \
", sub_class %" PCI_DEVICE_SUB_CLASS_ID_ITEM "%|" \
", api %" PCI_DEVICE_API_ID_ITEM "%"
#endif

View File

@ -0,0 +1,459 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open SCSI bus manager
SCSI bus manager interface
The bus manager interface is _based_ on CAM, but I've modified it because :-
- HBA engine, target mode and queue freezing (and probably other features)
aren't supported (at least the first two aren't supported by linux too ;)
- Asynchronous events aren't supported (no OS/driver I know uses them)
- P/T/L was defined by number not by handle, requiring many redundant tests
and thus making adding/removing of devices/busses very hard, especially if
PnP is to be supported
- single entry system as proposed by CAM involves extra tests and overhead
because of generalized data structure
For peripheral driver writers:
Something about requests involving data transfer: you can either specify
the virtual address in <data> of CCB (in which case it must be continuous),
or store a pointer to a S/G list that contains physical addresses in
<sg_list>/<sg_cnt>. If <sg_list> is non-Null, <data> is ignored.
The S/G list must be in kernel space because the request can be executed
in a different thread context. This is also the reason why the S/G list has
to contain physical addresses. For obvious reason, the data buffer specified
by <sg_list> must be locked, but <data> doesn't need to be.
You can either execute the request synchronously ("sync_io") or
asynchronously ("async_io"; you have to acquire <completion_sem> to find
out when the request is finished). In the first case you can use either
<data> or <sg_list>, in the latter <sg_list> only.
The SCSI bus manager takes care that the controller can access the data
via DMA by copying it into a buffer if necessary. For the paging path,
this can lead to problems (if the system writes a page to disk and the SCSI
bus manager has to allocate a buffer during execution you are in trouble),
therefore the blk_man takes care that is not necessary for reads/writes.
To safe some microseconds, you should set the SCSI_DMA_SAFE flag for these
requests, so the SCSI bus manager ommittes the test.
Effectively, using synchronous execution and specifying the address via
<data> is a safe bet.
For SIM writers:
Requests sent by peripheral drivers are forwarded to the <scsi_io> entry
of the SIM. You should return as soon as some waiting is required.
Usually, the controller raises an IRQ when a request can be continued
or is finished. As interrupt handlers must be as fast as possible, you
can schedule a DPC in the handler (<schedule_dpc>) which executed by a
high priority service thread that is spawned by the SCSI bus manager
for each bus. This service thread also takes care to submit waiting
requests.
You can specify a maximum number of concurrent requests per bus via
path_inquiry (<hba_queue_size>) for the bus. The device limit is
determined via INQUIRY. If you need a lower/dynamic limit, you can refuse
a request by <requeue>. If <bus_overflow> is true, no further requests
to the bus will be sent, if <bus_overflow> is false, no further requests
to the device will be sent. To terminate the overflow condition, call
<cont_send_device>/<cont_send_bus>. It also terminated when a request
for the bus/device is finished via <finished> or <resubmit>.
Because of the asynchronous nature, requests may still arrive after the
overflow condition being signalled, so you should add a safety test to
<scsi_io>.
If a problem occurs during execution, you can ask for a restart via
<resubmit>. The request in question will be submitted as soon as possible.
If you want to be not disturbed, you can block further requests via
<block_bus>/<block_device>. As said above, you must have a safety test
at <scsi_io> though.
If the SIM uses a non-SCSI protocol, it can ask the SCSI bus manager
to emulate unsupported SCSI commands by translating them other (supported)
commands. The bus manager calls <get_restriction> during detection for
each device, setting <is_atapi> on return makes the bus manager translate
READ6/WRITE6 commands to READ10/WRITE10 commands, MODE REQUEST6/SENSE6
to MODE REQUEST10/SENSE10 and fix the version fields of INQUIRY results,
so ATAPI devices can be used like standard SCSI devices. Further, the
SCSI bus manager can emulate auto-sense by executing a REQUEST SENSE
if <subsys_status> is SCSI_REQ_CMP_ERR and <device_status> is
SCSI_DEVICE_CHECK_CONDITION when a request is finished. This emulation
may be enhanced/generalized in the future.
*/
// warning: Be defined a scsi.h (lower case) header file already,
// so we cannot use that for the ifdef
#ifndef __SCSI_BUSMANAGER_H__
#define __SCSI_BUSMANAGER_H__
#include <KernelExport.h>
#include <device_manager.h>
//#include "r5_wrapper.h"
#define SCSI_MAX_CDB_SIZE 16 // max size of cdb
#define SCSI_MAX_SENSE_SIZE 64 // max size of sense data
#define SCSI_SIM_PRIV 1536 // SIM private data; this may be a bit much but
// we currently need that for the compatibility layer
// bus/device handle
typedef struct scsi_bus_info *scsi_bus;
typedef struct scsi_device_info *scsi_device;
// structure of one scsi i/o CCB (command control block)
typedef struct scsi_ccb
{
struct scsi_ccb *next, *prev; // internal
uchar subsys_status; // Returned subsystem status
uchar device_status; // Returned scsi device status
uchar path_id; // Path ID for the request
uchar target_id; // Target device ID
uchar target_lun; // Target LUN number
uint32 flags; // Flags for operation of the subsystem
// released once after asynchronous execution of request;
// initialised by alloc_ccb, can be replaced for action but
// must be restored before returning via free_ccb
sem_id completion_sem;
uint8 cdb[SCSI_MAX_CDB_SIZE]; // command data block
uchar cdb_len; // length of command in bytes
int64 sort; // value of command to sort on (<0 means n/a)
bigtime_t timeout; // timeout - 0 = use default
uchar *data; // pointer to data
const physical_entry *sg_list; // SG list
uint16 sg_cnt; // number of SG entries
uint32 data_len; // length of data
int32 data_resid; // data transfer residual length: 2's comp
uchar sense[SCSI_MAX_SENSE_SIZE]; // autosense data
uchar sense_resid; // autosense resid length: 2's comp
// private
bool ordered : 1; // request cannot overtake/be overtaken by others
bool buffered : 1; // data is buffered to make it DMA safe
bool emulated : 1; // command is executed as part of emulation
scsi_bus bus; // associated bus
scsi_device device; // associated device
struct dma_buffer *dma_buffer; // used dma buffer, or NULL
uchar state; // bus manager state
// original data before command emulation was applied
uint8 orig_cdb[SCSI_MAX_CDB_SIZE];
uchar orig_cdb_len;
const physical_entry *orig_sg_list;
uint16 orig_sg_cnt;
uint32 orig_data_len;
// private SIM data
uchar sim_state; // set to zero when request is submitted first time
uchar sim_priv[SCSI_SIM_PRIV]; /* SIM private data area */
} scsi_ccb;
// Defines for the subsystem status field
#define SCSI_REQ_INPROG 0x00 /* request is in progress */
#define SCSI_REQ_CMP 0x01 /* request completed w/out error */
#define SCSI_REQ_ABORTED 0x02 /* request aborted by the host */
#define SCSI_UA_ABORT 0x03 /* Unable to Abort request */
#define SCSI_REQ_CMP_ERR 0x04 /* request completed with an err */
#define SCSI_BUSY 0x05 /* subsystem is busy */
#define SCSI_REQ_INVALID 0x06 /* request is invalid */
#define SCSI_PATH_INVALID 0x07 /* Path ID supplied is invalid */
#define SCSI_DEV_NOT_THERE 0x08 /* SCSI device not installed/there */
#define SCSI_UA_TERMIO 0x09 /* Unable to Terminate I/O req */
#define SCSI_SEL_TIMEOUT 0x0A /* Target selection timeout */
#define SCSI_CMD_TIMEOUT 0x0B /* Command timeout */
#define SCSI_MSG_REJECT_REC 0x0D /* Message reject received */
#define SCSI_SCSI_BUS_RESET 0x0E /* SCSI bus reset sent/received */
#define SCSI_UNCOR_PARITY 0x0F /* Uncorrectable parity err occurred */
#define SCSI_AUTOSENSE_FAIL 0x10 /* Autosense: Request sense cmd fail */
#define SCSI_NO_HBA 0x11 /* No HBA detected Error */
#define SCSI_DATA_RUN_ERR 0x12 /* Data overrun/underrun error */
#define SCSI_UNEXP_BUSFREE 0x13 /* Unexpected BUS free */
#define SCSI_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
#define SCSI_PROVIDE_FAIL 0x16 /* Unable to provide requ. capability */
#define SCSI_BDR_SENT 0x17 /* A SCSI BDR msg was sent to target */
#define SCSI_REQ_TERMIO 0x18 /* request terminated by the host */
#define SCSI_HBA_ERR 0x19 /* Unrecoverable host bus adaptor err*/
#define SCSI_BUS_RESET_DENIED 0x1A /* SCSI bus reset denied */
#define SCSI_IDE 0x33 /* Initiator Detected Error Received */
#define SCSI_RESRC_UNAVAIL 0x34 /* Resource unavailable */
#define SCSI_UNACKED_EVENT 0x35 /* Unacknowledged event by host */
#define SCSI_LUN_INVALID 0x38 /* LUN supplied is invalid */
#define SCSI_TID_INVALID 0x39 /* Target ID supplied is invalid */
#define SCSI_FUNC_NOTAVAIL 0x3A /* The requ. func is not available */
#define SCSI_NO_NEXUS 0x3B /* Nexus is not established */
#define SCSI_IID_INVALID 0x3C /* The initiator ID is invalid */
#define SCSI_CDB_RECVD 0x3D /* The SCSI CDB has been received */
#define SCSI_LUN_ALLREADY_ENAB 0x3E /* LUN already enabled */
#define SCSI_SCSI_BUSY 0x3F /* SCSI bus busy */
#define SCSI_AUTOSNS_VALID 0x80 /* Autosense data valid for target */
#define SCSI_SUBSYS_STATUS_MASK 0x3F /* Mask bits for just the status # */
// Defines for the flags field
#define SCSI_DIR_RESV 0x00000000 /* Data direction (00: reserved) */
#define SCSI_DIR_IN 0x00000040 /* Data direction (01: DATA IN) */
#define SCSI_DIR_OUT 0x00000080 /* Data direction (10: DATA OUT) */
#define SCSI_DIR_NONE 0x000000C0 /* Data direction (11: no data) */
#define SCSI_DIR_MASK 0x000000C0
#define SCSI_DIS_AUTOSENSE 0x00000020 /* Disable autosense feature */
#define SCSI_ORDERED_QTAG 0x00000010 // ordered queue (cannot overtake/be overtaken)
#define SCSI_DMA_SAFE 0x00000008 // set if data buffer is DMA approved
#define SCSI_DIS_DISCONNECT 0x00008000 /* Disable disconnect */
#define SCSI_INITIATE_SYNC 0x00004000 /* Attempt Sync data xfer, and SDTR */
#define SCSI_DIS_SYNC 0x00002000 /* Disable sync, go to async */
#define SCSI_ENG_SYNC 0x00000200 /* Flush resid bytes before cmplt */
// Defines for the Path Inquiry CCB fields
// flags in hba_inquiry
#define SCSI_PI_MDP_ABLE 0x80 /* Supports MDP message */
#define SCSI_PI_WIDE_32 0x40 /* Supports 32 bit wide SCSI */
#define SCSI_PI_WIDE_16 0x20 /* Supports 16 bit wide SCSI */
#define SCSI_PI_SDTR_ABLE 0x10 /* Supports SDTR message */
#define SCSI_PI_TAG_ABLE 0x02 /* Supports tag queue message */
#define SCSI_PI_SOFT_RST 0x01 /* Supports soft reset */
// flags in hba_misc
#define SCSI_PIM_SCANHILO 0x80 /* Bus scans from ID 7 to ID 0 */
#define SCSI_PIM_NOREMOVE 0x40 /* Removable dev not included in scan */
// sizes of inquiry fields
#define SCSI_VUHBA 14 /* Vendor Unique HBA length */
#define SCSI_SIM_ID 16 /* ASCII string len for SIM ID */
#define SCSI_HBA_ID 16 /* ASCII string len for HBA ID */
#define SCSI_FAM_ID 16 /* ASCII string len for FAMILY ID */
#define SCSI_TYPE_ID 16 /* ASCII string len for TYPE ID */
#define SCSI_VERS 8 /* ASCII string len for SIM & HBA vers */
// Path inquiry, extended by BeOS XPT_EXTENDED_PATH_INQ parameters
typedef struct
{
uchar version_num; /* Version number for the SIM/HBA */
uchar hba_inquiry; /* Mimic of INQ byte 7 for the HBA */
uchar hba_misc; /* Misc HBA feature flags */
uint32 sim_priv; /* Size of SIM private data area */
uchar vuhba_flags[SCSI_VUHBA];/* Vendor unique capabilities */
uchar initiator_id; /* ID of the HBA on the SCSI bus */
uint32 hba_queue_size; // size of adapaters command queue
char sim_vid[SCSI_SIM_ID]; /* Vendor ID of the SIM */
char hba_vid[SCSI_HBA_ID]; /* Vendor ID of the HBA */
char sim_version[SCSI_VERS]; /* SIM version number */
char hba_version[SCSI_VERS]; /* HBA version number */
char controller_family[SCSI_FAM_ID]; /* Controller family */
char controller_type[SCSI_TYPE_ID]; /* Controller type */
} scsi_path_inquiry;
// Device node
// target (uint8)
#define SCSI_DEVICE_TARGET_ID_ITEM "scsi/target_id"
// lun (uint8)
#define SCSI_DEVICE_TARGET_LUN_ITEM "scsi/target_lun"
// node type
#define SCSI_DEVICE_TYPE_NAME "scsi/device/v1"
// device inquiry data (raw scsi_res_inquiry)
#define SCSI_DEVICE_INQUIRY_ITEM "scsi/device_inquiry"
// device type (uint8)
#define SCSI_DEVICE_TYPE_ITEM "scsi/type"
// vendor name (string)
#define SCSI_DEVICE_VENDOR_ITEM "scsi/vendor"
// product name (string)
#define SCSI_DEVICE_PRODUCT_ITEM "scsi/product"
// revision (string)
#define SCSI_DEVICE_REVISION_ITEM "scsi/revision"
// directory containing links to peripheral drivers
#define SCSI_PERIPHERAL_DRIVERS_DIR "scsi"
// bus manager device interface for peripheral driver
typedef struct scsi_device_interface {
pnp_driver_info dinfo;
// get CCB
// warning: if pool of CCBs is exhausted, this call is delayed until a
// CCB is freed, so don't try to allocate more then one CCB at once!
scsi_ccb *(*alloc_ccb)( scsi_device device );
// free CCB
void (*free_ccb)( scsi_ccb *ccb );
// execute command asynchronously
// when it's finished, the semaphore of the ccb is released
// you must provide a S/G list if data_len != 0
void (*async_io)( scsi_ccb *ccb );
// execute command synchronously
// you don't need to provide a S/G list nor have to lock data
void (*sync_io)( scsi_ccb *ccb );
// abort request
uchar (*abort)( scsi_ccb *ccb_to_abort );
// reset device
uchar (*reset_device)( scsi_device device );
// terminate request
uchar (*term_io)( scsi_ccb *ccb_to_terminate );
} scsi_device_interface;
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
// Bus node
// attributes:
// path (uint8)
#define SCSI_BUS_PATH_ID_ITEM "scsi/path_id"
// node type
#define SCSI_BUS_TYPE_NAME "scsi/bus"
// SCSI bus node driver.
// This interface can be used by peripheral drivers to access the
// bus directly.
typedef struct scsi_bus_interface {
pnp_bus_info binfo;
// get information about host controller
uchar (*path_inquiry)( scsi_bus bus, scsi_path_inquiry *inquiry_data );
// reset SCSI bus
uchar (*reset_bus)( scsi_bus bus );
} scsi_bus_interface;
// name of SCSI bus node driver
#define SCSI_BUS_MODULE_NAME "bus_managers/scsi/bus/v1"
// Interface for SIM
// cookie for dpc
typedef struct scsi_dpc_info *scsi_dpc_cookie;
// Bus manager interface used by SCSI controller drivers.
// SCSI controller drivers get this interface passed via their init_device
// method. Further, they must specify this driver as their fixed consumer.
typedef struct scsi_for_sim_interface {
pnp_driver_info dinfo;
// put request into wait queue because of overflow
// bus_overflow: true - too many bus requests
// false - too many device requests
// bus/device won't receive requests until cont_sent_bus/cont_send_device
// is called or a request is finished via finished();
// to avoid race conditions (reporting a full and a available bus at once)
// the SIM should synchronize calls to requeue, resubmit and finished
void (*requeue)( scsi_ccb *ccb, bool bus_overflow );
// resubmit request ASAP
// to be used if execution of request went wrong and must be retried
void (*resubmit)( scsi_ccb *ccb );
// mark request as being finished
// num_requests: number of requests that were handled by device
// when the request was sent (read: how full was the device
// queue); needed to find out how large the device queue is;
// e.g. if three were already running plus this request makes
// num_requests=4
void (*finished)( scsi_ccb *ccb, uint num_requests );
// following functions return error on invalid arguments only
status_t (*alloc_dpc)( scsi_dpc_cookie *dpc );
status_t (*free_dpc)( scsi_dpc_cookie dpc );
status_t (*schedule_dpc)( scsi_bus cookie, scsi_dpc_cookie dpc, /*int flags,*/
void (*func)( void * ), void *arg );
// block entire bus (can be nested)
// no more request will be submitted to this bus
void (*block_bus)( scsi_bus bus );
// unblock entire bus
// requests will be submitted to bus ASAP
void (*unblock_bus)( scsi_bus bus );
// block one device
// no more requests will be submitted to this device
void (*block_device)( scsi_device device );
// unblock device
// requests for this device will be submitted ASAP
void (*unblock_device)( scsi_device device );
// terminate bus overflow condition (see "requeue")
void (*cont_send_bus)( scsi_bus bus );
// terminate device overflow condition (see "requeue")
void (*cont_send_device)( scsi_device device );
} scsi_for_sim_interface;
#define SCSI_FOR_SIM_MODULE_NAME "bus_managers/scsi/sim/v1"
// SIM Node
// attributes:
// node type
#define SCSI_SIM_TYPE_NAME "bus/scsi/v1"
// controller name (required, string)
#define SCSI_DESCRIPTION_CONTROLLER_NAME "controller_name"
typedef struct scsi_sim_cookie *scsi_sim_cookie;
// SIM interface
// SCSI controller drivers must provide this interface
typedef struct scsi_sim_interface {
pnp_driver_info dinfo;
// execute request
void (*scsi_io)( scsi_sim_cookie cookie, scsi_ccb *ccb );
// abort request
uchar (*abort)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort );
// reset device
uchar (*reset_device)( scsi_sim_cookie cookie, uchar target_id, uchar target_lun );
// terminate request
uchar (*term_io)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate );
// get information about bus
uchar (*path_inquiry)( scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data );
// scan bus
// this is called immediately before the SCSI bus manager scans the bus
uchar (*scan_bus)( scsi_sim_cookie cookie );
// reset bus
uchar (*reset_bus)( scsi_sim_cookie cookie );
// get restrictions of one device
// (used for non-SCSI transport protocols and bug fixes)
void (*get_restrictions)(
scsi_sim_cookie cookie,
uchar target_id, // target id
bool *is_atapi, // set to true if this is an ATAPI device that
// needs some commands emulated
bool *no_autosense, // set to true if there is no autosense;
// the SCSI bus manager will request sense on
// SCSI_REQ_CMP_ERR/SCSI_DEVICE_CHECK_CONDITION
uint32 *max_blocks ); // maximum number of blocks per transfer if > 0;
// used for buggy devices that cannot handle
// large transfers (read: ATAPI ZIP drives)
} scsi_sim_interface;
#endif

View File

@ -0,0 +1,224 @@
/*
** Copyright 2002-04, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
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.
*/
#ifndef _IDE_PCI_H
#define _IDE_PCI_H
#include <bus/PCI.h>
#include <bus/IDE.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;
// command register
typedef struct ide_bm_command {
LBITFIELD8_4(
start_stop : 1, // start BM by changing from 0 to 1;
// stop BM by changing from 1 to 0
res0_1 : 2,
from_device : 1, // true - read from device, false - write to device
res0_4 : 4
);
} ide_bm_command;
// status register
typedef struct ide_bm_status {
LBITFIELD8_7(
active : 1, // 1, if BM is active
error : 1, // 1, if error occured; write 1 to reset
interrupt : 1, // 1, if INTRQ was raised, write 1 to reset
res0_3 : 2,
device0_dma : 1, // 1, if BIOS/driver has setup DMA for device 0
device1_dma : 1, // 1, if BIOS/driver has setup DMA for device 1
simplex : 1 // 1, if only one channel can use DMA at a time
);
} ide_bm_status;
// offset of bus master registers
enum {
ide_bm_command_reg = 0, // see ide_bm_command
ide_bm_status_reg = 2, // see ide_bm_status
ide_bm_prdt_address = 4 // offset of PRDT register; content must be dword-aligned
};
// bit mask in class_api of PCI configuration
// (for adapters that can run in compatability mode)
enum {
ide_api_primary_native = 1, // primary channel is in native mode
ide_api_primary_fixed = 2, // primary channel can be switched to native mode
ide_api_secondary_native = 4, // secondary channel is in native mode
ide_api_secondary_fixed = 8 // secondary channel can be switched to native mode
};
// (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"
// non-zero if primary channel, else secondary channel (uint8)
#define IDE_ADAPTER_IS_PRIMARY "ide_adapter/is_primary"
// 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 ide_channel;
pnp_node_handle 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
pnp_node_handle node;
} ide_adapter_controller_info;
// interface of IDE adapter library
typedef struct {
module_info minfo;
// 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)( pnp_node_handle node, ide_channel ide_channel,
ide_adapter_channel_info **cookie, size_t total_data_size,
int32 (*inthand)( void *arg ) );
status_t (*uninit_channel)( ide_adapter_channel_info *channel );
void (*channel_removed)( pnp_node_handle node, ide_adapter_channel_info *channel );
// publish channel node
status_t (*publish_channel)( pnp_node_handle controller_node,
const char *channel_module_name,
uint16 command_block_base, uint16 control_block_base,
uint8 intnum, bool can_dma, bool is_primary, const char *name,
io_resource_handle *resources, pnp_node_handle *node );
// verify channel configuration and publish node on success
status_t (*detect_channel)(
pci_device_module_info *pci, pci_device pci_device,
pnp_node_handle 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, bool is_primary, const char *name, pnp_node_handle *node,
bool supports_compatibility_mode );
// functions that must be called by init/uninit etc. of controller driver
status_t (*init_controller)( pnp_node_handle node, void *user_cookie,
ide_adapter_controller_info **cookie, size_t total_data_size );
status_t (*uninit_controller)( ide_adapter_controller_info *controller );
void (*controller_removed)( pnp_node_handle node, ide_adapter_controller_info *controller );
// publish controller node
status_t (*publish_controller)(
pnp_node_handle parent,
uint16 bus_master_base, io_resource_handle *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, pnp_node_handle *node );
// verify controller configuration and publish node on success
status_t (*detect_controller)(
pci_device_module_info *pci, pci_device pci_device,
pnp_node_handle 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, pnp_node_handle *node );
// standard master probe for controller that registers controller and channel nodes
status_t (*probe_controller)( pnp_node_handle 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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,163 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Part of Open SCSI Peripheral Driver
Use this module to minimize work required to write a SCSI
peripheral driver.
It takes care of:
- error handling
- medium changes (including restarting the medium)
- detection of medium capacity
*/
#ifndef __SCSI_PERIPH_H__
#define __SCSI_PERIPH_H__
#include <bus/SCSI.h>
#include <blkman.h>
#include <bus/scsi/scsi_cmds.h>
#include <Drivers.h>
// cookie issued by module per device
typedef struct scsi_periph_device_info *scsi_periph_device;
// cookie issued by module per file handle
typedef struct scsi_periph_handle_info *scsi_periph_handle;
// "standardized" error code to simplify handling of scsi errors
typedef enum {
err_act_ok, // executed successfully
err_act_retry, // failed, retry 3 times
err_act_fail, // failed, don't retry
err_act_many_retries, // failed, retry multiple times (currently 10 times)
err_act_start, // devices requires a "start" command
err_act_invalid_req // request is invalid
} err_act;
// packed scsi command result
typedef struct err_res {
status_t error_code : 32; // Be error code
uint32 action : 8; // err_act code
} err_res;
#define MK_ERROR( aaction, code ) ({ \
err_res res = {error_code: (code), action: (aaction) }; \
res; \
})
// device icon type
typedef enum {
icon_type_disk,
icon_type_removal,
icon_type_floppy,
icon_type_cd
} icon_type;
// cookie issued by driver to identify itself
//typedef struct periph_info *periph_cookie;
// cookie issued by driver per device
typedef struct periph_device_info *periph_device_cookie;
// cookie issued by driver per file handle
typedef struct periph_handle_info *periph_handle_cookie;
// callbacks to be provided by peripheral driver
typedef struct scsi_periph_callbacks {
// *** block devices ***
// informs of new size of medium
// (set to NULL if not a block device)
void (*set_capacity)( periph_device_cookie periph_device, uint64 capacity,
uint32 block_size );
// *** removable devices
// called when media got changed (can be NULL if medium is not changable)
// (you don't need to call periph->media_changed, but it's doesn't if you do)
// ccb - request at your disposal
void (*media_changed)( periph_device_cookie periph_device,
scsi_ccb *request );
} scsi_periph_callbacks;
// functions provided by this module
typedef struct scsi_periph_interface {
module_info module;
// *** init/cleanup ***
status_t (*register_device)(
periph_device_cookie periph_device,
scsi_periph_callbacks *callbacks,
scsi_device scsi_device,
scsi_device_interface *scsi,
pnp_node_handle node,
bool removable,
scsi_periph_device *driver );
status_t (*unregister_device)( scsi_periph_device driver );
// *** basic command execution ***
// exec command, retrying on problems
status_t (*safe_exec)(
scsi_periph_device periph_device,
scsi_ccb *request );
// exec simple command
status_t (*simple_exec)( scsi_periph_device device,
void *cdb, uchar cdb_len, void *data, size_t data_len,
int ccb_flags );
// *** file handling ***
// to be called when a new file is opened
status_t (*handle_open)( scsi_periph_device device,
periph_handle_cookie periph_handle, scsi_periph_handle *res_handle );
// to be called when a file is closed
status_t (*handle_close)( scsi_periph_handle handle );
// to be called when a file is freed
status_t (*handle_free)( scsi_periph_handle handle );
// *** default implementation for block devices ***
// block read
// preferred_ccb_size - preferred command size; if zero, the shortest is used
status_t (*read)( scsi_periph_handle handle, const phys_vecs *vecs,
off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred,
int preferred_ccb_size );
// block write
// (see block_read)
status_t (*write)( scsi_periph_handle handle, const phys_vecs *vecs,
off_t pos, size_t num_blocks, uint32 block_size, size_t *bytes_transferred,
int preferred_ccb_size );
// block ioctls
status_t (*ioctl)( scsi_periph_handle handle, int op, void *buf, size_t len );
// check medium capacity (calls set_capacity callback on success)
// request - ccb for this device; is used to talk to device
status_t (*check_capacity)( scsi_periph_device device, scsi_ccb *request );
// *** removable media ***
// to be called when a medium change is detected to block subsequent commands
void (*media_changed)( scsi_periph_device device );
// convert result of *request to err_res
err_res (*check_error)( scsi_periph_device device, scsi_ccb *request );
// send start or stop command to device
// with_LoEj = true - include loading/ejecting,
// false - only do allow/deny
err_res (*send_start_stop)( scsi_periph_device device, scsi_ccb *request,
bool start, bool with_LoEj );
// checks media status and waits for device to become ready
// returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or
// pending error reported by handle_get_error
status_t (*get_media_status)( scsi_periph_handle handle );
// compose device name consisting of prefix and path/target/LUN
// (result must be freed by caller)
char *(*compose_device_name)( pnp_node_handle device_node,
const char *prefix );
// fill data with icon (for B_GET_ICON ioctl)
status_t (*get_icon)( icon_type type, device_icon *data );
} scsi_periph_interface;
#define SCSI_PERIPH_MODULE_NAME "generic/scsi_periph/v1"
#endif

View File

@ -0,0 +1,80 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Fast logging facilities.
This logging is much faster then dprintf and is saver
against buffer overflow conditions.
Clients have to define events by creating an array of
fast_log_type entries, each consisting of a code and the
associated human-readable description. During logging,
only the code is stored to save space and time. Also,
all arguments are stored binary (currently, they must
be of type uint32). Conversion to human-readable text is
post-poned until the logging data is read or a client
connection is closed (as this invalidates the event-
description binding).
The reader interface is /dev/FAST_LOG_DEVFS_NAME. This
device can only be read from (no seeking or further
functionality) and does not block if there is no data.
This is because if you want to store the log into a
file, the file access may lead to further logging data,
so doing a sleep between reads saves logging entries.
*/
#ifndef FAST_LOG_H
#define FAST_LOG_H
#include <module.h>
// one event type as defined by client
typedef struct fast_log_event_type {
// code of event (zero means end-of-list)
int16 event;
// human-readable description
const char *description;
} fast_log_event_type;
// handle of client connection
typedef struct fast_log_connection *fast_log_handle;
// client interface
typedef struct fast_log_info {
module_info minfo;
// open client connection
// prefix - prefix to print in log before each event
// types - array of event types; last entry must have event=0
fast_log_handle (*start_log)(const char *prefix, fast_log_event_type types[]);
// close client connection
void (*stop_log)(fast_log_handle handle);
// log an entry without arguments
void (*log_0)(fast_log_handle handle, int event);
// log an entry with one argument
void (*log_1)(fast_log_handle handle, int event, uint32 param1);
// log an entry with two arguments
void (*log_2)(fast_log_handle handle, int event, uint32 param1, uint32 param2);
// log an entry with three arguments
void (*log_3)(fast_log_handle handle, int event, uint32 param1, uint32 param2, uint32 param3);
// log an entry with four arguments
void (*log_4)(fast_log_handle handle, int event, uint32 param1, uint32 param2, uint32 param3, uint32 param4);
// log an entry with n arguments
// don't cheat on num_params!
void (*log_n)(fast_log_handle handle, int event, int num_params, ...);
} fast_log_info;
// name of client interface module
#define FAST_LOG_MODULE_NAME "generic/fast_log/v1"
// name of device to read logging data from
#define FAST_LOG_DEVFS_NAME "fast_log"
#endif

View File

@ -0,0 +1,68 @@
/*
** Copyright 2002, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#ifndef LENDIAN_BITFIELD_H
#define LENDIAN_BITFIELD_H
#include <ByteOrder.h>
#define B_HOST_IS_LENDIAN 1
#if B_HOST_IS_BENDIAN
#define LBITFIELD8_2(b1,b2) uint8 b2,b1
#define LBITFIELD8_3(b1,b2,b3) uint8 b3,b2,b1
#define LBITFIELD8_4(b1,b2,b3,b4) uint8 b4,b3,b2,b1
#define LBITFIELD8_5(b1,b2,b3,b4,b5) uint8 b5,b4,b3,b2,b1
#define LBITFIELD8_6(b1,b2,b3,b4,b5,b6) uint8 b6,b5,b4,b3,b2,b1
#define LBITFIELD8_7(b1,b2,b3,b4,b5,b6,b7) uint8 b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD8_8(b1,b2,b3,b4,b5,b6,b7,b8) uint8 b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD2(b1,b2) uint16 b2,b1
#define LBITFIELD3(b1,b2,b3) uint16 b3,b2,b1
#define LBITFIELD4(b1,b2,b3,b4) uint16 b4,b3,b2,b1
#define LBITFIELD5(b1,b2,b3,b4,b5) uint16 b5,b4,b3,b2,b1
#define LBITFIELD6(b1,b2,b3,b4,b5,b6) uint16 b6,b5,b4,b3,b2,b1
#define LBITFIELD7(b1,b2,b3,b4,b5,b6,b7) uint16 b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD8(b1,b2,b3,b4,b5,b6,b7,b8) uint16 b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD9(b1,b2,b3,b4,b5,b6,b7,b8,b9) uint16 b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD10(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10) uint16 b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD11(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11) uint16 b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD12(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12) uint16 b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD13(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13) uint16 b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD14(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14) uint16 b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD15(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15) uint16 b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#define LBITFIELD16(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16) uint16 b16,b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1
#elif B_HOST_IS_LENDIAN
#define LBITFIELD8_2(b1,b2) uint8 b1,b2
#define LBITFIELD8_3(b1,b2,b3) uint8 b1,b2,b3
#define LBITFIELD8_4(b1,b2,b3,b4) uint8 b1,b2,b3,b4
#define LBITFIELD8_5(b1,b2,b3,b4,b5) uint8 b1,b2,b3,b4,b5
#define LBITFIELD8_6(b1,b2,b3,b4,b5,b6) uint8 b1,b2,b3,b4,b5,b6
#define LBITFIELD8_7(b1,b2,b3,b4,b5,b6,b7) uint8 b1,b2,b3,b4,b5,b6,b7
#define LBITFIELD8_8(b1,b2,b3,b4,b5,b6,b7,b8) uint8 b1,b2,b3,b4,b5,b6,b7,b8
#define LBITFIELD2(b1,b2) uint16 b1,b2
#define LBITFIELD3(b1,b2,b3) uint16 b1,b2,b3
#define LBITFIELD4(b1,b2,b3,b4) uint16 b1,b2,b3,b4
#define LBITFIELD5(b1,b2,b3,b4,b5) uint16 b1,b2,b3,b4,b5
#define LBITFIELD6(b1,b2,b3,b4,b5,b6) uint16 b1,b2,b3,b4,b5,b6
#define LBITFIELD7(b1,b2,b3,b4,b5,b6,b7) uint16 b1,b2,b3,b4,b5,b6,b7
#define LBITFIELD8(b1,b2,b3,b4,b5,b6,b7,b8) uint16 b1,b2,b3,b4,b5,b6,b7,b8
#define LBITFIELD9(b1,b2,b3,b4,b5,b6,b7,b8,b9) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9
#define LBITFIELD10(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10
#define LBITFIELD11(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11
#define LBITFIELD12(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12
#define LBITFIELD13(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13
#define LBITFIELD14(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14
#define LBITFIELD15(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15
#define LBITFIELD16(b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16) uint16 b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15,b16
#else
#error "Unknown host endianness"
#endif
#endif /* LENDIAN_BITFIELD_H */

View File

@ -0,0 +1,70 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
Paging-safe allocation of locked memory.
Library for managing temporary, locked memory with the condition of
not calling any function during allocation that can lead to paging.
Such memory is needed by drivers that are used to access the page file
but still need locked memory to execute requests.
Basically, a background thread manages a memory pool where blocks
are allocated from. If the pool is empty, allocation is delayed until
either a blocks is freed or the pool is enlarged by the background
thread.
All memory blocks must have same size and can be pre-initialized when
added to memory pool (and cleaned-up when removed from pool). The
free list is stored within free memory blocks, so you have to specify
a block offset where the manager can store the list pointers without
interfering with pre-initialization.
You can also specify an alignment, e.g. if the blocks are used for
DMA access, a minimum pool size (in blocks), a maximum pool size
(in blocks) and the size of memory chunks to be added if the entire
pool is allocated.
*/
#ifndef __LOCKED_POOL_H__
#define __LOCKED_POOL_H__
#include <device_manager.h>
typedef struct locked_pool *locked_pool_cookie;
typedef status_t (*locked_pool_add_hook)(void *block, void *arg);
typedef void (*locked_pool_remove_hook)(void *block, void *arg);
typedef struct {
module_info minfo;
// allocate block
void *(*alloc)(locked_pool_cookie pool);
// free block
void (*free)(locked_pool_cookie pool, void *block);
// create new pool
// block_size - size of one memory block
// alignment - set address bits here that must be zero for block addresses
// next_ofs - offset in block where internal next-pointer can be stored
// chunk_size - how much system memory is to be allocated at once
// max_blocks - maximum number of blocks
// min_free_block - minimum number of free blocks
// name - name of pool
// lock_flags - flags to be passed to lock_memory()
// alloc_hook - hook to be called when new block is added to pool (can be NULL )
// free_hook - hook to be called when block is removed from pool (can be NULL )
// hook_arg - value to be passed to hooks as arg
locked_pool_cookie (*create)(int block_size, int alignment, int next_ofs,
int chunk_size, int max_blocks, int min_free_blocks, const char *name,
uint32 lock_flags, locked_pool_add_hook add_hook,
locked_pool_remove_hook remove_hook, void *hook_arg);
void (*destroy)(locked_pool_cookie pool);
} locked_pool_interface;
#define LOCKED_POOL_MODULE_NAME "generic/locked_pool/v1"
#endif

View File

@ -0,0 +1,57 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
/*
PnP devfs driver interface.
The interface follows the normal pnp driver rules, i.e.
your driver creates a node for it and chooses PNP_DEVFS_MODULE_NAME
as the consumer, the type must be PNP_DEVFS_TYPE_NAME. The file
name is set via a PNP_DEVFS_FILENAME item.
Loading and unloading of your driver is done via the pnp manager.
Hooks are similar to the original devfs interface, but the open
hook gets the driver cookie (as returned by init_device of the
driver) instead of a filename.
*/
#ifndef _PNP_DEVFS_H
#define _PNP_DEVFS_H
#include <Drivers.h>
#include <device_manager.h>
//#include "r5_wrapper.h"
// changed open hook - gets cookie returned by init_device instead of name
typedef status_t (*pnp_device_open_hook)(void *device_cookie, uint32 flags,
void **handle_cookie);
// new interface to devfs
typedef struct pnp_devfs_driver_info {
pnp_driver_info dinfo;
pnp_device_open_hook open; // called to open the device
device_close_hook close; // called to close the device
device_free_hook free; // called to free the cookie
device_control_hook control; // called to control the device
device_read_hook read; // reads from the device
device_write_hook write; // writes to the device
device_select_hook select; // start select (can be NULL)
device_deselect_hook deselect; // stop select (can be NULL)
device_readv_hook readv; // scatter-gather read from the device (can be NULL)
device_writev_hook writev; // scatter-gather write to the device (can be NULL)
} pnp_devfs_driver_info;
// items:
// name under which the device should be published under /dev (required, string)
#define PNP_DEVFS_FILENAME "devfs/filename"
// type of devfs device drivers
#define PNP_DEVFS_TYPE_NAME "devfs_device"
#define PNP_DEVFS_MODULE_NAME "sys/pnp_devfs/v1"
#endif