diff --git a/headers/os/device/scsi_bus_raw_driver.h b/headers/os/device/scsi_bus_raw_driver.h new file mode 100644 index 0000000000..b6000e01a3 --- /dev/null +++ b/headers/os/device/scsi_bus_raw_driver.h @@ -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 + +// 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 diff --git a/headers/os/drivers/blkman.h b/headers/os/drivers/blkman.h new file mode 100644 index 0000000000..174cb1549d --- /dev/null +++ b/headers/os/drivers/blkman.h @@ -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 +#include + +// 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 diff --git a/headers/os/drivers/bus/IDE.h b/headers/os/drivers/bus/IDE.h new file mode 100644 index 0000000000..7c57a7de15 --- /dev/null +++ b/headers/os/drivers/bus/IDE.h @@ -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 +#include +#include +#include +#include + +// 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 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 diff --git a/headers/os/drivers/bus/ISA.h b/headers/os/drivers/bus/ISA.h new file mode 100644 index 0000000000..7e5f817732 --- /dev/null +++ b/headers/os/drivers/bus/ISA.h @@ -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 + + +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 diff --git a/headers/os/drivers/bus/PCI.h b/headers/os/drivers/bus/PCI.h new file mode 100644 index 0000000000..1746d28fe9 --- /dev/null +++ b/headers/os/drivers/bus/PCI.h @@ -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 +//#include "r5_wrapper.h" +#include + +// 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 diff --git a/headers/os/drivers/bus/SCSI.h b/headers/os/drivers/bus/SCSI.h new file mode 100644 index 0000000000..a8c8f2f41b --- /dev/null +++ b/headers/os/drivers/bus/SCSI.h @@ -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 of CCB (in which case it must be continuous), + or store a pointer to a S/G list that contains physical addresses in + /. If is non-Null, 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 must be locked, but doesn't need to be. + + You can either execute the request synchronously ("sync_io") or + asynchronously ("async_io"; you have to acquire to find + out when the request is finished). In the first case you can use either + or , in the latter 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 + is a safe bet. + + + For SIM writers: + + Requests sent by peripheral drivers are forwarded to the 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 () 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 () for the bus. The device limit is + determined via INQUIRY. If you need a lower/dynamic limit, you can refuse + a request by . If is true, no further requests + to the bus will be sent, if is false, no further requests + to the device will be sent. To terminate the overflow condition, call + /. It also terminated when a request + for the bus/device is finished via or . + Because of the asynchronous nature, requests may still arrive after the + overflow condition being signalled, so you should add a safety test to + . + + If a problem occurs during execution, you can ask for a restart via + . The request in question will be submitted as soon as possible. + + If you want to be not disturbed, you can block further requests via + /. As said above, you must have a safety test + at 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 during detection for + each device, setting 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 is SCSI_REQ_CMP_ERR and 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 +#include +//#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 diff --git a/headers/os/drivers/bus/ide/ide_adapter.h b/headers/os/drivers/bus/ide/ide_adapter.h new file mode 100644 index 0000000000..703d51bcd0 --- /dev/null +++ b/headers/os/drivers/bus/ide/ide_adapter.h @@ -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 +#include +#include + + +// 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 diff --git a/headers/os/drivers/bus/scsi/scsi_cmds.h b/headers/os/drivers/bus/scsi/scsi_cmds.h new file mode 100644 index 0000000000..7b8ebf2a54 --- /dev/null +++ b/headers/os/drivers/bus/scsi/scsi_cmds.h @@ -0,0 +1,1026 @@ +/* +** Copyright 2002/03, Thomas Kurschel. All rights reserved. +** Distributed under the terms of the OpenBeOS License. +*/ + +/* + Part of Open SCSI bus manager + + SCSI commands and their data structures and constants +*/ + +#ifndef __SCSI_CMDS_H__ +#define __SCSI_CMDS_H__ + +#include + +// always keep in mind that SCSI is big-endian !!! + +#define SCSI_STD_TIMEOUT 10 + +// SCSI device status (as the result of a command) +#define SCSI_STATUS_GOOD (0 << 1) +#define SCSI_STATUS_CHECK_CONDITION (1 << 1) // error occured +#define SCSI_STATUS_CONDITION_MET (2 << 1) // "found" for SEARCH DATA and PREFETCH +#define SCSI_STATUS_BUSY (4 << 1) // try again later (??? == QUEUE_FULL ???) +#define SCSI_STATUS_INTERMEDIATE (8 << 1) // used by linked command only +#define SCSI_STATUS_INTERMEDIATE_COND_MET (10 << 1) // ditto +#define SCSI_STATUS_RESERVATION_CONFLICT (12 << 1) // only if RESERVE/RELEASE is used +#define SCSI_STATUS_COMMAND_TERMINATED (17 << 1) // aborted by TERMINATE I/O PROCESS +#define SCSI_STATUS_QUEUE_FULL (20 << 1) // queue full + +#define SCSI_STATUS_MASK 0xfe + +// SCSI sense key +#define SCSIS_KEY_NO_SENSE 0 +#define SCSIS_KEY_RECOVERED_ERROR 1 +#define SCSIS_KEY_NOT_READY 2 // operator intervention may be required +#define SCSIS_KEY_MEDIUM_ERROR 3 // can be set if source could be hardware error +#define SCSIS_KEY_HARDWARE_ERROR 4 +#define SCSIS_KEY_ILLEGAL_REQUEST 5 // invalid command +#define SCSIS_KEY_UNIT_ATTENTION 6 // medium changed or target reset +#define SCSIS_KEY_DATA_PROTECT 7 // data access forbidden +#define SCSIS_KEY_BLANK_CHECK 8 // tried to read blank or to write non-blank medium +#define SCSIS_KEY_VENDOR_SPECIFIC 9 +#define SCSIS_KEY_COPY_ABORTED 10 // error in COPY or COMPARE command +#define SCSIS_KEY_ABORTED_COMMAND 11 // aborted by target, retry *may* help +#define SCSIS_KEY_EQUAL 12 // during SEARCH: data found +#define SCSIS_KEY_VOLUME_OVERFLOW 13 // tried to write buffered data beyond end of medium +#define SCSIS_KEY_MISCOMPARE 14 +#define SCSIS_KEY_RESERVED 15 + +// SCSI ASC and ASCQ data - (ASC << 8) | ASCQ +// all codes with bit 7 of ASC or ASCQ set are vendor-specific +#define SCSIS_ASC_NO_SENSE 0x0000 +#define SCSIS_ASC_IO_PROC_TERMINATED 0x0006 +#define SCSIS_ASC_AUDIO_PLAYING 0x0011 +#define SCSIS_ASC_AUDIO_PAUSED 0x0012 +#define SCSIS_ASC_AUDIO_COMPLETED 0x0013 +#define SCSIS_ASC_AUDIO_ERROR 0x0014 // playing has stopped due to error +#define SCSIS_ASC_AUDIO_NO_STATUS 0x0015 +#define SCSIS_ASC_NO_INDEX 0x0100 // no index/sector signal +#define SCSIS_ASC_NO_SEEK_CMP 0x0200 // ??? +#define SCSIS_ASC_WRITE_FAULT 0x0300 +#define SCSIS_ASC_LUN_NOT_READY 0x0400 // LUN not ready, cause not reportable +#define SCSIS_ASC_LUN_BECOMING_READY 0x0401 // LUN in progress of becoming ready +#define SCSIS_ASC_LUN_NEED_INIT 0x0402 // LUN need initializing command +#define SCSIS_ASC_LUN_NEED_MANUAL_HELP 0x0403 // LUN needs manual intervention +#define SCSIS_ASC_LUN_FORMATTING 0x0404 // LUN format in progress +#define SCSIS_ASC_LUN_SEL_FAILED 0x0500 // LUN doesn't respond to selection +#define SCSIS_ASC_LUN_COM_FAILURE 0x0800 // LUN communication failure +#define SCSIS_ASC_LUN_TIMEOUT 0x0801 // LUN communication time-out +#define SCSIS_ASC_LUN_COM_PARITY 0x0802 // LUN communication parity failure +#define SCSIS_ASC_LUN_COM_CRC 0x0803 // LUN communication CRC failure (SCSI-3) +#define SCSIS_ASC_WRITE_ERR_AUTOREALLOC 0x0c01 // recovered by auto-reallocation +#define SCSIS_ASC_WRITE_ERR_AUTOREALLOC_FAILED 0x0c02 +#define SCSIS_ASC_ECC_ERROR 0x1000 +#define SCSIS_ASC_UNREC_READ_ERR 0x1100 // unrecovered read error +#define SCSIS_ASC_READ_RETRIES_EXH 0x1101 // read retries exhausted +#define SCSIS_ASC_UNREC_READ_ERR_AUTOREALLOC_FAILED 0x1104 // above + auto-reallocate failed +#define SCSIS_ASC_RECORD_NOT_FOUND 0x1401 +#define SCSIS_ASC_RANDOM_POS_ERROR 0x1500 // random positioning error +#define SCSIS_ASC_POSITIONING_ERR 0x1501 // mechanical positioning error +#define SCSIS_ASC_POS_ERR_ON_READ 0x1502 // positioning error detected by reading +#define SCSIS_ASC_DATA_RECOV_NO_ERR_CORR 0x1700 // recovered with no error correction applied +#define SCSIS_ASC_DATA_RECOV_WITH_RETRIES 0x1701 +#define SCSIS_ASC_DATA_RECOV_POS_HEAD_OFS 0x1702 // ?recovered with positive head offset +#define SCSIS_ASC_DATA_RECOV_NEG_HEAD_OFS 0x1703 // ?recovered with negative head offset +#define SCSIS_ASC_DATA_RECOV_WITH_RETRIES_CIRC 0x1704 // recovered with retries/CIRC +#define SCSIS_ASC_DATA_RECOV_PREV_SECT_ID 0x1705 // recovered using previous sector ID +#define SCSIS_ASC_DATA_RECOV_NO_ECC_AUTOREALLOC 0x1706 +#define SCSIS_ASC_DATA_RECOV_NO_ECC_REASSIGN 0x1707 // reassign recommended +#define SCSIS_ASC_DATA_RECOV_NO_ECC_REWRITE 0x1708 // rewrite recommended +#define SCSIS_ASC_DATA_RECOV_WITH_CORR 0x1800 // recovered using error correction +#define SCSIS_ASC_DATA_RECOV_WITH_CORR_RETRIES 0x1801 // used error correction and retries +#define SCSIS_ASC_DATA_RECOV_AUTOREALLOC 0x1802 +#define SCSIS_ASC_DATA_RECOV_CIRC 0x1803 // recovered using CIRC +#define SCSIS_ASC_DATA_RECOV_LEC 0x1804 // recovered using LEC +#define SCSIS_ASC_DATA_RECOV_REASSIGN 0x1805 // reassign recommended +#define SCSIS_ASC_DATA_RECOV_REWRITE 0x1806 // rewrite recommended +#define SCSIS_ASC_PARAM_LIST_LENGTH_ERR 0x1a00 // parameter list too short +#define SCSIS_ASC_ID_RECOV 0x1e00 // recoved ID with ECC +#define SCSIS_ASC_INV_OPCODE 0x2000 +#define SCSIS_ASC_LBA_OOR 0x2100 // LBA out of range +#define SCSIS_ASC_ILL_FUNCTION 0x2200 // better use 0x2000/0x2400/0x2600 instead +#define SCSIS_ASC_INV_CDB_FIELD 0x2400 +#define SCSIS_ASC_LUN_NOT_SUPPORTED 0x2500 +#define SCSIS_ASC_INV_PARAM_LIST_FIELD 0x2600 +#define SCSIS_ASC_PARAM_NOT_SUPPORTED 0x2601 +#define SCSIS_ASC_PARAM_VALUE_INV 0x2602 +#define SCSIS_ASC_WRITE_PROTECTED 0x2700 +#define SCSIS_ASC_MEDIUM_CHANGED 0x2800 +#define SCSIS_ASC_WAS_RESET 0x2900 // reset by power-on/bus reset/device reset +#define SCSIS_ASC_PARAMS_CHANGED 0x2a00 +#define SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED 0x3100 +#define SCSIS_ASC_ROUNDED_PARAM 0x3700 // parameter got rounded +#define SCSIS_ASC_NO_MEDIUM 0x3a00 // medium not present +#define SCSIS_ASC_INTERNAL_FAILURE 0x4400 +#define SCSIS_ASC_SEL_FAILURE 0x4500 // select/reselect failure +#define SCSIS_ASC_UNSUCC_SOFT_RESET 0x4600 // unsuccessful soft reset +#define SCSIS_ASC_SCSI_PARITY_ERR 0x4700 // SCSI parity error +#define SCSIS_ASC_LOAD_EJECT_FAILED 0x5300 // media load or eject failed +#define SCSIS_ASC_REMOVAL_PREVENTED 0x5302 // medium removal prevented +#define SCSIS_ASC_REMOVAL_REQUESTED 0x5a01 // operator requests medium removal + + +// some scsi op-codes +#define SCSI_OP_TUR 0x00 +#define SCSI_OP_REQUEST_SENSE 0x03 +#define SCSI_OP_FORMAT 0x04 +#define SCSI_OP_READ_6 0x08 +#define SCSI_OP_WRITE_6 0x0a +#define SCSI_OP_INQUIRY 0x12 +#define SCSI_OP_MODE_SELECT_6 0x15 +#define SCSI_OP_RESERVE 0x16 +#define SCSI_OP_RELEASE 0x17 +#define SCSI_OP_MODE_SENSE_6 0x1a +#define SCSI_OP_START_STOP 0x1b +#define SCSI_OP_RECEIVE_DIAGNOSTIC 0x1c +#define SCSI_OP_SEND_DIAGNOSTIC 0x1d +#define SCSI_OP_PREVENT_ALLOW 0x1e +#define SCSI_OP_READ_CAPACITY 0x25 +#define SCSI_OP_READ_10 0x28 +#define SCSI_OP_WRITE_10 0x2a +#define SCSI_OP_POSITION_TO_ELEMENT 0x2b +#define SCSI_OP_VERIFY 0x2f +#define SCSI_OP_SYNCHRONIZE_CACHE 0x35 +#define SCSI_OP_WRITE_BUFFER 0x3b +#define SCSI_OP_READ_BUFFER 0x3c +#define SCSI_OP_CHANGE_DEFINITION 0x40 +#define SCSI_OP_READ_SUB_CHANNEL 0x42 +#define SCSI_OP_READ_TOC 0x43 +#define SCSI_OP_PLAY_MSF 0x47 +#define SCSI_OP_PLAY_AUDIO_TRACK_INDEX 0x48 // obsolete, spec missing +#define SCSI_OP_PAUSE_RESUME 0x4b +#define SCSI_OP_STOP_PLAY 0x4e +#define SCSI_OP_MODE_SELECT_10 0x55 +#define SCSI_OP_MODE_SENSE_10 0x5A +#define SCSI_OP_MOVE_MEDIUM 0xa5 +#define SCSI_OP_READ_12 0xa8 +#define SCSI_OP_WRITE_12 0xaa +#define SCSI_OP_READ_ELEMENT_STATUS 0xb8 +#define SCSI_OP_SCAN 0xba +#define SCSI_OP_READ_CD 0xbe + +// INQUIRY + +typedef struct scsi_cmd_inquiry { + uint8 opcode; + LBITFIELD8_3( + EVPD : 1, // enhanced vital product data + res1_1 : 4, + LUN : 3 + ); + uint8 page_code; + uint8 res3; + uint8 allocation_length; + uint8 control; +} scsi_cmd_inquiry; + +typedef struct scsi_res_inquiry { + LBITFIELD8_2( + device_type : 5, + device_qualifier : 3 + ); + LBITFIELD8_2( + device_type_modifier : 7, // obsolete, normally set to zero + RMB : 1 // 1 = removable medium + ); + LBITFIELD8_3( // 0 always means "not conforming" + ANSI_version : 3, // 1 for SCSI-1, 2 for SCSI-2 etc. + ECMA_version : 3, + ISO_version : 2 + ); + LBITFIELD8_4( + response_data_format : 4, // 2 = SCSI/2 compliant + res3_4 : 2, + TrmIOP : 1, // 1 = supports TERMINATE I/O PROCESS + AENC : 1 // processor devices only : + // Asynchronous Event Notification Capable + ); + uint8 additional_length; // total (whished) length = this + 4 + uint8 res5; + uint8 res6; + LBITFIELD8_8( + SftRe : 1, // 0 = soft reset leads to hard reset + CmdQue : 1, // 1 = supports tagged command queuing + res7_2 : 1, + Linked : 1, // 1 = supports linked commands + Sync : 1, // 1 = supports synchronous transfers + WBus16 : 1, // 1 = supports 16 bit transfers + WBus32 : 1, // 1 = supports 32 bit transfers + RelAdr : 1 // 1 = supports relative addr. for linking + ); + char vendor_ident[8]; // 8 + char product_ident[16]; // 16 + char product_rev[4]; // 32 + + // XPT doesn't return following data on XPT_GDEV_TYPE + uint8 vendor_spec[20]; // 36 + uint8 res56[2]; // 56 + + struct { + uint8 high; + uint8 low; + } version_descriptor[8]; // array of supported standards + + uint8 res74[22]; // 74 + + /* additional vendor specific data */ // 96 +} scsi_res_inquiry; + +enum { + scsi_periph_qual_connected = 0, + scsi_periph_qual_not_connected = 2, + scsi_periph_qual_not_connectable = 3 + // value 1 is reserved, values of 4 and above are vendor-specific +} scsi_peripheral_qualifier; + +enum { + scsi_dev_direct_access = 0, + scsi_dev_sequential_access = 1, + scsi_dev_printer = 2, + scsi_dev_processor = 3, + scsi_dev_WORM = 4, + scsi_dev_CDROM = 5, + scsi_dev_scanner = 6, + scsi_dev_optical = 7, + scsi_dev_medium_changer = 8, + scsi_dev_communication = 9, + // 0xa - 0xb are graphics arts pre-press devices + // 0xc - 0x1e reserved + scsi_dev_storage_array = 0xc, + scsi_dev_enclosure_services = 0xd, + scsi_dev_simplified_direct_access = 0xe, + scsi_dev_optical_card = 0xf, + scsi_dev_unknown = 0x1f // used for scsi_periph_qual_not_connectable +} scsi_device_type; + + +// vital product data: unit serial number page + +#define SCSI_PAGE_USN 0x80 + +typedef struct scsi_page_USN { + LBITFIELD8_2( + device_type : 5, + device_qualifier : 3 + ); + uint8 page_code; + uint8 res2; + + uint8 page_length; // total size = this + 3 + char PSN[1]; // size according to page_length +} scsi_page_USN; + +// READ CAPACITY + +typedef struct scsi_cmd_read_capacity { + uint8 opcode; + LBITFIELD8_3( + RelAdr : 1, // relative address + res1_1 : 4, + LUN : 3 + ); + uint8 top_LBA; + uint8 high_LBA; + uint8 mid_LBA; + uint8 low_LBA; + uint8 res6[2]; + LBITFIELD8_2( + PMI : 1, // partial medium indicator + res8_1 : 7 + ); + uint8 control; +} scsi_cmd_read_capacity; + +typedef struct scsi_res_read_capacity { + uint8 top_LBA; + uint8 high_LBA; + uint8 mid_LBA; + uint8 low_LBA; + uint8 top_block_size; // in bytes + uint8 high_block_size; + uint8 mid_block_size; + uint8 low_block_size; +} scsi_res_read_capacity; + + +// READ (6), WRITE (6) + +typedef struct scsi_cmd_rw_6 { + uint8 opcode; + LBITFIELD8_2( + high_LBA : 5, + LUN : 3 + ); + uint8 mid_LBA; + uint8 low_LBA; + uint8 length; // 0 = 256 blocks + uint8 control; +} scsi_cmd_rw_6; + + +// READ (10), WRITE (10) + +typedef struct scsi_cmd_rw_10 { + uint8 opcode; + LBITFIELD8_5( + RelAdr : 1, // relative address + res1_1 : 2, + FUA : 1, // force unit access (1 = safe, cacheless access) + DPO : 1, // disable page out (1 = not worth caching) + LUN : 3 + ); + uint8 top_LBA; + uint8 high_LBA; + uint8 mid_LBA; + uint8 low_LBA; + uint8 res6; + uint8 high_length; // 0 = no block + uint8 low_length; + uint8 control; +} scsi_cmd_rw_10; + + +// READ (12), WRITE (12) + +typedef struct scsi_cmd_rw_12 { + uint8 opcode; + LBITFIELD8_5( + RelAdr : 1, // relative address + res1_1 : 2, + FUA : 1, // force unit access (1 = safe, cacheless access) + DPO : 1, // disable page out (1 = not worth caching) + LUN : 3 + ); + uint8 top_LBA; + uint8 high_LBA; + uint8 mid_LBA; + uint8 low_LBA; + uint8 top_length; // 0 = no block + uint8 high_length; + uint8 mid_length; + uint8 low_length; + uint8 res10; + uint8 control; +} scsi_cmd_rw_12; + + +// REQUEST SENSE + +typedef struct scsi_cmd_request_sense { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res2[2]; + uint8 alloc_length; + uint8 control; +} scsi_cmd_request_sense; + + +// sense data structures + +#define SCSIS_CURR_ERROR 0x70 +#define SCSIS_DEFERRED_ERROR 0x71 + +typedef struct scsi_sense { + LBITFIELD8_2( + error_code : 7, + valid : 1 // 0 = not conforming to standard + ); + uint8 segment_number; // for COPY/COPY AND VERIFY/COMPARE + LBITFIELD8_5( + sense_key : 4, + res2_4 : 1, + ILI : 1, // incorrect length indicator - req. block + // length doesn't match physical block length + EOM : 1, // serial devices only + Filemark : 1 // optional for random access + ); + + uint8 highest_inf; // device-type or command specific + uint8 high_inf; // device-type 0, 4, 5, 7: block address + uint8 mid_inf; // device-type 1, 2, 3: req length - act. length + uint8 low_inf; // (and others for sequential dev. and COPY cmds + + uint8 add_sense_length; // total length = this + 7 + + uint8 highest_cmd_inf; + uint8 high_cmd_inf; + uint8 mid_cmd_inf; + uint8 low_cmd_inf; + uint8 asc; + uint8 ascq; // this can be zero if unsupported + uint8 unit_code; // != 0 to specify internal device unit + + union { + struct { + LBITFIELD8_2( + high_key_spec : 7, + SKSV : 1 // 1 = sense key specific (byte 15-17) valid + ); + uint8 mid_key_spec; + uint8 low_key_spec; + } raw; + + // ILLEGAL REQUEST + struct { + LBITFIELD8_5( + bit_pointer : 3, // points to (highest) invalid bit of parameter + BPV : 1, // 1 = bit_pointer is valid + res15_4 : 2, + c_d : 2, // 1 = error command, 0 = error in data + SKSV : 1 // s.a. + ); + uint8 high_field_pointer; // points to (highest) invalid byte of parameter + uint8 low_field_pointer; // (!using big endian, this means the first byte!) + } ill_request; + + // access error (RECOVERED, HARDWARE or MEDIUM ERROR) + struct { + LBITFIELD8_2( + res15_0 : 7, + SKSV : 1 + ); + uint8 high_retry_cnt; + uint8 low_retry_cnt; + } acc_error; + + // format progress (if sense key = NOT READY) + struct { + LBITFIELD8_2( + res15_0 : 7, + SKSV : 1 + ); + uint8 high_progress; // 0 = start, 0xffff = almost finished + uint8 low_progress; + } format_progress; + } sense_key_spec; + + // starting with offset 18 there are additional sense byte +} scsi_sense; + + +// PREVENT ALLOW + +typedef struct scsi_cmd_prevent_allow { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res2[2]; + LBITFIELD8_2( + prevent : 1, // 1 - prevent medium removal, 0 - allow removal + res4_1 : 7 + ); + uint8 control; +} scsi_cmd_prevent_allow; + +// START STOP UNIT + +typedef struct scsi_cmd_ssu { + uint8 opcode; + LBITFIELD8_3( + immed : 1, // 1 - return immediately, 0 - return on completion + res1_1 : 4, + LUN : 3 + ); + uint8 res2[2]; + LBITFIELD8_3( + start : 1, // 1 - load+start, i.e. allow, 0 - eject+stop, i.e. deny + LoEj : 1, // 1 - include loading/ejecting, 0 - only to allow/deny + res4_2 : 6 + ); + uint8 control; +} scsi_cmd_ssu; + + +// MODE SELECT (6) + +typedef struct scsi_cmd_mode_select_6 { + uint8 opcode; + LBITFIELD8_4( + SP : 1, // 1 = save pages to non-volatile memory + res1_1 : 3, + PF : 1, // 0 = old SCSI-1; 1 = new SCSI-2 format + LUN : 3 + ); + uint8 res2[2]; + uint8 param_list_length; // data size + uint8 control; +} scsi_cmd_mode_select_6; + + +// MODE SENSE (6) + +typedef struct scsi_cmd_mode_sense_6 { + uint8 opcode; + LBITFIELD8_4( + res1_0 : 3, + DBD : 1, // disable block descriptors + res1_4 : 1, + LUN : 3 + ); + LBITFIELD8_2( + page_code : 6, + PC : 2 // page control field + ); + uint8 res3; + uint8 allocation_length; // maximum amount of data + uint8 control; +} scsi_cmd_mode_sense_6; + + +// MODE SELECT (10) + +typedef struct scsi_cmd_mode_select_10 { + uint8 opcode; + LBITFIELD8_4( + SP : 1, // 1 = save pages to non-volatile memory + res1_1 : 3, + PF : 1, // 0 = old SCSI-1; 1 = new SCSI-2 format + LUN : 3 + ); + uint8 res2[5]; + uint8 high_param_list_length; // data size + uint8 low_param_list_length; + uint8 control; +} scsi_cmd_mode_select_10; + + +// MODE SENSE (10) + +typedef struct scsi_cmd_mode_sense_10 { + uint8 opcode; + LBITFIELD8_4( + res1_0 : 3, + DBD : 1, // disable block descriptors + res1_4 : 1, + LUN : 3 + ); + LBITFIELD8_2( + page_code : 6, + PC : 2 // page control field + ); + uint8 res3[4]; + uint8 high_allocation_length; // maximum amount of data + uint8 low_allocation_length; + uint8 control; +} scsi_cmd_mode_sense_10; + + +// possible contents of PC +#define SCSI_MODE_SENSE_PC_CURRENT 0 +#define SCSI_MODE_SENSE_PC_CHANGABLE 1 // changable field are filled with "1" +#define SCSI_MODE_SENSE_PC_DEFAULT 2 +#define SCSI_MODE_SENSE_PC_SAVED 3 + +// special mode page indicating to return all mode pages +#define SCSI_MODEPAGE_ALL 0x3f + +// header of mode data; followed by block descriptors and mode pages +typedef struct scsi_mode_param_header_6 { + uint8 mode_data_len; // total length excluding this byte + uint8 medium_type; + uint8 dev_spec_parameter; + uint8 block_desc_len; // total length of all transmitted block descriptors +} scsi_mode_param_header_6; + +typedef struct scsi_mode_param_header_10 { + uint8 high_mode_data_len; // total length excluding these two bytes + uint8 low_mode_data_len; + uint8 medium_type; + uint8 dev_spec_parameter; + uint8 res4[2]; + uint8 high_block_desc_len; // total length of all transmitted block descriptors + uint8 low_block_desc_len; +} scsi_mode_param_header_10; + + +// content of dev_spec_parameter for direct access devices +typedef struct scsi_mode_param_dev_spec_da { + LBITFIELD8_4( + res0_0 : 4, + DPOFUA : 1, // 1 = supports DPO and FUA, see READ (10) (sense only) + res0_6 : 1, + WP : 1 // write protected (sense only) + ); +} scsi_mode_param_dev_spec_da; + +typedef struct scsi_mode_param_block_desc { + uint8 density; // density code of area + uint8 high_numblocks; // size of this area in blocks + uint8 med_numblocks; // 0 = all remaining blocks + uint8 low_numblocks; + uint8 res4; + uint8 high_blocklen; // block size + uint8 med_blocklen; + uint8 low_blocklen; +} scsi_mode_param_block_desc; + + +// header of a mode pages +typedef struct scsi_modepage_header { + LBITFIELD8_3( + page_code : 6, + res0_6 : 1, + PS : 1 // 1 = page can be saved (only valid for MODE SENSE) + ); + uint8 page_length; // size of page excluding this common header +} scsi_modepage_header; + + +// control mode page +#define SCSI_MODEPAGE_CONTROL 0xa + +typedef struct scsi_modepage_contr { + scsi_modepage_header header; + LBITFIELD8_2( + RLEC : 1, // Report Log Exception Condition + res2_1 : 7 + ); + LBITFIELD8_4( + DQue : 1, // disable Queuing + QErr : 1, // abort queued commands on contingent allegiance condition + res3_2 : 2, + QAM : 4 // Queue Algorithm Modifier + ); + LBITFIELD8_5( + EAENP : 1, // error AEN permission; true = send AEN on deferred error + // false = generate UA condition after deferred error + UAAENP : 1, // unit attention AEN permission; true = send AEN, + // false = generate UA condition (for everything but init.) + RAENP : 1, // ready AEN permission; true = send async event notification + // (AEN) instead of generating an Unit Attention (UA) Condition + // after initialization + res4_3 : 4, + EECA : 1 // enable Extended Contingent Allegiance + ); + uint8 res5; + uint8 high_AEN_holdoff; // ready AEN hold off period - delay in ms between + uint8 low_AEN_holdoff; // initialization and AEN +} scsi_modepage_contr; + +// values for QAM +#define SCSI_QAM_RESTRICTED 0 +#define SCSI_QAM_UNRESTRICTED 1 +// 2 - 7 reserved, 8 - 0xf vendor-specific + + +// CD audio control page +#define SCSI_MODEPAGE_AUDIO 0xe + +typedef struct scsi_modepage_audio { + scsi_modepage_header header; + LBITFIELD8_4( + res2_0 : 1, + SOTC : 1, // Stop On Track Crossing + // 0 - stop according transfer length, 1 - stop at end of track + IMMED : 1, // must be one + res2_3 : 5 + ); + uint8 res3[3]; + uint8 obs6[2]; + struct { + LBITFIELD8_2( + channel : 4, // select channel to connect to this port + res0_4 : 4 + ); + uint8 volume; + } ports[4]; +} scsi_modepage_audio; + +// connection between output port and audio channel +#define SCSI_CHANNEL_SEL_MUTED 0 // mute port +#define SCSI_CHANNEL_SEL_CHANNEL0 1 // connect to channel 0 +#define SCSI_CHANNEL_SEL_CHANNEL1 2 // connect to channel 1 +#define SCSI_CHANNEL_SEL_CHANNEL0_1 3 // connect to channel 0 and channel 1 +#define SCSI_CHANNEL_SEL_CHANNEL2 4 // connect to channel 2 +#define SCSI_CHANNEL_SEL_CHANNEL3 8 // connect to channel 3 + +// TUR + +typedef struct scsi_cmd_tur { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res3[3]; + uint8 control; +} scsi_cmd_tur; + + +// READ_TOC + +typedef struct scsi_cmd_read_toc { + uint8 opcode; + LBITFIELD8_4( + res1_0 : 1, + TIME : 1, // true, to use TIME format, false for LBA format + res1_2 : 3, + LUN : 3 + ); + LBITFIELD8_2( + format : 4, // see below + res2_4 : 4 + ); + uint8 res3[3]; + uint8 track; // (starting) track + uint8 high_allocation_length; // maximum amount of data + uint8 low_allocation_length; + uint8 control; +} scsi_cmd_read_toc; + +// values of in TOC command +#define SCSI_TOC_FORMAT_TOC 0 // all TOCs starting with (0xaa for lead-out) +#define SCSI_TOC_FORMAT_SESSION_INFO 1 // Session info +#define SCSI_TOC_FORMAT_FULL_TOC 2 // all Q-channel data in TOC +#define SCSI_TOC_FORMAT_PMA 3 // Q-channel data in PMA area +#define SCSI_TOC_FORMAT_ATIP 4 // get ATIP data +#define SCSI_TOC_FORMAT_CD_TEXT 5 // get CD-Text from R/W-channel in lead-in + +// general structure of response +typedef struct scsi_toc_general { + uint8 high_data_len; // total length - 2 + uint8 low_data_len; + uint8 first; // first track/session/reserved + uint8 last; // last one + // remainder are parameter list descriptors +} scsi_toc_general; + +// definition of CD-ROM LBA +typedef struct scsi_cd_lba { + uint8 top; + uint8 high; + uint8 mid; + uint8 low; +} scsi_cd_lba; + +// definition of CD-ROM MSF time +typedef struct scsi_cd_msf { + uint8 reserved; + uint8 minute; + uint8 second; + uint8 frame; +} scsi_cd_msf; + +// definition of Track Number address format +typedef struct scsi_cd_tno { + uint8 res0[3]; + uint8 track; +} scsi_cd_tno; + +// one track for SCSI_TOC_FORMAT_TOC +typedef struct scsi_toc_track { + uint8 res0; + LBITFIELD8_2( + CONTROL : 4, + ADR : 4 + ); + uint8 track_number; // track number (hex) + uint8 res3; + union { // start of track (time or LBA, see TIME of command) + scsi_cd_lba lba; + scsi_cd_msf time; + } start; +} scsi_toc_track; + +// possible value of ADR-field (described Q-channel content) +enum { + scsi_adr_none = 0, // no Q-channel mode info + scsi_adr_position = 1, // Q-channel encodes current position data + scsi_adr_mcn = 2, // Q-channel encodes Media Catalog Number + scsi_adr_isrc = 3 // Q-channel encodes ISRC +} scsi_adr; + +// value of Q-channel control field (CONTROL) +enum { + scsi_q_control_2audio = 0, // stereo audio + scsi_q_control_2audio_preemp = 1, // stereo audio with 50/15µs pre-emphasis + scsi_q_control_1audio = 8, // audio (reserved in CD-R/W) + scsi_q_control_1audio_preemp = 9, // audio with pre-emphasis (reserved in CD-R/W) + scsi_q_control_data_un_intr = 4, // data, recorded un-interrupted + scsi_q_control_data_incr = 5, // data, recorded incremental + scsi_q_control_ddcd = 4, // DDCD data + scsi_q_control_copy_perm = 2 // copy permitted (or-ed with value above) +} scsi_q_control; + +// format SCSI_TOC_FORMAT_TOC +typedef struct scsi_toc_toc { + uint8 high_data_len; // total length - 2 (independant of actual size) + uint8 low_data_len; + uint8 first_track; // first track (hex) + uint8 last_track; // last track (hex) + + scsi_toc_track tracks[1]; // one entry per track +} scsi_toc_toc; + + +// READ SUB-CHANNEL + +typedef struct scsi_cmd_read_subchannel { + uint8 opcode; + LBITFIELD8_4( + res1_0 : 1, + TIME : 1, // true, to use TIME format, false for LBA format + res1_2 : 3, + LUN : 3 + ); + LBITFIELD8_3( + res2_0 : 6, + SUBQ : 1, // 1 - return Q sub-channel data + res2_7 : 1 + ); + uint8 parameter_list; // see below + uint8 res4[2]; + uint8 track; // track number (hex) + uint8 high_allocation_length; // maximum amount of data + uint8 low_allocation_length; + uint8 control; +} scsi_cmd_read_subchannel; + +// values of parameter_list +enum { + scsi_sub_channel_parameter_list_cd_pos = 1, // CD current position + scsi_sub_channel_parameter_list_mcn = 2, // Media Catalog Number + scsi_sub_channel_parameter_list_isrc = 3 // Track International Standard Recording Code +} scsi_sub_channel_parameter_list; + +// header of response +typedef struct scsi_subchannel_data_header { + uint8 res0; + uint8 audio_status; // see below + uint8 high_data_len; // total length - 4 + uint8 low_data_len; +} scsi_subchannel_data_header; + +// possible audio_status +enum { + scsi_audio_status_not_supported = 0, + scsi_audio_status_playing = 0x11, + scsi_audio_status_paused = 0x12, + scsi_audio_status_completed = 0x13, + scsi_audio_status_error_stop = 0x14, + scsi_audio_status_no_status = 0x15 +} scsi_audio_status; + +typedef struct scsi_cd_current_position { + uint8 format_code; // always 1 + LBITFIELD8_2( + CONTROL : 4, // see scsi_q_control + ADR : 4 // see scsi_adr + ); + uint8 track; + uint8 index; + union { // current position, relative to logical beginning + scsi_cd_lba lba; + scsi_cd_msf time; + } absolute_address; + union { // current position, relative to track + scsi_cd_lba lba; + scsi_cd_msf time; + } track_relative_address; +} scsi_cd_current_position; + + +// PLAY AUDIO MSF + +typedef struct scsi_cmd_play_msf { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res2; + uint8 start_minute; // start time + uint8 start_second; + uint8 start_frame; + uint8 end_minute; // end time (excluding) + uint8 end_second; + uint8 end_frame; + uint8 control; +} scsi_cmd_play_msf; + + +// STOP AUDIO + +typedef struct scsi_cmd_stop_play { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res2[7]; + uint8 control; +} scsi_cmd_stop_play; + + +// PAUSE/RESUME + +typedef struct scsi_cmd_pause_resume { + uint8 opcode; + LBITFIELD8_2( + res1_0 : 5, + LUN : 3 + ); + uint8 res2[6]; + LBITFIELD8_2( + resume : 1, // 1 for resume, 0 for pause + res8_2 : 7 + ); + uint8 control; +} scsi_cmd_pause_resume; + + +// SCAN + +typedef struct scsi_cmd_scan { + uint8 opcode; + LBITFIELD8_4( + RELADR : 1, // must be 0 + res1_1 : 3, + Direct : 1, // direction: 0 forward, 1 backward + LUN : 3 + ); + union { // start of track (depends on ) + scsi_cd_lba lba; + scsi_cd_msf time; + scsi_cd_tno tno; + } start; + uint8 res6[3]; + LBITFIELD8_2( + res9_0 : 6, + type : 2 // actual type of (see below) + ); + uint8 res10; + uint8 control; +} scsi_cmd_scan; + +// possible values for type +enum { + scsi_scan_lba = 0, + scsi_scan_msf = 1, + scsi_scan_tno = 2 +} scsi_scan_type; + + +// READ_CD + +typedef struct scsi_cmd_read_cd { + uint8 opcode; + LBITFIELD8_4( + RELADR : 1, // must be 0 + res1_1 : 1, + sector_type : 3, // required sector type (1=CDDA) + LUN : 3 + ); + scsi_cd_lba lba; + uint8 high_length; + uint8 mid_length; + uint8 low_length; + LBITFIELD8_6( + res9_0 : 1, + error_field : 2, + EDC_ECC : 1, // include EDC/ECC; includes 8 byte padding for Mode 1 format + user_data : 1, // if 1, include user data + // (mode select block size is ignored) + header_code : 2, + SYNC : 1 // if 1, include sync field from sector + ); + LBITFIELD8_2( + sub_channel_selection : 4, + res10_4 : 4 + ); + uint8 control; +} scsi_cmd_read_cd; + +// possible values for header_code +enum { + scsi_read_cd_header_none = 0, + scsi_read_cd_header_hdr_only = 1, + scsi_read_cd_header_sub_header_only = 2, + scsi_read_cd_header_all_headers = 3, +} scsi_read_cd_header_code; + +// possible values for error_field +enum { + scsi_read_cd_error_none = 0, + scsi_read_cd_error_c2_error = 1, // include 2352 bits indicating error in byte + scsi_read_cd_error_c2_and_block_error = 2, // include or of C2 data plus pad byte +} scsi_read_cd_error_field; + +// possible values for sub_channel_selection +enum { + scsi_read_cd_sub_channel_none = 0, + scsi_read_cd_sub_channel_RAW = 1, + scsi_read_cd_sub_channel_Q = 2, + scsi_read_cd_sub_channel_P_W = 4 // R/W data, depending on CD capabilities + // and Mechanism status page +} scsi_read_cd_sub_channel_selection; + +#endif diff --git a/headers/os/drivers/bus/scsi/scsi_periph.h b/headers/os/drivers/bus/scsi/scsi_periph.h new file mode 100644 index 0000000000..ffec0efe1a --- /dev/null +++ b/headers/os/drivers/bus/scsi/scsi_periph.h @@ -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 +#include +#include +#include + +// 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 diff --git a/headers/os/drivers/fast_log.h b/headers/os/drivers/fast_log.h new file mode 100644 index 0000000000..310a758e95 --- /dev/null +++ b/headers/os/drivers/fast_log.h @@ -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 + +// 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 diff --git a/headers/os/drivers/lendian_bitfield.h b/headers/os/drivers/lendian_bitfield.h new file mode 100644 index 0000000000..c38f2f038f --- /dev/null +++ b/headers/os/drivers/lendian_bitfield.h @@ -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 +#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 */ diff --git a/headers/os/drivers/locked_pool.h b/headers/os/drivers/locked_pool.h new file mode 100644 index 0000000000..2a0064d2a6 --- /dev/null +++ b/headers/os/drivers/locked_pool.h @@ -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 + +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 diff --git a/headers/os/drivers/pnp_devfs.h b/headers/os/drivers/pnp_devfs.h new file mode 100644 index 0000000000..bbd830bbdf --- /dev/null +++ b/headers/os/drivers/pnp_devfs.h @@ -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 +#include +//#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