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:
parent
cc5bfcb2e9
commit
0d59a3d2a9
29
headers/os/device/scsi_bus_raw_driver.h
Normal file
29
headers/os/device/scsi_bus_raw_driver.h
Normal 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
102
headers/os/drivers/blkman.h
Normal 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
|
363
headers/os/drivers/bus/IDE.h
Normal file
363
headers/os/drivers/bus/IDE.h
Normal 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
|
72
headers/os/drivers/bus/ISA.h
Normal file
72
headers/os/drivers/bus/ISA.h
Normal 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
|
165
headers/os/drivers/bus/PCI.h
Normal file
165
headers/os/drivers/bus/PCI.h
Normal 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
|
459
headers/os/drivers/bus/SCSI.h
Normal file
459
headers/os/drivers/bus/SCSI.h
Normal 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
|
224
headers/os/drivers/bus/ide/ide_adapter.h
Normal file
224
headers/os/drivers/bus/ide/ide_adapter.h
Normal 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
|
1026
headers/os/drivers/bus/scsi/scsi_cmds.h
Normal file
1026
headers/os/drivers/bus/scsi/scsi_cmds.h
Normal file
File diff suppressed because it is too large
Load Diff
163
headers/os/drivers/bus/scsi/scsi_periph.h
Normal file
163
headers/os/drivers/bus/scsi/scsi_periph.h
Normal 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
|
80
headers/os/drivers/fast_log.h
Normal file
80
headers/os/drivers/fast_log.h
Normal 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
|
68
headers/os/drivers/lendian_bitfield.h
Normal file
68
headers/os/drivers/lendian_bitfield.h
Normal 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 */
|
70
headers/os/drivers/locked_pool.h
Normal file
70
headers/os/drivers/locked_pool.h
Normal 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
|
57
headers/os/drivers/pnp_devfs.h
Normal file
57
headers/os/drivers/pnp_devfs.h
Normal 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
|
Loading…
Reference in New Issue
Block a user