#ifndef _SYS_SBP2_DRIVER_H
#define _SYS_SBP2_DRIVER_H
#include <sys/sbp2/defs.h>
#include <sys/sbp2/bus.h>
#include <sys/sysmacros.h>
#include <sys/note.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct sbp2_cfgrom_bib {
int cb_len;
uint32_t *cb_buf;
} sbp2_cfgrom_bib_t;
typedef struct sbp2_cfgrom_dir {
struct sbp2_cfgrom_ent *cd_ent;
int cd_cnt;
int cd_size;
} sbp2_cfgrom_dir_t;
typedef struct sbp2_cfgrom_ent {
uint8_t ce_kt;
uint8_t ce_kv;
uint16_t ce_len;
uint64_t ce_offset;
struct sbp2_cfgrom_ent *ce_ref;
union {
uint32_t imm;
uint32_t offset;
uint32_t *leaf;
sbp2_cfgrom_dir_t dir;
} ce_data;
} sbp2_cfgrom_ent_t;
typedef struct sbp2_cfgrom {
sbp2_cfgrom_bib_t cr_bib;
sbp2_cfgrom_ent_t cr_root;
} sbp2_cfgrom_t;
_NOTE(SCHEME_PROTECTS_DATA("stable data", {
sbp2_cfgrom_bib sbp2_cfgrom_dir sbp2_cfgrom_ent sbp2_cfgrom }))
typedef enum {
SBP2_TASK_INIT,
SBP2_TASK_PEND,
SBP2_TASK_COMP,
SBP2_TASK_PROC
} sbp2_task_state_t;
typedef enum {
SBP2_TASK_ERR_NONE,
SBP2_TASK_ERR_DEAD,
SBP2_TASK_ERR_BUS,
SBP2_TASK_ERR_TIMEOUT,
SBP2_TASK_ERR_ABORT,
SBP2_TASK_ERR_LUN_RESET,
SBP2_TASK_ERR_TGT_RESET
} sbp2_task_error;
typedef struct sbp2_task {
struct sbp2_task *ts_next;
struct sbp2_task *ts_prev;
struct sbp2_ses *ts_ses;
void *ts_drv_priv;
sbp2_bus_buf_t *ts_buf;
int ts_timeout;
timeout_id_t ts_timeout_id;
sbp2_task_state_t ts_state;
sbp2_task_error ts_error;
int ts_bus_error;
sbp2_status_t ts_status;
hrtime_t ts_time_start;
hrtime_t ts_time_comp;
} sbp2_task_t;
_NOTE(SCHEME_PROTECTS_DATA("unique per call", sbp2_task))
typedef struct sbp2_agent {
struct sbp2_tgt *a_tgt;
kmutex_t a_mutex;
uint16_t a_state;
kcondvar_t a_cv;
boolean_t a_acquired;
void *a_cmd;
mblk_t *a_cmd_data;
sbp2_task_t *a_active_task;
uint64_t a_reg_agent_state;
uint64_t a_reg_agent_reset;
uint64_t a_reg_orbp;
uint64_t a_reg_doorbell;
uint64_t a_reg_unsol_status_enable;
} sbp2_agent_t;
_NOTE(MUTEX_PROTECTS_DATA(sbp2_agent::a_mutex, sbp2_agent))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_agent::{
a_tgt a_reg_agent_state a_reg_agent_reset a_reg_orbp a_reg_doorbell
a_reg_unsol_status_enable }))
_NOTE(SCHEME_PROTECTS_DATA("a_acquired", sbp2_agent::{
a_cmd a_cmd_data a_active_task }))
typedef struct sbp2_ses {
struct sbp2_tgt *s_tgt;
struct sbp2_lun *s_lun;
kmutex_t s_mutex;
struct sbp2_ses *s_next;
uint16_t s_id;
uint64_t s_agent_offset;
sbp2_agent_t s_agent;
sbp2_bus_buf_t s_status_fifo_buf;
kmutex_t s_task_mutex;
sbp2_task_t *s_task_head;
sbp2_task_t *s_task_tail;
int s_task_cnt;
void (*s_status_cb)(void *, sbp2_task_t *);
void *s_status_cb_arg;
} sbp2_ses_t;
_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_mutex, sbp2_ses))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_ses::{
s_tgt s_lun s_id s_agent_offset s_agent s_status_fifo_buf s_status_cb
s_status_cb_arg }))
_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_ses::{
s_task_head s_task_tail s_task_cnt }))
_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_task::{
ts_next ts_prev }))
typedef struct sbp2_buf_list {
kmutex_t bl_mutex;
int bl_len;
sbp2_bus_buf_t *bl_head;
sbp2_bus_buf_t *bl_tail;
} sbp2_buf_list_t;
typedef struct sbp2_lun {
struct sbp2_tgt *l_tgt;
uint16_t l_lun;
uint8_t l_type;
sbp2_ses_t *l_ses;
sbp2_buf_list_t l_orb_freelist;
sbp2_login_resp_t l_login_resp;
boolean_t l_logged_in;
boolean_t l_reconnecting;
} sbp2_lun_t;
enum {
SBP2_ORB_FREELIST_MAX = 3
};
typedef struct sbp2_tgt_stat {
hrtime_t stat_cfgrom_last_parse_time;
uint_t stat_submit_orbp;
uint_t stat_submit_doorbell;
uint_t stat_status_dead;
uint_t stat_status_short;
uint_t stat_status_unsolicited;
uint_t stat_status_notask;
uint_t stat_status_mgt_notask;
uint_t stat_agent_worbp;
uint_t stat_agent_worbp_fail;
uint_t stat_agent_wreset;
uint_t stat_agent_wreset_fail;
uint_t stat_task_max;
} sbp2_tgt_stat_t;
typedef struct sbp2_tgt {
struct sbp2_bus *t_bus;
void *t_bus_hdl;
kmutex_t t_mutex;
sbp2_lun_t *t_lun;
int t_nluns;
int t_nluns_alloc;
sbp2_cfgrom_t t_cfgrom;
hrtime_t t_last_cfgrd;
int t_orb_size;
uint64_t t_mgt_agent;
int t_mot;
boolean_t t_mgt_agent_acquired;
kcondvar_t t_mgt_agent_cv;
sbp2_bus_buf_t t_mgt_orb_buf;
void *t_mgt_cmd;
mblk_t *t_mgt_cmd_data;
sbp2_bus_buf_t t_mgt_status_fifo_buf;
sbp2_status_t t_mgt_status;
boolean_t t_mgt_status_rcvd;
kcondvar_t t_mgt_status_cv;
sbp2_bus_buf_t t_mgt_login_resp_buf;
sbp2_tgt_stat_t t_stat;
} sbp2_tgt_t;
_NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_tgt))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_tgt::{
t_bus t_bus_hdl t_lun t_nluns t_nluns_alloc t_cfgrom t_last_cfgrd
t_orb_size t_mgt_agent t_mot }))
_NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_tgt::{
t_mgt_orb_buf t_mgt_cmd t_mgt_cmd_data t_mgt_status_fifo_buf
t_mgt_status_rcvd t_mgt_login_resp_buf }))
_NOTE(SCHEME_PROTECTS_DATA("statistics", sbp2_tgt::t_stat))
_NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_lun))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_lun::{
l_tgt l_lun l_type l_ses }))
_NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_lun::l_login_resp))
_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_mutex))
_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_task_mutex))
_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_agent::a_mutex))
#define SBP2_ORB_SIZE_ROUNDUP(tp, size) roundup(size, (tp)->t_orb_size)
enum {
SBP2_WALK_DIRONLY = 0x01
};
enum {
SBP2_WALK_CONTINUE,
SBP2_WALK_STOP
};
int sbp2_tgt_init(void *, struct sbp2_bus *, int, sbp2_tgt_t **);
void sbp2_tgt_fini(sbp2_tgt_t *);
void sbp2_tgt_disconnect(sbp2_tgt_t *);
int sbp2_tgt_reconnect(sbp2_tgt_t *);
int sbp2_tgt_reset(sbp2_tgt_t *, int *);
int sbp2_tgt_get_cfgrom(sbp2_tgt_t *, sbp2_cfgrom_t **);
int sbp2_tgt_get_lun_cnt(sbp2_tgt_t *);
sbp2_lun_t *sbp2_tgt_get_lun(sbp2_tgt_t *, int);
int sbp2_lun_reset(sbp2_lun_t *, int *);
int sbp2_lun_login(sbp2_lun_t *, sbp2_ses_t **, void (*)(void *, sbp2_task_t *),
void *, int *);
int sbp2_lun_logout(sbp2_lun_t *, sbp2_ses_t **, int *, boolean_t);
int sbp2_ses_reconnect(sbp2_ses_t *, int *, uint16_t);
int sbp2_ses_submit_task(sbp2_ses_t *, sbp2_task_t *);
void sbp2_ses_nudge(sbp2_ses_t *);
int sbp2_ses_remove_task(sbp2_ses_t *, sbp2_task_t *);
sbp2_task_t *sbp2_ses_find_task_state(sbp2_ses_t *, sbp2_task_state_t);
sbp2_task_t *sbp2_ses_remove_first_task(sbp2_ses_t *);
sbp2_task_t *sbp2_ses_remove_first_task_state(sbp2_ses_t *, sbp2_task_state_t);
sbp2_task_t *sbp2_ses_cancel_first_task(sbp2_ses_t *);
int sbp2_ses_agent_reset(sbp2_ses_t *, int *);
int sbp2_ses_abort_task(sbp2_ses_t *, sbp2_task_t *, int *);
int sbp2_ses_abort_task_set(sbp2_ses_t *, int *);
int sbp2_task_orb_alloc(sbp2_lun_t *, sbp2_task_t *, int);
void sbp2_task_orb_free(sbp2_lun_t *, sbp2_task_t *);
void *sbp2_task_orb_kaddr(sbp2_task_t *);
void sbp2_task_orb_sync(sbp2_lun_t *, sbp2_task_t *, int);
void sbp2_swap32_buf(uint32_t *, int);
void sbp2_cfgrom_walk(sbp2_cfgrom_ent_t *,
int (*)(void *, sbp2_cfgrom_ent_t *, int), void *);
sbp2_cfgrom_ent_t *sbp2_cfgrom_ent_by_key(sbp2_cfgrom_ent_t *, int8_t, int8_t,
int);
#ifdef __cplusplus
}
#endif
#endif