#ifndef _SYS_1394_TARGETS_SCSA1394_IMPL_H
#define _SYS_1394_TARGETS_SCSA1394_IMPL_H
#include <sys/1394/t1394.h>
#include <sys/sbp2/driver.h>
#include <sys/scsi/scsi.h>
#include <sys/cdio.h>
#include <sys/1394/targets/scsa1394/cmd.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
SCSA1394_THR_INIT,
SCSA1394_THR_RUN,
SCSA1394_THR_EXIT
} scsa1394_thr_state_t;
enum {
SCSA1394_THREQ_EXIT = 0x1,
SCSA1394_THREQ_TASK_STATUS = 0x2,
SCSA1394_THREQ_NUDGE = 0x4,
SCSA1394_THREQ_BUS_RESET = 0x8,
SCSA1394_THREQ_DISCONNECT = 0x10,
SCSA1394_THREQ_RECONNECT = 0x20
};
typedef struct scsa1394_thread {
void (*thr_func)(void *);
void *thr_arg;
struct scsa1394_lun *thr_lun;
scsa1394_thr_state_t thr_state;
kcondvar_t thr_cv;
int thr_req;
} scsa1394_thread_t;
typedef enum {
SCSA1394_DEV_INIT = 0,
SCSA1394_DEV_ONLINE,
SCSA1394_DEV_BUS_RESET,
SCSA1394_DEV_DISCONNECTED,
SCSA1394_DEV_PWRED_DOWN,
SCSA1394_DEV_SUSPENDED
} scsa1394_dev_state_t;
enum { SCSA1394_STAT_NCMD_LAST = 8 };
typedef struct scsa1394_lun_stat {
uint64_t stat_cmd_last_fail[SCSA1394_STAT_NCMD_LAST][3];
int stat_cmd_last_fail_idx;
uint_t stat_cmd_cnt;
uint_t stat_cmd_buf_max_nsegs;
uint_t stat_cmd_buf_dma_partial;
uint_t stat_err_pkt_kmem_alloc;
uint_t stat_err_cmd_cdb_dmem_alloc;
uint_t stat_err_cmd_cdb_dbind;
uint_t stat_err_cmd_cdb_addr_alloc;
uint_t stat_err_cmd_buf_dbind;
uint_t stat_err_cmd_buf_addr_alloc;
uint_t stat_err_cmd_pt_kmem_alloc;
uint_t stat_err_cmd_pt_dmem_alloc;
uint_t stat_err_cmd_pt_addr_alloc;
uint_t stat_err_status_tran_err;
uint_t stat_err_status_conv;
uint_t stat_err_status_resp;
} scsa1394_lun_stat_t;
typedef struct scsa1394_lun {
kmutex_t l_mutex;
struct scsa1394_state *l_sp;
sbp2_lun_t *l_lun;
sbp2_ses_t *l_ses;
dev_info_t *l_cdip;
scsa1394_thread_t l_worker_thread;
ddi_softintr_t l_softintr_id;
boolean_t l_softintr_triggered;
int l_softintr_req;
int l_lba_size;
int l_dtype_orig;
int l_rmb_orig;
int l_start_stop_fail_cnt;
boolean_t l_start_stop_fake;
int l_mode_sense_fail_cnt;
boolean_t l_mode_sense_fake;
boolean_t l_nosup_tur;
boolean_t l_nosup_start_stop;
boolean_t l_nosup_inquiry;
struct scsi_inquiry l_fake_inq;
scsa1394_lun_stat_t l_stat;
} scsa1394_lun_t;
_NOTE(MUTEX_PROTECTS_DATA(scsa1394_lun::l_mutex, scsa1394_lun))
_NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_lun::{
l_sp l_lun l_ses l_cdip l_worker_thread l_softintr_id
l_nosup_tur l_nosup_start_stop l_nosup_inquiry }))
_NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_lun::l_stat))
enum {
SCSA1394_SOFTINTR_STATUS_RCVD = 0x1,
SCSA1394_SOFTINTR_RECONNECT = 0x2
};
typedef struct scsa1394_inst_stat {
uint_t stat_bus_reset_cnt;
uint_t stat_disconnect_cnt;
uint_t stat_reconnect_cnt;
} scsa1394_inst_stat_t;
typedef struct scsa1394_state {
kmutex_t s_mutex;
dev_info_t *s_dip;
int s_instance;
scsa1394_dev_state_t s_dev_state;
t1394_handle_t s_t1394_hdl;
t1394_attachinfo_t s_attachinfo;
t1394_targetinfo_t s_targetinfo;
ddi_callback_id_t s_reset_cb_id;
ddi_callback_id_t s_remove_cb_id;
ddi_callback_id_t s_insert_cb_id;
boolean_t s_event_entered;
kcondvar_t s_event_cv;
ddi_dma_attr_t s_buf_dma_attr;
ddi_dma_attr_t s_pt_dma_attr;
scsi_hba_tran_t *s_tran;
sbp2_tgt_t *s_tgt;
sbp2_cfgrom_t *s_cfgrom;
int s_nluns;
scsa1394_lun_t *s_lun;
kmem_cache_t *s_cmd_cache;
ddi_taskq_t *s_taskq;
boolean_t s_symbios;
boolean_t s_disconnect_warned;
size_t s_totalsec;
size_t s_secsz;
scsa1394_inst_stat_t s_stat;
} scsa1394_state_t;
_NOTE(MUTEX_PROTECTS_DATA(scsa1394_state::s_mutex, scsa1394_state))
_NOTE(SCHEME_PROTECTS_DATA("stable data", scsa1394_state::{
s_dip s_instance s_t1394_hdl s_attachinfo s_reset_cb_id s_remove_cb_id
s_insert_cb_id s_buf_dma_attr s_pt_dma_attr s_tran s_tgt s_cfgrom
s_nluns s_lun s_cmd_cache s_taskq s_symbios s_targetinfo
s_totalsec s_secsz}))
_NOTE(SCHEME_PROTECTS_DATA("statistics", scsa1394_state::s_stat))
_NOTE(LOCK_ORDER(scsa1394_state::s_mutex scsa1394_lun::l_mutex))
typedef struct scsa1394_bus_buf {
scsa1394_state_t *sbb_state;
t1394_addr_handle_t sbb_addr_hdl;
ddi_dma_handle_t sbb_dma_hdl;
ddi_acc_handle_t sbb_acc_hdl;
} scsa1394_bus_buf_t;
_NOTE(SCHEME_PROTECTS_DATA("unique per task", scsa1394_bus_buf))
_NOTE(SCHEME_PROTECTS_DATA("dev_info::devi_lock", dev_info::devi_state))
#define ADDR2TRAN(ap) ((ap)->a_hba_tran)
#define TRAN2STATE(hba) ((scsa1394_state_t *)(hba)->tran_hba_private)
#define ADDR2STATE(ap) (TRAN2STATE(ADDR2TRAN(ap)))
#define SCSA1394_NODEID(sp) ((sp)->s_attachinfo.localinfo.local_nodeID)
#define SCSA1394_BUSGEN(sp) ((sp)->s_attachinfo.localinfo.bus_generation)
#define SCSA1394_ORB_SIZE_ROUNDUP(sp, sz) SBP2_ORB_SIZE_ROUNDUP(sp->s_tgt, sz)
#define SCSA1394_ADDR_SET(sp, var, addr) \
SBP2_ADDR_SET(var, addr, SCSA1394_NODEID(sp))
#define SCSA1394_LBA_6BYTE(pkt) \
(((pkt)->pkt_cdbp[1] & 0x1f) << 16) + \
((pkt)->pkt_cdbp[2] << 8) + (pkt)->pkt_cdbp[3]
#define SCSA1394_LEN_6BYTE(pkt) \
(pkt)->pkt_cdbp[4]
#define SCSA1394_LEN_10BYTE(pkt) \
((pkt)->pkt_cdbp[7] << 8) + (pkt)->pkt_cdbp[8]
#define SCSA1394_LBA_10BYTE(pkt) \
((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) + \
((pkt)->pkt_cdbp[4] << 8) + (pkt)->pkt_cdbp[5]
#define SCSA1394_LEN_12BYTE(pkt) \
((pkt)->pkt_cdbp[6] << 24) + ((pkt)->pkt_cdbp[7] << 16) + \
((pkt)->pkt_cdbp[8] << 8) + (pkt)->pkt_cdbp[9]
#define SCSA1394_LBA_12BYTE(pkt) \
((pkt)->pkt_cdbp[2] << 24) + ((pkt)->pkt_cdbp[3] << 16) + \
((pkt)->pkt_cdbp[4] << 8) + (pkt)->pkt_cdbp[5]
#define SCSA1394_LEN_READ_CD(pkt) \
(((pkt)->pkt_cdbp[6] << 16) + ((pkt)->pkt_cdbp[7] << 8) + \
(pkt)->pkt_cdbp[8])
#define SCSA1394_CDRW_BLKSZ(bcount, len) ((bcount) / (len))
#define SCSA1394_VALID_CDRW_BLKSZ(blksz) \
(((blksz) == CDROM_BLK_2048) || ((blksz) == CDROM_BLK_2352) || \
((blksz) == CDROM_BLK_2336) || ((blksz) == CDROM_BLK_2324))
typedef struct scsa1394_bw_list {
int vid_match;
int vid;
} scsa1394_bw_list_t;
enum {
SCSA1394_BW_ONE,
SCSA1394_BW_ALL
};
#define NELEM(a) (sizeof (a) / sizeof (*(a)))
enum {
SCSA1394_COMPAT_MAX = 1,
SCSA1394_CLEANUP_LEVEL_MAX = 256,
SCSA1394_START_STOP_FAIL_MAX = 3,
SCSA1394_MODE_SENSE_FAIL_MAX = 3,
SCSA1394_START_STOP_TIMEOUT_MAX = 30,
SCSA1394_MAPIN_SIZE_MAX = 512,
SCSA1394_PROBE_TIMEOUT = 15,
SCSA1394_DTYPE_RBC = 0x0E
};
int scsa1394_sbp2_attach(scsa1394_state_t *);
void scsa1394_sbp2_detach(scsa1394_state_t *);
void scsa1394_sbp2_fake_inquiry(scsa1394_state_t *, struct scsi_inquiry *);
int scsa1394_sbp2_threads_init(scsa1394_state_t *);
void scsa1394_sbp2_threads_fini(scsa1394_state_t *);
int scsa1394_sbp2_get_lun_type(scsa1394_lun_t *);
int scsa1394_sbp2_login(scsa1394_state_t *, int);
void scsa1394_sbp2_logout(scsa1394_state_t *, int, boolean_t);
void scsa1394_sbp2_req(scsa1394_state_t *, int, int);
void scsa1394_sbp2_disconnect(scsa1394_state_t *);
void scsa1394_sbp2_seg2pt(scsa1394_lun_t *, scsa1394_cmd_t *);
void scsa1394_sbp2_cmd2orb(scsa1394_lun_t *, scsa1394_cmd_t *);
int scsa1394_sbp2_start(scsa1394_lun_t *, scsa1394_cmd_t *);
void scsa1394_sbp2_nudge(scsa1394_lun_t *);
int scsa1394_sbp2_reset(scsa1394_lun_t *, int, scsa1394_cmd_t *);
void scsa1394_sbp2_flush_cmds(scsa1394_lun_t *, int, int, int);
int scsa1394_thr_dispatch(scsa1394_thread_t *);
void scsa1394_thr_cancel(scsa1394_thread_t *);
void scsa1394_thr_wake(scsa1394_thread_t *, int);
void scsa1394_thr_clear_req(scsa1394_thread_t *, int);
void scsa1394_cmd_status_proc(scsa1394_lun_t *, scsa1394_cmd_t *);
boolean_t scsa1394_dev_is_online(scsa1394_state_t *);
void scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *);
void scsa1394_sbp2_req_reconnect(scsa1394_lun_t *);
#ifdef __cplusplus
}
#endif
#endif