#ifndef _SMRT_H
#define _SMRT_H
#include <sys/types.h>
#include <sys/pci.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/conf.h>
#include <sys/map.h>
#include <sys/modctl.h>
#include <sys/kmem.h>
#include <sys/cmn_err.h>
#include <sys/stat.h>
#include <sys/scsi/scsi.h>
#include <sys/scsi/impl/spc3_types.h>
#include <sys/devops.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/sdt.h>
#include <sys/policy.h>
#include <sys/ctype.h>
#if !defined(_LITTLE_ENDIAN) || !defined(_BIT_FIELDS_LTOH)
#error "smrt: driver works only on little endian systems"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define SMRT_MAX_LOGDRV 64
#define SMRT_MAX_PHYSDEV 128
#include <sys/scsi/adapters/smrt/smrt_ciss.h>
#include <sys/scsi/adapters/smrt/smrt_scsi.h>
#ifdef __cplusplus
extern "C" {
#endif
extern ddi_device_acc_attr_t smrt_dev_attributes;
typedef enum smrt_init_level {
SMRT_INITLEVEL_BASIC = (0x1 << 0),
SMRT_INITLEVEL_I2O_MAPPED = (0x1 << 1),
SMRT_INITLEVEL_CFGTBL_MAPPED = (0x1 << 2),
SMRT_INITLEVEL_PERIODIC = (0x1 << 3),
SMRT_INITLEVEL_INT_ALLOC = (0x1 << 4),
SMRT_INITLEVEL_INT_ADDED = (0x1 << 5),
SMRT_INITLEVEL_INT_ENABLED = (0x1 << 6),
SMRT_INITLEVEL_SCSA = (0x1 << 7),
SMRT_INITLEVEL_MUTEX = (0x1 << 8),
SMRT_INITLEVEL_TASKQ = (0x1 << 9),
SMRT_INITLEVEL_ASYNC_EVENT = (0x1 << 10),
} smrt_init_level_t;
#define SMRT_PRE_TAG_NUMBER 0x00000bad
#define SMRT_MIN_TAG_NUMBER 0x00001000
#define SMRT_MAX_TAG_NUMBER 0x0fffffff
#define SMRT_IPORT_PHYS "p0"
#define SMRT_IPORT_VIRT "v0"
#define SMRT_WAIT_DELAY_SECONDS 120
typedef enum smrt_wait_state {
SMRT_WAIT_STATE_READY = 1,
SMRT_WAIT_STATE_UNREADY
} smrt_wait_state_t;
typedef enum smrt_ctlr_mode {
SMRT_CTLR_MODE_UNKNOWN = 0,
SMRT_CTLR_MODE_SIMPLE
} smrt_ctlr_mode_t;
#define SMRT_CONTROLLER_TARGET 128
#define SMRT_DISCOVER_TIMEOUT 30
#define SMRT_PERIODIC_RATE 5
#define SMRT_PING_CHECK_TIMEOUT 60
#define SMRT_ASYNC_CANCEL_TIMEOUT 60
#define SMRT_VENDOR_HP 0x103c
#define SMRT_DEVICE_GEN9 0x3238
typedef enum smrt_controller_status {
SMRT_CTLR_STATUS_DETACHING = (0x1 << 0),
SMRT_CTLR_STATUS_RUNNING = (0x1 << 1),
SMRT_CTLR_STATUS_RESETTING = (0x1 << 2),
SMRT_CTLR_ASYNC_INTERVENTION = (0x1 << 3),
SMRT_CTLR_DISCOVERY_REQUESTED = (0x1 << 4),
SMRT_CTLR_DISCOVERY_RUNNING = (0x1 << 5),
SMRT_CTLR_DISCOVERY_PERIODIC = (0x1 << 6),
SMRT_CTLR_DISCOVERY_REQUIRED = (0x1 << 7),
} smrt_controller_status_t;
#define SMRT_CTLR_DISCOVERY_MASK (SMRT_CTLR_DISCOVERY_REQUESTED | \
SMRT_CTLR_DISCOVERY_RUNNING | SMRT_CTLR_DISCOVERY_PERIODIC)
typedef struct smrt_stats {
uint64_t smrts_tran_aborts;
uint64_t smrts_tran_resets;
uint64_t smrts_tran_starts;
uint64_t smrts_ctlr_resets;
unsigned smrts_max_inflight;
uint64_t smrts_unclaimed_interrupts;
uint64_t smrts_claimed_interrupts;
uint64_t smrts_ignored_scsi_cmds;
uint64_t smrts_events_received;
uint64_t smrts_events_errors;
uint64_t smrts_events_intervened;
uint64_t smrts_discovery_tq_errors;
} smrt_stats_t;
typedef struct smrt_versions {
uint8_t smrtv_hardware_version;
char smrtv_firmware_rev[5];
char smrtv_recovery_rev[5];
char smrtv_bootblock_rev[5];
} smrt_versions_t;
typedef struct smrt smrt_t;
typedef struct smrt_command smrt_command_t;
typedef struct smrt_command_internal smrt_command_internal_t;
typedef struct smrt_command_scsa smrt_command_scsa_t;
typedef struct smrt_pkt smrt_pkt_t;
struct smrt {
dev_info_t *smrt_dip;
int smrt_instance;
smrt_controller_status_t smrt_status;
smrt_stats_t smrt_stats;
uint32_t smrt_host_support;
uint32_t smrt_bus_support;
uint32_t smrt_maxcmds;
uint32_t smrt_sg_cnt;
smrt_versions_t smrt_versions;
uint16_t smrt_pci_vendor;
uint16_t smrt_pci_device;
dev_info_t *smrt_virt_iport;
dev_info_t *smrt_phys_iport;
scsi_hba_tgtmap_t *smrt_virt_tgtmap;
scsi_hba_tgtmap_t *smrt_phys_tgtmap;
smrt_ctlr_mode_t smrt_ctlr_mode;
smrt_init_level_t smrt_init_level;
kmutex_t smrt_mutex;
kcondvar_t smrt_cv_finishq;
list_t smrt_volumes;
list_t smrt_physicals;
list_t smrt_targets;
uint32_t smrt_last_heartbeat;
hrtime_t smrt_last_heartbeat_time;
hrtime_t smrt_last_interrupt_claimed;
hrtime_t smrt_last_interrupt_unclaimed;
hrtime_t smrt_last_reset_start;
hrtime_t smrt_last_reset_finish;
uint32_t smrt_next_tag;
avl_tree_t smrt_inflight;
list_t smrt_commands;
list_t smrt_finishq;
list_t smrt_abortq;
ddi_taskq_t *smrt_discover_taskq;
hrtime_t smrt_last_phys_discovery;
hrtime_t smrt_last_log_discovery;
uint64_t smrt_discover_gen;
int smrt_interrupt_type;
int smrt_interrupt_cap;
uint_t smrt_interrupt_pri;
ddi_intr_handle_t smrt_interrupts[1];
int smrt_ninterrupts;
ddi_periodic_t smrt_periodic;
scsi_hba_tran_t *smrt_hba_tran;
ddi_dma_attr_t smrt_dma_attr;
unsigned smrt_i2o_bar;
caddr_t smrt_i2o_space;
ddi_acc_handle_t smrt_i2o_handle;
unsigned smrt_ct_bar;
uint32_t smrt_ct_baseaddr;
CfgTable_t *smrt_ct;
ddi_acc_handle_t smrt_ct_handle;
uint32_t smrt_event_count;
smrt_command_t *smrt_event_cmd;
smrt_command_t *smrt_event_cancel_cmd;
kcondvar_t smrt_event_queue;
};
typedef enum smrt_volume_flags {
SMRT_VOL_FLAG_WWN = (0x1 << 0),
} smrt_volume_flags_t;
typedef struct smrt_volume {
LUNAddr_t smlv_addr;
smrt_volume_flags_t smlv_flags;
uint8_t smlv_wwn[16];
uint64_t smlv_gen;
smrt_t *smlv_ctlr;
list_node_t smlv_link;
list_t smlv_targets;
} smrt_volume_t;
typedef struct smrt_physical {
LUNAddr_t smpt_addr;
uint64_t smpt_wwn;
uint8_t smpt_dtype;
uint16_t smpt_bmic;
uint64_t smpt_gen;
boolean_t smpt_supported;
boolean_t smpt_visible;
boolean_t smpt_unsup_warn;
list_node_t smpt_link;
list_t smpt_targets;
smrt_t *smpt_ctlr;
smrt_identify_physical_drive_t *smpt_info;
} smrt_physical_t;
typedef struct smrt_target {
struct scsi_device *smtg_scsi_dev;
boolean_t smtg_physical;
boolean_t smtg_gone;
union {
smrt_physical_t *smtg_phys;
smrt_volume_t *smtg_vol;
} smtg_lun;
list_node_t smtg_link_lun;
LUNAddr_t *smtg_addr;
smrt_t *smtg_ctlr;
list_node_t smtg_link_ctlr;
} smrt_target_t;
typedef enum smrt_dma_level {
SMRT_DMALEVEL_HANDLE_ALLOC = (0x1 << 0),
SMRT_DMALEVEL_MEMORY_ALLOC = (0x1 << 1),
SMRT_DMALEVEL_HANDLE_BOUND = (0x1 << 2),
} smrt_dma_level_t;
typedef struct smrt_dma {
smrt_dma_level_t smdma_level;
size_t smdma_real_size;
ddi_dma_handle_t smdma_dma_handle;
ddi_acc_handle_t smdma_acc_handle;
ddi_dma_cookie_t smdma_dma_cookies[1];
uint_t smdma_dma_ncookies;
} smrt_dma_t;
typedef enum smrt_command_status {
SMRT_CMD_STATUS_USED = (0x1 << 0),
SMRT_CMD_STATUS_INFLIGHT = (0x1 << 1),
SMRT_CMD_STATUS_TIMEOUT = (0x1 << 2),
SMRT_CMD_STATUS_ERROR = (0x1 << 3),
SMRT_CMD_STATUS_ABANDONED = (0x1 << 4),
SMRT_CMD_STATUS_COMPLETE = (0x1 << 5),
SMRT_CMD_STATUS_POLLED = (0x1 << 6),
SMRT_CMD_STATUS_POLL_COMPLETE = (0x1 << 7),
SMRT_CMD_STATUS_ABORT_SENT = (0x1 << 8),
SMRT_CMD_STATUS_TRAN_START = (0x1 << 9),
SMRT_CMD_STATUS_TRAN_IGNORED = (0x1 << 10),
SMRT_CMD_STATUS_REUSED = (0x1 << 11),
SMRT_CMD_STATUS_RESET_SENT = (0x1 << 12),
SMRT_CMD_IGNORE_RUNNING = (0x1 << 13),
} smrt_command_status_t;
typedef enum smrt_command_type {
SMRT_CMDTYPE_INTERNAL = 1,
SMRT_CMDTYPE_EVENT,
SMRT_CMDTYPE_ABORTQ,
SMRT_CMDTYPE_SCSA,
SMRT_CMDTYPE_PREINIT,
} smrt_command_type_t;
struct smrt_command {
uint32_t smcm_tag;
smrt_command_type_t smcm_type;
smrt_command_status_t smcm_status;
smrt_t *smcm_ctlr;
smrt_target_t *smcm_target;
list_node_t smcm_link;
list_node_t smcm_link_finish;
list_node_t smcm_link_abort;
avl_node_t smcm_node;
hrtime_t smcm_time_submit;
hrtime_t smcm_time_complete;
hrtime_t smcm_expiry;
hrtime_t smcm_abort_time;
uint32_t smcm_abort_tag;
smrt_command_scsa_t *smcm_scsa;
smrt_command_internal_t *smcm_internal;
smrt_dma_t smcm_contig;
CommandList_t *smcm_va_cmd;
uint32_t smcm_pa_cmd;
ErrorInfo_t *smcm_va_err;
uint32_t smcm_pa_err;
};
struct smrt_command_internal {
smrt_dma_t smcmi_contig;
void *smcmi_va;
uint32_t smcmi_pa;
size_t smcmi_len;
};
struct smrt_command_scsa {
struct scsi_pkt *smcms_pkt;
smrt_command_t *smcms_command;
};
void smrt_periodic(void *);
void smrt_lockup_check(smrt_t *);
int smrt_submit(smrt_t *, smrt_command_t *);
void smrt_submit_simple(smrt_t *, smrt_command_t *);
int smrt_retrieve(smrt_t *);
void smrt_retrieve_simple(smrt_t *);
int smrt_poll_for(smrt_t *, smrt_command_t *);
int smrt_preinit_command_simple(smrt_t *, smrt_command_t *);
int smrt_interrupts_setup(smrt_t *);
int smrt_interrupts_enable(smrt_t *);
void smrt_interrupts_teardown(smrt_t *);
uint32_t smrt_isr_hw_simple(caddr_t, caddr_t);
void smrt_intr_set(smrt_t *, boolean_t);
int smrt_ctlr_init(smrt_t *);
void smrt_ctlr_teardown(smrt_t *);
int smrt_ctlr_reset(smrt_t *);
int smrt_ctlr_wait_for_state(smrt_t *, smrt_wait_state_t);
int smrt_ctlr_init_simple(smrt_t *);
void smrt_ctlr_teardown_simple(smrt_t *);
int smrt_cfgtbl_flush(smrt_t *);
int smrt_cfgtbl_transport_has_support(smrt_t *, int);
void smrt_cfgtbl_transport_set(smrt_t *, int);
int smrt_cfgtbl_transport_confirm(smrt_t *, int);
uint32_t smrt_ctlr_get_cmdsoutmax(smrt_t *);
uint32_t smrt_ctlr_get_maxsgelements(smrt_t *);
void smrt_discover_request(smrt_t *);
int smrt_logvol_discover(smrt_t *, uint16_t, uint64_t);
void smrt_logvol_teardown(smrt_t *);
smrt_volume_t *smrt_logvol_lookup_by_id(smrt_t *, unsigned long);
void smrt_logvol_tgtmap_activate(void *, char *, scsi_tgtmap_tgt_type_t,
void **);
boolean_t smrt_logvol_tgtmap_deactivate(void *, char *, scsi_tgtmap_tgt_type_t,
void *, scsi_tgtmap_deact_rsn_t);
int smrt_phys_discover(smrt_t *, uint16_t, uint64_t);
smrt_physical_t *smrt_phys_lookup_by_ua(smrt_t *, const char *);
void smrt_phys_teardown(smrt_t *);
void smrt_phys_tgtmap_activate(void *, char *, scsi_tgtmap_tgt_type_t,
void **);
boolean_t smrt_phys_tgtmap_deactivate(void *, char *, scsi_tgtmap_tgt_type_t,
void *, scsi_tgtmap_deact_rsn_t);
int smrt_ctrl_hba_setup(smrt_t *);
void smrt_ctrl_hba_teardown(smrt_t *);
int smrt_logvol_hba_setup(smrt_t *, dev_info_t *);
void smrt_logvol_hba_teardown(smrt_t *, dev_info_t *);
int smrt_phys_hba_setup(smrt_t *, dev_info_t *);
void smrt_phys_hba_teardown(smrt_t *, dev_info_t *);
void smrt_hba_complete(smrt_command_t *);
void smrt_process_finishq(smrt_t *);
void smrt_process_abortq(smrt_t *);
smrt_command_t *smrt_command_alloc(smrt_t *, smrt_command_type_t,
int);
smrt_command_t *smrt_command_alloc_preinit(smrt_t *, size_t, int);
int smrt_command_attach_internal(smrt_t *, smrt_command_t *, size_t,
int);
void smrt_command_free(smrt_command_t *);
smrt_command_t *smrt_lookup_inflight(smrt_t *, uint32_t);
void smrt_command_reuse(smrt_command_t *);
void smrt_write_lun_addr_phys(LUNAddr_t *, boolean_t, unsigned, unsigned);
void smrt_write_controller_lun_addr(LUNAddr_t *);
uint16_t smrt_lun_addr_to_bmic(PhysDevAddr_t *);
void smrt_write_message_abort_one(smrt_command_t *, uint32_t);
void smrt_write_message_abort_all(smrt_command_t *, LUNAddr_t *);
void smrt_write_message_nop(smrt_command_t *, int);
void smrt_write_message_event_notify(smrt_command_t *);
int smrt_device_setup(smrt_t *);
void smrt_device_teardown(smrt_t *);
uint32_t smrt_get32(smrt_t *, offset_t);
void smrt_put32(smrt_t *, offset_t, uint32_t);
int smrt_sata_determine_wwn(smrt_t *, PhysDevAddr_t *, uint64_t *, uint16_t);
int smrt_event_init(smrt_t *);
void smrt_event_fini(smrt_t *);
void smrt_event_complete(smrt_command_t *);
#ifdef __cplusplus
}
#endif
#endif