#ifndef _SCSI_INTERNAL_H
#define _SCSI_INTERNAL_H
#include <sys/cdefs.h>
#include <bus/SCSI.h>
#include <scsi_cmds.h>
#include <device_manager.h>
#include <lock.h>
#define debug_level_error 4
#define debug_level_info 4
#define debug_level_flow 4
#define DEBUG_MSG_PREFIX "SCSI -- "
#include "wrapper.h"
#include "scsi_lock.h"
#define MAX_PATH_ID 255
#define MAX_TARGET_ID 15
#define MAX_LUN_ID 7
#define MAX_TEMP_SG_FRAGMENTS (128*1024 / B_PAGE_SIZE + 1)
#define MAX_TEMP_SG_LISTS 32
#define SCSI_DMA_BUFFER_CLEANUP_DELAY 10*1000000
#define SCSI_ATAPI_BUFFER_SIZE 512
#define SCSI_PATHID_GENERATOR "scsi/path_id"
#define SCSI_DEVICE_IS_ATAPI_ITEM "scsi/is_atapi"
#define SCSI_DEVICE_MANUAL_AUTOSENSE_ITEM "scsi/manual_autosense"
#define SCSI_BUS_RAW_MODULE_NAME "bus_managers/scsi/bus/raw/device_v1"
typedef struct scsi_dpc_info {
struct scsi_dpc_info *next;
bool registered;
void (*func)( void * );
void *arg;
} scsi_dpc_info;
typedef struct dma_params {
uint32 alignment;
uint32 max_blocks;
uint32 dma_boundary;
uint32 max_sg_block_size;
uint32 max_sg_blocks;
uint64 high_address;
} dma_params;
typedef struct scsi_bus_info {
int lock_count;
int blocked[2];
int left_slots;
bool sim_overflow;
uchar path_id;
uint32 max_target_count;
uint32 max_lun_count;
thread_id service_thread;
sem_id start_service;
bool shutting_down;
struct mutex mutex;
sem_id scan_lun_lock;
scsi_sim_interface *interface;
scsi_sim_cookie sim_cookie;
spinlock_irq dpc_lock;
scsi_dpc_info *dpc_list;
struct scsi_device_info *waiting_devices;
device_node *node;
struct dma_params dma_params;
scsi_path_inquiry inquiry_data;
} scsi_bus_info;
typedef struct dma_buffer {
area_id area;
uchar *address;
size_t size;
area_id sg_list_area;
physical_entry *sg_list;
uint32 sg_count;
bool inuse;
bigtime_t last_use;
area_id sg_orig;
physical_entry *sg_list_orig;
uint32 sg_count_max_orig;
uint32 sg_count_orig;
uchar *orig_data;
const physical_entry *orig_sg_list;
uint32 orig_sg_count;
} dma_buffer;
typedef struct scsi_device_info {
struct scsi_device_info *waiting_next;
struct scsi_device_info *waiting_prev;
bool manual_autosense : 1;
bool is_atapi : 1;
int lock_count;
int blocked[2];
int sim_overflow;
int left_slots;
int total_slots;
scsi_ccb *queued_reqs;
int64 last_sort;
int32 valid;
scsi_bus_info *bus;
uchar target_id;
uchar target_lun;
scsi_ccb *auto_sense_request;
scsi_ccb *auto_sense_originator;
area_id auto_sense_area;
uint8 emulation_map[256/8];
scsi_res_inquiry inquiry_data;
device_node *node;
struct mutex dma_buffer_lock;
sem_id dma_buffer_owner;
struct dma_buffer dma_buffer;
char *buffer;
physical_entry *buffer_sg_list;
size_t buffer_sg_count;
size_t buffer_size;
area_id buffer_area;
sem_id buffer_sem;
} scsi_device_info;
enum {
ev_scsi_requeue_request = 1,
ev_scsi_resubmit_request,
ev_scsi_submit_autosense,
ev_scsi_finish_autosense,
ev_scsi_device_queue_overflow,
ev_scsi_request_finished,
ev_scsi_async_io,
ev_scsi_do_resend_request,
ev_copy_sg_data
};
#define DEVICE_IN_WAIT_QUEUE( device ) ((device)->waiting_next != NULL)
enum {
SCSI_STATE_INVALID = 0,
SCSI_STATE_INWORK = 1,
SCSI_STATE_QUEUED = 2,
SCSI_STATE_SENT = 3,
SCSI_STATE_FINISHED = 5,
};
extern device_manager_info *pnp;
extern scsi_for_sim_interface scsi_for_sim_module;
extern scsi_bus_interface scsi_bus_module;
extern scsi_device_interface scsi_device_module;
extern struct device_module_info gSCSIBusRawModule;
__BEGIN_DECLS
uchar scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data);
scsi_ccb *scsi_alloc_ccb(scsi_device_info *device);
void scsi_free_ccb(scsi_ccb *ccb);
status_t init_ccb_alloc();
void uninit_ccb_alloc();
status_t scsi_force_get_device(scsi_bus_info *bus,
uchar target_id, uchar target_lun, scsi_device_info **res_device);
void scsi_put_forced_device(scsi_device_info *device);
status_t scsi_register_device(scsi_bus_info *bus, uchar target_id,
uchar target_lun, scsi_res_inquiry *inquiry_data);
status_t scsi_scan_bus(scsi_bus_info *bus);
status_t scsi_scan_lun(scsi_bus_info *bus, uchar target_id, uchar target_lun);
status_t scsi_alloc_dpc(scsi_dpc_info **dpc);
status_t scsi_free_dpc(scsi_dpc_info *dpc);
bool scsi_check_exec_dpc(scsi_bus_info *bus);
status_t scsi_schedule_dpc(scsi_bus_info *bus, scsi_dpc_info *dpc,
void (*func)( void *arg ), void *arg);
void scsi_async_io(scsi_ccb *request);
void scsi_sync_io(scsi_ccb *request);
uchar scsi_term_io(scsi_ccb *ccb_to_terminate);
uchar scsi_abort(scsi_ccb *ccb_to_abort);
bool scsi_check_exec_service(scsi_bus_info *bus);
void scsi_done_io(scsi_ccb *ccb);
void scsi_requeue_request(scsi_ccb *request, bool bus_overflow);
void scsi_resubmit_request(scsi_ccb *request);
void scsi_request_finished(scsi_ccb *request, uint num_requests);
bool create_temp_sg(scsi_ccb *ccb);
void cleanup_temp_sg(scsi_ccb *ccb);
int init_temp_sg(void);
void uninit_temp_sg(void);
void scsi_dma_buffer_daemon(void *dev, int counter);
void scsi_release_dma_buffer(scsi_ccb *request);
bool scsi_get_dma_buffer(scsi_ccb *request);
void scsi_dma_buffer_free(dma_buffer *buffer);
void scsi_dma_buffer_init(dma_buffer *buffer);
bool scsi_start_emulation(scsi_ccb *request);
void scsi_finish_emulation(scsi_ccb *request);
void scsi_free_emulation_buffer(scsi_device_info *device);
status_t scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size);
__END_DECLS
#endif