#ifndef _LMRC_RAID_H
#define _LMRC_RAID_H
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/scsi/adapters/mfi/mfi_evt.h>
#include <sys/scsi/adapters/mfi/mfi_ld.h>
#include <sys/scsi/adapters/mpi/mpi2_type.h>
#include <sys/scsi/adapters/mpi/mpi2.h>
#include <sys/scsi/adapters/mpi/mpi2_cnfg.h>
#include <sys/scsi/adapters/mpi/mpi2_ioc.h>
typedef struct lmrc_raidctx_g35 lmrc_raidctx_g35_t;
typedef struct lmrc_devhdl_info lmrc_devhdl_info_t;
typedef struct lmrc_array_info lmrc_array_info_t;
typedef struct lmrc_quad_element lmrc_quad_element_t;
typedef struct lmrc_span_info lmrc_span_info_t;
typedef struct lmrc_ld_span lmrc_ld_span_t;
typedef struct lmrc_span_block_info lmrc_span_block_info_t;
typedef struct lmrc_ld_raid lmrc_ld_raid_t;
typedef struct lmrc_ld_span_map lmrc_ld_span_map_t;
typedef struct lmrc_fw_raid_map lmrc_fw_raid_map_t;
typedef struct lmrc_raid_map_desc lmrc_raid_map_desc_t;
#include "lmrc.h"
#pragma pack(1)
struct lmrc_raidctx_g35 {
uint8_t rc_type:4;
uint8_t rc_nseg:4;
uint8_t rc_rsvd0;
uint16_t rc_timeout;
struct {
uint16_t rf_rsvd:1;
uint16_t rf_sld:1;
uint16_t rf_c2f:1;
uint16_t rf_fwn:1;
uint16_t rf_sqn:1;
uint16_t rf_sbs:1;
uint16_t rf_rw:1;
uint16_t rf_log:1;
uint16_t rf_cpu_sel:4;
uint16_t rf_set_divert:4;
} rc_routing_flags;
uint16_t rc_ld_tgtid;
uint64_t rc_reg_lock_rowlba;
uint32_t rc_reg_lock_len;
union {
uint16_t rc_next_lmid;
uint16_t rc_peer_smid;
} rc_smid;
uint8_t rc_exstatus;
uint8_t rc_status;
struct {
uint8_t rf_pref_cpu:1;
uint8_t rf_rsvd1:3;
uint8_t rf_io_subtype:3;
uint8_t rf_rsvd2:1;
} rc_raid_flags;
uint8_t rc_span_arm;
uint16_t rc_cfg_seqnum;
struct {
uint16_t rc_num_sge:12;
uint16_t rc_rsvd1:3;
uint16_t rc_stream_detected:1;
};
uint8_t rc_rsvd2[2];
};
CTASSERT(sizeof (lmrc_raidctx_g35_t) == 0x20);
#define LMRC_RF_IO_SUBTYPE_NONE 0
#define LMRC_RF_IO_SUBTYPE_SYSTEM_PD 1
#define LMRC_RF_IO_SUBTYPE_RMW_DATA 2
#define LMRC_RF_IO_SUBTYPE_RMW_P 3
#define LMRC_RF_IO_SUBTYPE_RMW_Q 4
#define LMRC_RF_IO_SUBTYPE_CACHE_BYPASS 6
#define LMRC_RF_IO_SUBTYPE_LDIO_BW_LIMIT 7
#define LMRC_MIN_MAP_SIZE 0x10000
#define LMRC_MAX_SPAN_DEPTH 8
#define LMRC_MAX_QUAD_DEPTH LMRC_SPAN_DEPTH
#define LMRC_MAX_ROW_SIZE 32
#define LMRC_MAX_LOGICAL_DRIVES_EXT 256
#define LMRC_MAX_LOGICAL_DRIVES_DYN 512
#define LMRC_MAX_ARRAYS 128
#define LMRC_MAX_ARRAYS_EXT 256
#define LMRC_MAX_API_ARRAYS_EXT (LMRC_MAX_ARRAYS_EXT)
#define LMRC_MAX_API_ARRAYS_DYN 512
#define LMRC_RAIDMAP_MAX_SPAN_DEPTH (LMRC_MAX_SPAN_DEPTH)
#define LMRC_RAIDMAP_MAX_ROW_SIZE (LMRC_MAX_ROW_SIZE)
#define LMRC_RAIDMAP_ARRAYS (LMRC_MAX_ARRAYS)
#define LMRC_RAIDMAP_MAX_PHYS_DEV_DYN 512
#define LMRC_DEVHDL_IFTYPE_UNKNOWN 0
#define LMRC_DEVHDL_IFTYPE_PARALLEL_SCSI 1
#define LMRC_DEVHDL_IFTYPE_SAS_PD 2
#define LMRC_DEVHDL_IFTYPE_SATA_PD 3
#define LMRC_DEVHDL_IFTYPE_FC_PD 4
#define LMRC_DEVHDL_IFTYPE_NVME_PD 5
#define LMRC_DEVHDL_INVALID 0xFFFF
struct lmrc_devhdl_info {
uint16_t di_cur_devhdl;
uint8_t di_valid_handles;
uint8_t di_iftype;
uint16_t di_devhdl[2];
};
struct lmrc_array_info {
uint16_t ai_pd[LMRC_RAIDMAP_MAX_ROW_SIZE];
};
struct lmrc_quad_element {
uint64_t qe_logstart;
uint64_t qe_logend;
uint64_t qe_offset_in_span;
uint32_t qe_diff;
uint32_t qe_reserved;
};
struct lmrc_span_info {
uint32_t si_nelem;
uint32_t si_reserved;
lmrc_quad_element_t si_quad[LMRC_RAIDMAP_MAX_SPAN_DEPTH];
};
struct lmrc_ld_span {
uint64_t ls_start_blk;
uint64_t ls_nblk;
uint16_t ls_arrayref;
uint8_t ls_span_rowsz;
uint8_t ls_span_row_datasz;
uint8_t ls_reserved[4];
};
struct lmrc_span_block_info {
uint64_t sbi_num_rows;
lmrc_ld_span_t sbi_span;
lmrc_span_info_t sbi_block_span_info;
};
struct lmrc_ld_raid {
struct {
uint32_t lc_fp_cap:1;
uint32_t lc_ra_cap:1;
uint32_t lc_reserved5:2;
uint32_t lc_ld_pi_mode:4;
uint32_t lc_pd_pi_mode:4;
uint32_t lc_encryption_type:8;
uint32_t lc_fp_write_cap:1;
uint32_t lc_fp_read_cap:1;
uint32_t lc_fp_write_across_stripe:1;
uint32_t lc_fp_read_across_stripe:1;
uint32_t lc_fp_non_rw_cap:1;
uint32_t lc_tm_cap:1;
uint32_t lc_fp_cache_bypass_cap:1;
uint32_t lc_reserved4:5;
} lr_cap;
uint32_t lr_reserved6;
uint64_t lr_size;
uint8_t lr_span_depth;
uint8_t lr_level;
uint8_t lr_stripe_shift;
uint8_t lr_row_size;
uint8_t lr_row_data_size;
uint8_t lr_write_mode;
uint8_t lr_prl;
uint8_t lr_srl;
uint16_t lr_target_id;
uint8_t lr_ld_state;
uint8_t lr_reg_type_req_on_write;
uint8_t lr_mod_factor;
uint8_t lr_reg_type_req_on_read;
uint16_t lr_seq_num;
struct {
uint32_t lf_reserved:30;
uint32_t lf_reg_type_req_on_read_ls_valid:1;
uint32_t lf_ld_sync_required:1;
} lr_flags;
uint8_t lr_lun[8];
uint8_t lr_fp_io_timeout_for_ld;
uint8_t lr_reserved2[3];
uint32_t lr_logical_block_length;
struct {
uint32_t le_reserved1:24;
uint32_t le_ld_logical_block_exp:4;
uint32_t le_ld_pi_exp:4;
} lr_exponent;
uint8_t lr_reserved3[0x80 - 0x38];
};
struct lmrc_ld_span_map {
lmrc_ld_raid_t sm_ld_raid;
uint8_t sm_data_arm_map[LMRC_RAIDMAP_MAX_ROW_SIZE];
lmrc_span_block_info_t sm_span_block[LMRC_RAIDMAP_MAX_SPAN_DEPTH];
};
struct lmrc_raid_map_desc {
uint32_t rmd_type;
uint32_t rmd_off;
uint32_t rmd_bufsz;
uint32_t rmd_desc_nelem;
};
#define LMRC_RAID_MAP_DESC_TYPE_DEVHDL 0
#define LMRC_RAID_MAP_DESC_TYPE_LD_ID 1
#define LMRC_RAID_MAP_DESC_TYPE_ARRAY 2
#define LMRC_RAID_MAP_DESC_TYPE_SPAN 3
#define LMRC_RAID_MAP_DESC_TYPES_COUNT (LMRC_RAID_MAP_DESC_TYPE_SPAN + 1)
struct lmrc_fw_raid_map {
uint32_t rm_raidmap_sz;
uint32_t rm_desc_table_off;
uint32_t rm_desc_table_sz;
uint32_t rm_desc_table_nelem;
uint64_t rm_pci_thres_bandw;
uint32_t rm_rsvd[3];
uint8_t rm_fp_pd_io_timeout;
uint8_t rm_rsvd2[3];
uint32_t rm_rmw_fp_seqnum;
uint16_t rm_ld_count;
uint16_t rm_ar_count;
uint16_t rm_span_count;
uint16_t rm_rsvd3[3];
union {
struct {
lmrc_devhdl_info_t *rm_devhdl;
uint16_t *rm_ld_id;
lmrc_array_info_t *rm_array;
lmrc_ld_span_map_t *rm_span;
};
void *rm_desc_ptrs[LMRC_RAID_MAP_DESC_TYPES_COUNT];
};
lmrc_raid_map_desc_t rm_desc_table[LMRC_RAID_MAP_DESC_TYPES_COUNT];
uint32_t rm_desc_data[0];
};
#pragma pack(0)
static inline lmrc_ld_raid_t *
lmrc_ld_raid_get(uint16_t ld_id, lmrc_fw_raid_map_t *rm)
{
if (ld_id >= rm->rm_ld_count)
return (NULL);
return (&rm->rm_span[ld_id].sm_ld_raid);
}
static inline uint16_t
lmrc_ld_id_get(uint16_t tgtid, lmrc_fw_raid_map_t *rm)
{
ASSERT3U(tgtid, <,
rm->rm_desc_table[LMRC_RAID_MAP_DESC_TYPE_LD_ID].rmd_desc_nelem);
uint32_t nelem =
rm->rm_desc_table[LMRC_RAID_MAP_DESC_TYPE_LD_ID].rmd_desc_nelem;
if (tgtid >= nelem)
return (LMRC_DEVHDL_INVALID);
return (rm->rm_ld_id[tgtid]);
}
static inline uint16_t
lmrc_tgtid_get(uint16_t ld_id, lmrc_fw_raid_map_t *rm)
{
lmrc_ld_raid_t *raid;
if (ld_id >= rm->rm_ld_count)
return (LMRC_DEVHDL_INVALID);
raid = lmrc_ld_raid_get(ld_id, rm);
if (raid == NULL)
return (LMRC_DEVHDL_INVALID);
return (raid->lr_target_id);
}
static inline boolean_t
lmrc_cmd_is_rw(uint8_t cdb0)
{
switch (cdb0) {
case SCMD_READ:
case SCMD_WRITE:
case SCMD_READ_G1:
case SCMD_WRITE_G1:
case SCMD_READ_G4:
case SCMD_WRITE_G4:
case SCMD_READ_G5:
case SCMD_WRITE_G5:
return (B_TRUE);
default:
return (B_FALSE);
}
}
typedef lmrc_raidctx_g35_t MPI25_SCSI_IO_VENDOR_UNIQUE;
#define MPI25_SCSI_IO_VENDOR_UNIQUE_REGION
#include <sys/scsi/adapters/mpi/mpi2_init.h>
int lmrc_setup_raidmap(lmrc_t *);
void lmrc_free_raidmap(lmrc_t *);
boolean_t lmrc_ld_tm_capable(lmrc_t *, uint16_t);
int lmrc_get_ld_list(lmrc_t *);
int lmrc_raid_attach(dev_info_t *);
int lmrc_raid_detach(dev_info_t *);
int lmrc_raid_aen_handler(lmrc_t *, mfi_evt_detail_t *);
#endif