1*8226594fSRick McNeal /* 2*8226594fSRick McNeal * This file and its contents are supplied under the terms of the 3*8226594fSRick McNeal * Common Development and Distribution License ("CDDL"), version 1.0. 4*8226594fSRick McNeal * You may only use this file in accordance with the terms of version 5*8226594fSRick McNeal * 1.0 of the CDDL. 6*8226594fSRick McNeal * 7*8226594fSRick McNeal * A full copy of the text of the CDDL should have accompanied this 8*8226594fSRick McNeal * source. A copy of the CDDL is also available via the Internet at 9*8226594fSRick McNeal * http://www.illumos.org/license/CDDL. 10*8226594fSRick McNeal */ 11*8226594fSRick McNeal 12*8226594fSRick McNeal /* 13*8226594fSRick McNeal * Copyright 2023 Tintri by DDN, Inc. All rights reserved. 14*8226594fSRick McNeal * Copyright 2021 RackTop Systems, Inc. 15*8226594fSRick McNeal */ 16*8226594fSRick McNeal 17*8226594fSRick McNeal #ifndef _SMARTPQI_H 18*8226594fSRick McNeal #define _SMARTPQI_H 19*8226594fSRick McNeal 20*8226594fSRick McNeal #ifdef __cplusplus 21*8226594fSRick McNeal extern "C" { 22*8226594fSRick McNeal #endif 23*8226594fSRick McNeal 24*8226594fSRick McNeal /* ---- Standard header files. ---- */ 25*8226594fSRick McNeal #include <sys/note.h> 26*8226594fSRick McNeal #include <sys/byteorder.h> 27*8226594fSRick McNeal #include <sys/scsi/scsi.h> 28*8226594fSRick McNeal #include <sys/pci.h> 29*8226594fSRick McNeal #include <sys/file.h> 30*8226594fSRick McNeal #include <sys/policy.h> 31*8226594fSRick McNeal #include <sys/model.h> 32*8226594fSRick McNeal #include <sys/sysevent.h> 33*8226594fSRick McNeal #include <sys/sysevent/eventdefs.h> 34*8226594fSRick McNeal #include <sys/sysevent/dr.h> 35*8226594fSRick McNeal #include <sys/sata/sata_defs.h> 36*8226594fSRick McNeal #include <sys/sata/sata_hba.h> 37*8226594fSRick McNeal #include <sys/scsi/generic/sas.h> 38*8226594fSRick McNeal #include <sys/scsi/impl/scsi_sas.h> 39*8226594fSRick McNeal #include <sys/scsi/impl/scsi_reset_notify.h> 40*8226594fSRick McNeal #include <sys/sdt.h> 41*8226594fSRick McNeal #include <sys/mdi_impldefs.h> 42*8226594fSRick McNeal #include <sys/fs/dv_node.h> 43*8226594fSRick McNeal #include <sys/sysmacros.h> 44*8226594fSRick McNeal #include <sys/systm.h> 45*8226594fSRick McNeal #include <smartpqi_hw.h> 46*8226594fSRick McNeal 47*8226594fSRick McNeal /* ---- Hint for ddi_soft_state_init() on amount of structs to alloc ---- */ 48*8226594fSRick McNeal #define SMARTPQI_INITIAL_SOFT_SPACE 1 49*8226594fSRick McNeal 50*8226594fSRick McNeal #define SMARTPQI_MOD_STRING "smartpqi RT-20210716" 51*8226594fSRick McNeal 52*8226594fSRick McNeal /* ---- Handy constants ---- */ 53*8226594fSRick McNeal #define UNDEFINED -1 54*8226594fSRick McNeal #define MAX_NAME_PROP_SIZE 256 55*8226594fSRick McNeal #define LUN_PROP "lun" 56*8226594fSRick McNeal #define LUN64_PROP "lun64" 57*8226594fSRick McNeal #define MDI_GUID "wwn" 58*8226594fSRick McNeal #define NDI_GUID "guid" 59*8226594fSRick McNeal #define TARGET_PROP "target" 60*8226594fSRick McNeal #define LUN_PROP "lun" 61*8226594fSRick McNeal #define COMPAT_PROP "compatible" 62*8226594fSRick McNeal #define NAME_DISK "disk" 63*8226594fSRick McNeal #define NAME_ENCLOSURE "enclosure" 64*8226594fSRick McNeal 65*8226594fSRick McNeal #define CMD_TIMEOUT_SCAN_SECS 10 66*8226594fSRick McNeal #define SYNC_CMDS_TIMEOUT_SECS 5 67*8226594fSRick McNeal #define IO_SPACE 1 68*8226594fSRick McNeal #define PQI_MAXTGTS 256 69*8226594fSRick McNeal 70*8226594fSRick McNeal #define PQI_MIN_MSIX_VECTORS 1 71*8226594fSRick McNeal #define PQI_MAX_MSIX_VECTORS 16 72*8226594fSRick McNeal #define PQI_DEFAULT_QUEUE_GROUP 0 73*8226594fSRick McNeal #define PQI_MAX_QUEUE_GROUPS PQI_MAX_MSIX_VECTORS 74*8226594fSRick McNeal #define PQI_MIN_OPERATIONAL_QUEUE_ID 1 75*8226594fSRick McNeal #define PQI_NGENS 16 76*8226594fSRick McNeal #define PQI_MAX_IO_SLOTS (1 << 12) 77*8226594fSRick McNeal #define PQI_SLOT_INDEX_MASK 0xfff 78*8226594fSRick McNeal #define PQI_GENSHIFT 12 79*8226594fSRick McNeal /* 80*8226594fSRick McNeal * Generate and extract fields from a 16 bit io request id. 81*8226594fSRick McNeal * We generate a request id by combining a 12 bit slot index with a 82*8226594fSRick McNeal * 4 bit generation count. 83*8226594fSRick McNeal */ 84*8226594fSRick McNeal #define PQI_MAKE_REQID(index, gen) (((gen) << PQI_GENSHIFT) | (index)) 85*8226594fSRick McNeal #define PQI_REQID_GEN(id) ((id) >> PQI_GENSHIFT) 86*8226594fSRick McNeal #define PQI_REQID_INDEX(id) ((id) & PQI_SLOT_INDEX_MASK) 87*8226594fSRick McNeal 88*8226594fSRick McNeal /* ---- Size of structure scsi_arq_status without sense data. ---- */ 89*8226594fSRick McNeal #define PQI_ARQ_STATUS_NOSENSE_LEN (sizeof (struct scsi_arq_status) - \ 90*8226594fSRick McNeal sizeof (struct scsi_extended_sense)) 91*8226594fSRick McNeal 92*8226594fSRick McNeal /* ---- macros to return various addresses ---- */ 93*8226594fSRick McNeal #define ADDR2TRAN(ap) ((ap)->a_hba_tran) 94*8226594fSRick McNeal #define TRAN2PQI(hba) ((pqi_state_t *)(hba)->tran_hba_private) 95*8226594fSRick McNeal #define ADDR2PQI(ap) (TRAN2PQI(ADDR2TRAN(ap))) 96*8226594fSRick McNeal #define PKT2CMD(pkt) ((pqi_cmd_t *)(pkt)->pkt_ha_private) 97*8226594fSRick McNeal #define CMD2PKT(cmd) ((struct scsi_pkt *)(cmd)->pc_pkt) 98*8226594fSRick McNeal 99*8226594fSRick McNeal /* ---- PQI configuration ---- */ 100*8226594fSRick McNeal #define PQI_MAX_OUTSTANDING_REQUESTS 32 101*8226594fSRick McNeal #define PQI_ERROR_BUFFER_ELEMENT_LENGTH sizeof (struct pqi_raid_error_info) 102*8226594fSRick McNeal #define PQI_CREATE_ADMIN_QUEUE_PAIR 1 103*8226594fSRick McNeal #define PQI_DELETE_ADMIN_QUEUE_PAIR 2 104*8226594fSRick McNeal #define PQI_MAX_TRANSFER_SIZE (4 * 1024U * 1024U) 105*8226594fSRick McNeal #define PQI_MAX_RESET_XFER_SIZE (512 * 1024) 106*8226594fSRick McNeal #define PQI_NUM_SUPPORTED_EVENTS 7 107*8226594fSRick McNeal #define PQI_RESERVED_IO_SLOTS_LUN_RESET 1 108*8226594fSRick McNeal #define PQI_RESERVED_IO_SLOTS_EVENT_ACK PQI_NUM_SUPPORTED_EVENTS 109*8226594fSRick McNeal #define PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS 3 110*8226594fSRick McNeal #define PQI_RESERVED_IO_SLOTS \ 111*8226594fSRick McNeal (PQI_RESERVED_IO_SLOTS_LUN_RESET + PQI_RESERVED_IO_SLOTS_EVENT_ACK + \ 112*8226594fSRick McNeal PQI_RESERVED_IO_SLOTS_SYNCHRONOUS_REQUESTS) 113*8226594fSRick McNeal #define PQI_MAX_SCATTER_GATHER 0x200 114*8226594fSRick McNeal 115*8226594fSRick McNeal /* ---- SIS constants ---- */ 116*8226594fSRick McNeal #define SIS_BASE_STRUCT_ALIGNMENT 16 117*8226594fSRick McNeal 118*8226594fSRick McNeal /* ---- Once every 10 seconds ---- */ 119*8226594fSRick McNeal #define WATCHDOG (10 * MICROSEC) 120*8226594fSRick McNeal 121*8226594fSRick McNeal /* ---- Update HBA time of day clock once a day ---- */ 122*8226594fSRick McNeal #define MINUTE 60 123*8226594fSRick McNeal #define HOUR (60 * MINUTE) 124*8226594fSRick McNeal #define DAY (24 * HOUR) 125*8226594fSRick McNeal 126*8226594fSRick McNeal #define HBA_IS_QUIESCED(s) (((s)->s_flags & PQI_HBA_QUIESCED) != 0) 127*8226594fSRick McNeal #define HBA_QUIESCED_PENDING(s) \ 128*8226594fSRick McNeal (((s)->s_flags & PQI_HBA_QUIESCED_PENDING) != 0 && \ 129*8226594fSRick McNeal ((s)->s_cmd_queue_len == 0)) 130*8226594fSRick McNeal 131*8226594fSRick McNeal /* 132*8226594fSRick McNeal * The PQIALIGN_TYPED() does round up to produce aligned value, 133*8226594fSRick McNeal * and is built to support pointers. 134*8226594fSRick McNeal * We could use P2ROUNDUP_TYPED from sysmacros.h, but unfortunately, 135*8226594fSRick McNeal * P2ROUNDUP_TYPED does not work with pointer types. 136*8226594fSRick McNeal */ 137*8226594fSRick McNeal #define PQIALIGN_TYPED(addr, align, type) \ 138*8226594fSRick McNeal (type)(((uintptr_t)(addr) + align - 1) & ~(align - 1)) 139*8226594fSRick McNeal 140*8226594fSRick McNeal /* ---- Handy macros to get/set device registers ---- */ 141*8226594fSRick McNeal #define G8(state, __reg__) \ 142*8226594fSRick McNeal ddi_get8(state->s_datap, &state->s_reg->__reg__) 143*8226594fSRick McNeal #define G16(state, __reg__) \ 144*8226594fSRick McNeal ddi_get16(state->s_datap, &state->s_reg->__reg__) 145*8226594fSRick McNeal #define G32(state, __reg__) \ 146*8226594fSRick McNeal ddi_get32(state->s_datap, &state->s_reg->__reg__) 147*8226594fSRick McNeal #define S8(state, __reg__, val) \ 148*8226594fSRick McNeal ddi_put8(state->s_datap, &state->s_reg->__reg__, val) 149*8226594fSRick McNeal #define S32(state, __reg__, val) \ 150*8226594fSRick McNeal ddi_put32(state->s_datap, &state->s_reg->__reg__, val) 151*8226594fSRick McNeal #define S64(state, __reg__, val) \ 152*8226594fSRick McNeal ddi_put64(state->s_datap, &state->s_reg->__reg__, val) 153*8226594fSRick McNeal #define G64(state, __reg__) \ 154*8226594fSRick McNeal ddi_get64(state->s_datap, &state->s_reg->__reg__) 155*8226594fSRick McNeal 156*8226594fSRick McNeal /* 157*8226594fSRick McNeal * Yuck! Internal knowledge of MPxIO, but since this variable is required 158*8226594fSRick McNeal * to use MPxIO and there's no public API it must be declared here. Both 159*8226594fSRick McNeal * the iSCSI Initiator and MPT SAS drivers do the same thing. 160*8226594fSRick McNeal */ 161*8226594fSRick McNeal extern dev_info_t *scsi_vhci_dip; 162*8226594fSRick McNeal 163*8226594fSRick McNeal typedef enum pqi_io_path { 164*8226594fSRick McNeal RAID_PATH = 0, 165*8226594fSRick McNeal AIO_PATH = 1 166*8226594fSRick McNeal } pqi_path_t; 167*8226594fSRick McNeal 168*8226594fSRick McNeal typedef struct dma_overhead { 169*8226594fSRick McNeal ddi_dma_handle_t handle; 170*8226594fSRick McNeal ddi_acc_handle_t acc; 171*8226594fSRick McNeal caddr_t alloc_memory; 172*8226594fSRick McNeal size_t len_to_alloc; 173*8226594fSRick McNeal size_t allocated_len; 174*8226594fSRick McNeal uint64_t dma_addr; 175*8226594fSRick McNeal uint_t cookie_count; 176*8226594fSRick McNeal ddi_dma_cookie_t second; 177*8226594fSRick McNeal } pqi_dma_overhead_t; 178*8226594fSRick McNeal 179*8226594fSRick McNeal typedef struct pqi_admin_queues { 180*8226594fSRick McNeal caddr_t iq_element_array; 181*8226594fSRick McNeal caddr_t oq_element_array; 182*8226594fSRick McNeal volatile pqi_index_t *iq_ci; 183*8226594fSRick McNeal pqi_index_t *oq_pi; 184*8226594fSRick McNeal uint64_t iq_element_array_bus_addr; 185*8226594fSRick McNeal uint64_t oq_element_array_bus_addr; 186*8226594fSRick McNeal uint64_t iq_ci_bus_addr; 187*8226594fSRick McNeal uint64_t oq_pi_bus_addr; 188*8226594fSRick McNeal uint32_t *iq_pi; 189*8226594fSRick McNeal pqi_index_t iq_pi_copy; 190*8226594fSRick McNeal uint32_t *oq_ci; 191*8226594fSRick McNeal pqi_index_t oq_ci_copy; 192*8226594fSRick McNeal struct task_struct *task; 193*8226594fSRick McNeal uint16_t int_msg_num; 194*8226594fSRick McNeal } pqi_admin_queues_t; 195*8226594fSRick McNeal 196*8226594fSRick McNeal typedef struct pqi_event_queue { 197*8226594fSRick McNeal uint16_t oq_id; 198*8226594fSRick McNeal uint16_t int_msg_num; 199*8226594fSRick McNeal void *oq_element_array; 200*8226594fSRick McNeal pqi_index_t *oq_pi; /* In s_queue_dma space */ 201*8226594fSRick McNeal uint64_t oq_element_array_bus_addr; 202*8226594fSRick McNeal uint64_t oq_pi_bus_addr; 203*8226594fSRick McNeal uint32_t *oq_ci; /* In s_reg space */ 204*8226594fSRick McNeal pqi_index_t oq_ci_copy; 205*8226594fSRick McNeal } pqi_event_queue_t; 206*8226594fSRick McNeal 207*8226594fSRick McNeal typedef struct pqi_queue_group { 208*8226594fSRick McNeal struct pqi_state *qg_softc; /* backpointer */ 209*8226594fSRick McNeal uint16_t iq_id[2]; 210*8226594fSRick McNeal uint16_t oq_id; 211*8226594fSRick McNeal uint16_t int_msg_num; 212*8226594fSRick McNeal caddr_t iq_element_array[2]; 213*8226594fSRick McNeal caddr_t oq_element_array; 214*8226594fSRick McNeal uint64_t iq_element_array_bus_addr[2]; 215*8226594fSRick McNeal uint64_t oq_element_array_bus_addr; 216*8226594fSRick McNeal pqi_index_t iq_pi_copy[2]; 217*8226594fSRick McNeal pqi_index_t oq_ci_copy; 218*8226594fSRick McNeal /* ---- In s_reg space ---- */ 219*8226594fSRick McNeal uint32_t *iq_pi[2]; 220*8226594fSRick McNeal uint32_t *oq_ci; 221*8226594fSRick McNeal 222*8226594fSRick McNeal /* ---- In s_queue_dma space ---- */ 223*8226594fSRick McNeal pqi_index_t *iq_ci[2]; 224*8226594fSRick McNeal pqi_index_t *oq_pi; 225*8226594fSRick McNeal 226*8226594fSRick McNeal uint64_t iq_ci_bus_addr[2]; 227*8226594fSRick McNeal uint64_t oq_pi_bus_addr; 228*8226594fSRick McNeal 229*8226594fSRick McNeal kmutex_t submit_lock[2]; /* protect submission queue */ 230*8226594fSRick McNeal list_t request_list[2]; 231*8226594fSRick McNeal int submit_count; 232*8226594fSRick McNeal int cmplt_count; 233*8226594fSRick McNeal boolean_t qg_active; 234*8226594fSRick McNeal } pqi_queue_group_t; 235*8226594fSRick McNeal 236*8226594fSRick McNeal typedef struct pqi_io_request { 237*8226594fSRick McNeal kmutex_t io_lock; /* protect generation/serviced flag */ 238*8226594fSRick McNeal uint32_t io_refcount; 239*8226594fSRick McNeal uint16_t io_index; 240*8226594fSRick McNeal void (*io_cb)(struct pqi_io_request *, void *); 241*8226594fSRick McNeal void *io_context; 242*8226594fSRick McNeal uint8_t io_raid_bypass : 1; 243*8226594fSRick McNeal uint8_t io_gen; 244*8226594fSRick McNeal boolean_t io_serviced; 245*8226594fSRick McNeal int io_status; 246*8226594fSRick McNeal pqi_queue_group_t *io_queue_group; 247*8226594fSRick McNeal int io_queue_path; 248*8226594fSRick McNeal struct pqi_cmd *io_cmd; 249*8226594fSRick McNeal void *io_error_info; 250*8226594fSRick McNeal pqi_dma_overhead_t *io_sg_chain_dma; 251*8226594fSRick McNeal void *io_iu; 252*8226594fSRick McNeal list_node_t io_list_node; 253*8226594fSRick McNeal 254*8226594fSRick McNeal /* ---- Debug aids ---- */ 255*8226594fSRick McNeal pqi_index_t io_pi; 256*8226594fSRick McNeal int io_iu_type; 257*8226594fSRick McNeal 258*8226594fSRick McNeal struct pqi_state *io_softc; 259*8226594fSRick McNeal } pqi_io_request_t; 260*8226594fSRick McNeal 261*8226594fSRick McNeal typedef struct pqi_event { 262*8226594fSRick McNeal boolean_t ev_pending; 263*8226594fSRick McNeal uint8_t ev_type; 264*8226594fSRick McNeal uint16_t ev_id; 265*8226594fSRick McNeal uint32_t ev_additional; 266*8226594fSRick McNeal } pqi_event_t; 267*8226594fSRick McNeal 268*8226594fSRick McNeal /* ---- Flags used in pqi_state ---- */ 269*8226594fSRick McNeal #define PQI_HBA_DRIVER_SHUTDOWN 0x0001 270*8226594fSRick McNeal #define PQI_HBA_QUIESCED 0x0002 271*8226594fSRick McNeal #define PQI_HBA_QUIESCED_PENDING 0x0004 272*8226594fSRick McNeal #define PQI_HBA_AUTO_REQUEST_SENSE 0x0008 273*8226594fSRick McNeal #define PQI_HBA_LUN_RESET_CAP 0x0010 274*8226594fSRick McNeal 275*8226594fSRick McNeal /* ---- Debug flags, example debug=0x10; in .conf file ---- */ 276*8226594fSRick McNeal #define DBG_LVL_CDB 0x0001 277*8226594fSRick McNeal #define DBG_LVL_RQST 0x0002 278*8226594fSRick McNeal #define DBG_LVL_STATE 0x0004 279*8226594fSRick McNeal #define DBG_LVL_RAW_RQST 0x0008 280*8226594fSRick McNeal 281*8226594fSRick McNeal typedef struct pqi_device { 282*8226594fSRick McNeal list_node_t pd_list; 283*8226594fSRick McNeal kmutex_t pd_mutex; 284*8226594fSRick McNeal 285*8226594fSRick McNeal /* ---- Protected by pd_mutex ---- */ 286*8226594fSRick McNeal list_t pd_cmd_list; 287*8226594fSRick McNeal int pd_flags; 288*8226594fSRick McNeal 289*8226594fSRick McNeal int pd_active_cmds; 290*8226594fSRick McNeal int pd_target; 291*8226594fSRick McNeal int pd_lun; 292*8226594fSRick McNeal 293*8226594fSRick McNeal /* ---- Only one will be valid, MPxIO uses s_pip ---- */ 294*8226594fSRick McNeal dev_info_t *pd_dip; 295*8226594fSRick McNeal mdi_pathinfo_t *pd_pip; 296*8226594fSRick McNeal mdi_pathinfo_t *pd_pip_offlined; 297*8226594fSRick McNeal 298*8226594fSRick McNeal dev_info_t *pd_parent; 299*8226594fSRick McNeal int pd_devtype; 300*8226594fSRick McNeal int pd_online : 1; 301*8226594fSRick McNeal int pd_scanned : 1; 302*8226594fSRick McNeal int pd_phys_dev : 1; 303*8226594fSRick McNeal int pd_external_raid : 1; 304*8226594fSRick McNeal int pd_aio_enabled : 1; 305*8226594fSRick McNeal uint32_t pd_aio_handle; 306*8226594fSRick McNeal char pd_scsi3addr[8]; 307*8226594fSRick McNeal uint64_t pd_wwid; 308*8226594fSRick McNeal char *pd_guid; 309*8226594fSRick McNeal uint8_t pd_volume_id[16]; 310*8226594fSRick McNeal char pd_vendor[8]; /* From INQUIRY */ 311*8226594fSRick McNeal char pd_model[16]; /* From INQUIRY */ 312*8226594fSRick McNeal char pd_unit_address[32]; 313*8226594fSRick McNeal 314*8226594fSRick McNeal /* ---- Debug stats ---- */ 315*8226594fSRick McNeal uint32_t pd_killed; 316*8226594fSRick McNeal uint32_t pd_posted; 317*8226594fSRick McNeal uint32_t pd_timedout; 318*8226594fSRick McNeal uint32_t pd_sense_errors; 319*8226594fSRick McNeal } pqi_device_t; 320*8226594fSRick McNeal 321*8226594fSRick McNeal typedef struct pqi_state { 322*8226594fSRick McNeal int s_instance; 323*8226594fSRick McNeal dev_info_t *s_dip; 324*8226594fSRick McNeal int s_flags; 325*8226594fSRick McNeal kmutex_t s_mutex; 326*8226594fSRick McNeal kmutex_t s_intr_mutex; 327*8226594fSRick McNeal kcondvar_t s_quiescedvar; 328*8226594fSRick McNeal uint32_t s_next_target; 329*8226594fSRick McNeal 330*8226594fSRick McNeal /* ---- Used for serialized commands through driver ---- */ 331*8226594fSRick McNeal struct pqi_device s_special_device; 332*8226594fSRick McNeal 333*8226594fSRick McNeal boolean_t s_intr_ready; 334*8226594fSRick McNeal boolean_t s_offline; 335*8226594fSRick McNeal boolean_t s_disable_mpxio; 336*8226594fSRick McNeal kmem_cache_t *s_cmd_cache; 337*8226594fSRick McNeal ddi_taskq_t *s_events_taskq; 338*8226594fSRick McNeal ddi_taskq_t *s_complete_taskq; 339*8226594fSRick McNeal timeout_id_t s_time_of_day; 340*8226594fSRick McNeal timeout_id_t s_cmd_timeout; 341*8226594fSRick McNeal 342*8226594fSRick McNeal /* ---- Debug related state ---- */ 343*8226594fSRick McNeal int s_debug_level; 344*8226594fSRick McNeal 345*8226594fSRick McNeal /* ---- State for watchdog ---- */ 346*8226594fSRick McNeal timeout_id_t s_watchdog; 347*8226594fSRick McNeal uint32_t s_last_intr_count; 348*8226594fSRick McNeal uint32_t s_last_heartbeat_count; 349*8226594fSRick McNeal uint32_t s_intr_count; 350*8226594fSRick McNeal 351*8226594fSRick McNeal /* ---- Interrupt related fields ---- */ 352*8226594fSRick McNeal int s_intr_type; /* Type of interrupt used */ 353*8226594fSRick McNeal int s_intr_cnt; /* # of interrupts */ 354*8226594fSRick McNeal uint_t s_intr_pri; /* Interrupt priority */ 355*8226594fSRick McNeal int s_intr_cap; /* Interrupt capabilities */ 356*8226594fSRick McNeal int s_intr_size; /* Size of s_htable */ 357*8226594fSRick McNeal ddi_intr_handle_t *s_itable; /* Interrupt table */ 358*8226594fSRick McNeal 359*8226594fSRick McNeal scsi_hba_tran_t *s_tran; 360*8226594fSRick McNeal ddi_dma_attr_t s_msg_dma_attr; /* Used for message frames */ 361*8226594fSRick McNeal 362*8226594fSRick McNeal /* ---- list of reset notification requests ---- */ 363*8226594fSRick McNeal struct scsi_reset_notify_entry *s_reset_notify_listf; 364*8226594fSRick McNeal 365*8226594fSRick McNeal pqi_ctrl_regs_t *s_reg; 366*8226594fSRick McNeal ddi_device_acc_attr_t s_reg_acc_attr; 367*8226594fSRick McNeal /* ---- operating regs data access handle ---- */ 368*8226594fSRick McNeal ddi_acc_handle_t s_datap; 369*8226594fSRick McNeal 370*8226594fSRick McNeal list_t s_devnodes; 371*8226594fSRick McNeal volatile uint32_t s_cmd_queue_len; 372*8226594fSRick McNeal 373*8226594fSRick McNeal /* ---- SIS capabilities from controller ---- */ 374*8226594fSRick McNeal uint32_t s_max_sg_entries; 375*8226594fSRick McNeal uint32_t s_max_xfer_size; 376*8226594fSRick McNeal uint32_t s_max_outstanding_requests; 377*8226594fSRick McNeal uint32_t s_config_table_offset; 378*8226594fSRick McNeal uint32_t s_config_table_len; 379*8226594fSRick McNeal 380*8226594fSRick McNeal /* ---- PQI capabilities from controller ---- */ 381*8226594fSRick McNeal uint32_t *s_heartbeat_counter; 382*8226594fSRick McNeal uint16_t s_max_inbound_queues; 383*8226594fSRick McNeal uint16_t s_max_elements_per_iq; 384*8226594fSRick McNeal uint16_t s_max_iq_element_length; 385*8226594fSRick McNeal uint16_t s_max_outbound_queues; 386*8226594fSRick McNeal uint16_t s_max_elements_per_oq; 387*8226594fSRick McNeal uint16_t s_max_oq_element_length; 388*8226594fSRick McNeal uint16_t s_max_inbound_iu_length_per_firmware; 389*8226594fSRick McNeal uint8_t s_inbound_spanning_supported : 1, 390*8226594fSRick McNeal s_outbound_spanning_supported:1, 391*8226594fSRick McNeal s_pqi_mode_enabled : 1; 392*8226594fSRick McNeal char s_firmware_version[11]; 393*8226594fSRick McNeal 394*8226594fSRick McNeal /* ---- Computed values from config ---- */ 395*8226594fSRick McNeal uint32_t s_max_sg_per_iu; 396*8226594fSRick McNeal uint32_t s_num_elements_per_iq; 397*8226594fSRick McNeal uint32_t s_num_elements_per_oq; 398*8226594fSRick McNeal uint32_t s_max_inbound_iu_length; 399*8226594fSRick McNeal uint32_t s_num_queue_groups; 400*8226594fSRick McNeal uint32_t s_max_io_slots; 401*8226594fSRick McNeal uint32_t s_sg_chain_buf_length; 402*8226594fSRick McNeal uint32_t s_max_sectors; 403*8226594fSRick McNeal 404*8226594fSRick McNeal /* ---- allocation/free is protected by s_io_mutex ---- */ 405*8226594fSRick McNeal kmutex_t s_io_mutex; 406*8226594fSRick McNeal kcondvar_t s_io_condvar; 407*8226594fSRick McNeal pqi_io_request_t *s_io_rqst_pool; 408*8226594fSRick McNeal int s_io_wait_cnt; 409*8226594fSRick McNeal int s_next_io_slot; 410*8226594fSRick McNeal uint32_t s_io_need; 411*8226594fSRick McNeal uint32_t s_io_had2wait; 412*8226594fSRick McNeal uint32_t s_io_sig; 413*8226594fSRick McNeal 414*8226594fSRick McNeal pqi_dma_overhead_t *s_error_dma; 415*8226594fSRick McNeal pqi_dma_overhead_t *s_adminq_dma; 416*8226594fSRick McNeal pqi_admin_queues_t s_admin_queues; 417*8226594fSRick McNeal pqi_dma_overhead_t *s_queue_dma; 418*8226594fSRick McNeal pqi_queue_group_t s_queue_groups[PQI_MAX_QUEUE_GROUPS]; 419*8226594fSRick McNeal pqi_event_queue_t s_event_queue; 420*8226594fSRick McNeal struct pqi_event s_events[PQI_NUM_SUPPORTED_EVENTS]; 421*8226594fSRick McNeal } pqi_state_t; 422*8226594fSRick McNeal 423*8226594fSRick McNeal /* ---- Flags used in pqi_cmd_t ---- */ 424*8226594fSRick McNeal #define PQI_FLAG_ABORTED 0x0001 425*8226594fSRick McNeal #define PQI_FLAG_TIMED_OUT 0x0002 426*8226594fSRick McNeal #define PQI_FLAG_RESET 0x0004 427*8226594fSRick McNeal #define PQI_FLAG_IO_IOPB 0x0040 428*8226594fSRick McNeal #define PQI_FLAG_DMA_VALID 0x0100 429*8226594fSRick McNeal #define PQI_FLAG_CDB_EXT 0x0200 430*8226594fSRick McNeal #define PQI_FLAG_SCB_EXT 0x0400 431*8226594fSRick McNeal #define PQI_FLAG_PRIV_EXT 0x0800 432*8226594fSRick McNeal #define PQI_FLAG_IO_READ 0x1000 433*8226594fSRick McNeal #define PQI_FLAG_IO_BOUNCE 0x2000 434*8226594fSRick McNeal #define PQI_FLAG_FINISHING 0x4000 435*8226594fSRick McNeal 436*8226594fSRick McNeal typedef enum pqi_cmd_action { 437*8226594fSRick McNeal PQI_CMD_UNINIT, 438*8226594fSRick McNeal PQI_CMD_QUEUE, 439*8226594fSRick McNeal PQI_CMD_START, 440*8226594fSRick McNeal PQI_CMD_CMPLT, 441*8226594fSRick McNeal PQI_CMD_TIMEOUT, 442*8226594fSRick McNeal PQI_CMD_FAIL 443*8226594fSRick McNeal } pqi_cmd_action_t; 444*8226594fSRick McNeal 445*8226594fSRick McNeal #define PQI_FLAGS_PERSISTENT \ 446*8226594fSRick McNeal (PQI_FLAG_DMA_VALID |\ 447*8226594fSRick McNeal PQI_FLAG_IO_IOPB) 448*8226594fSRick McNeal 449*8226594fSRick McNeal #define PQI_FLAGS_NON_HW_COMPLETION \ 450*8226594fSRick McNeal (PQI_FLAG_ABORTED |\ 451*8226594fSRick McNeal PQI_FLAG_TIMED_OUT |\ 452*8226594fSRick McNeal PQI_FLAG_RESET) 453*8226594fSRick McNeal 454*8226594fSRick McNeal typedef struct pqi_cmd { 455*8226594fSRick McNeal list_node_t pc_list; 456*8226594fSRick McNeal kmutex_t pc_mutex; // protects pc_cmd_state 457*8226594fSRick McNeal 458*8226594fSRick McNeal pqi_cmd_action_t pc_cur_action; 459*8226594fSRick McNeal pqi_cmd_action_t pc_last_action; 460*8226594fSRick McNeal 461*8226594fSRick McNeal struct scsi_pkt *pc_pkt; 462*8226594fSRick McNeal pqi_state_t *pc_softc; 463*8226594fSRick McNeal pqi_device_t *pc_device; 464*8226594fSRick McNeal ksema_t *pc_poll; 465*8226594fSRick McNeal uint8_t pc_cdb[SCSI_CDB_SIZE]; 466*8226594fSRick McNeal struct scsi_arq_status pc_cmd_scb; 467*8226594fSRick McNeal 468*8226594fSRick McNeal uint64_t pc_tgt_priv[2]; 469*8226594fSRick McNeal int pc_dma_count; /* bytes to transfer */ 470*8226594fSRick McNeal 471*8226594fSRick McNeal /* 472*8226594fSRick McNeal * Setting/clearing/testing of ABORT and FINISHING are 473*8226594fSRick McNeal * protected by pqi_device->pd_mutex. The other bits in 474*8226594fSRick McNeal * this flag are set during init_pkt and read only during 475*8226594fSRick McNeal * cleanup. 476*8226594fSRick McNeal */ 477*8226594fSRick McNeal int pc_flags; 478*8226594fSRick McNeal 479*8226594fSRick McNeal int pc_tgtlen; 480*8226594fSRick McNeal int pc_statuslen; 481*8226594fSRick McNeal int pc_cmdlen; 482*8226594fSRick McNeal hrtime_t pc_expiration; 483*8226594fSRick McNeal hrtime_t pc_start_time; 484*8226594fSRick McNeal 485*8226594fSRick McNeal /* ---- For partial DMA transfers ---- */ 486*8226594fSRick McNeal uint_t pc_nwin; 487*8226594fSRick McNeal uint_t pc_winidx; 488*8226594fSRick McNeal off_t pc_dma_offset; 489*8226594fSRick McNeal size_t pc_dma_len; 490*8226594fSRick McNeal 491*8226594fSRick McNeal /* ---- Valid after call to pqi_transport_command ---- */ 492*8226594fSRick McNeal pqi_io_request_t *pc_io_rqst; 493*8226594fSRick McNeal 494*8226594fSRick McNeal ddi_dma_handle_t pc_dmahdl; 495*8226594fSRick McNeal ddi_dma_cookie_t pc_dmac; 496*8226594fSRick McNeal uint_t pc_dmaccount; /* cookie count */ 497*8226594fSRick McNeal struct scsi_pkt pc_cached_pkt; 498*8226594fSRick McNeal ddi_dma_cookie_t pc_cached_cookies[PQI_MAX_SCATTER_GATHER]; 499*8226594fSRick McNeal } pqi_cmd_t; 500*8226594fSRick McNeal 501*8226594fSRick McNeal /* ---- configuration table section IDs ---- */ 502*8226594fSRick McNeal #define PQI_CONFIG_TABLE_SECTION_GENERAL_INFO 0 503*8226594fSRick McNeal #define PQI_CONFIG_TABLE_SECTION_FIRMWARE_FEATURES 1 504*8226594fSRick McNeal #define PQI_CONFIG_TABLE_SECTION_FIRMWARE_ERRATA 2 505*8226594fSRick McNeal #define PQI_CONFIG_TABLE_SECTION_DEBUG 3 506*8226594fSRick McNeal #define PQI_CONFIG_TABLE_SECTION_HEARTBEAT 4 507*8226594fSRick McNeal 508*8226594fSRick McNeal /* ---- manifest constants for the flags field of pqi_sg_descriptor ---- */ 509*8226594fSRick McNeal #define CISS_SG_NORMAL 0x00000000 510*8226594fSRick McNeal #define CISS_SG_LAST 0x40000000 511*8226594fSRick McNeal #define CISS_SG_CHAIN 0x80000000 512*8226594fSRick McNeal 513*8226594fSRick McNeal /* 514*8226594fSRick McNeal * According to the PQI spec, the IU header is only the first 4 bytes of our 515*8226594fSRick McNeal * pqi_iu_header structure. 516*8226594fSRick McNeal */ 517*8226594fSRick McNeal #define PQI_REQUEST_HEADER_LENGTH 4 518*8226594fSRick McNeal #define PQI_REQUEST_IU_TASK_MANAGEMENT 0x13 519*8226594fSRick McNeal #define PQI_REQUEST_IU_RAID_PATH_IO 0x14 520*8226594fSRick McNeal #define PQI_REQUEST_IU_AIO_PATH_IO 0x15 521*8226594fSRick McNeal #define PQI_REQUEST_IU_GENERAL_ADMIN 0x60 522*8226594fSRick McNeal #define PQI_REQUEST_IU_REPORT_VENDOR_EVENT_CONFIG 0x72 523*8226594fSRick McNeal #define PQI_REQUEST_IU_SET_VENDOR_EVENT_CONFIG 0x73 524*8226594fSRick McNeal #define PQI_REQUEST_IU_ACKNOWLEDGE_VENDOR_EVENT 0xf6 525*8226594fSRick McNeal 526*8226594fSRick McNeal #define MASKED_DEVICE(lunid) ((lunid)[3] & 0xc0) 527*8226594fSRick McNeal 528*8226594fSRick McNeal #define MEMP(args...) (void) snprintf(m.mem + strlen(m.mem), \ 529*8226594fSRick McNeal m.len - strlen(m.mem), args) 530*8226594fSRick McNeal 531*8226594fSRick McNeal typedef struct mem_len_pair { 532*8226594fSRick McNeal caddr_t mem; 533*8226594fSRick McNeal int len; 534*8226594fSRick McNeal } mem_len_pair_t; 535*8226594fSRick McNeal 536*8226594fSRick McNeal /* ---- Defines for PQI mode ---- */ 537*8226594fSRick McNeal #define IRQ_MODE_NONE 0x00 538*8226594fSRick McNeal #define VPD_PAGE (1 << 8) 539*8226594fSRick McNeal 540*8226594fSRick McNeal /* ---- Defines for use in Legacy mode ---- */ 541*8226594fSRick McNeal #define SIS_CTRL_KERNEL_UP 0x080 542*8226594fSRick McNeal #define SIS_CTRL_KERNEL_PANIC 0x100 543*8226594fSRick McNeal #define SIS_MODE 0x0 544*8226594fSRick McNeal #define PQI_MODE 0x1 545*8226594fSRick McNeal 546*8226594fSRick McNeal /* ---- smartpqi_main.c ---- */ 547*8226594fSRick McNeal extern void *pqi_state; 548*8226594fSRick McNeal extern int pqi_do_scan; 549*8226594fSRick McNeal extern int pqi_do_ctrl; 550*8226594fSRick McNeal 551*8226594fSRick McNeal /* ---- smartpqi_intr.c ---- */ 552*8226594fSRick McNeal int smartpqi_register_intrs(pqi_state_t *); 553*8226594fSRick McNeal void smartpqi_unregister_intrs(pqi_state_t *); 554*8226594fSRick McNeal void pqi_process_io_intr(pqi_state_t *s, pqi_queue_group_t *qg); 555*8226594fSRick McNeal 556*8226594fSRick McNeal /* ---- smartpqi_sis.c ---- */ 557*8226594fSRick McNeal boolean_t sis_reenable_mode(pqi_state_t *s); 558*8226594fSRick McNeal void sis_write_scratch(pqi_state_t *s, int mode); 559*8226594fSRick McNeal uint32_t sis_read_scratch(pqi_state_t *s); 560*8226594fSRick McNeal boolean_t sis_wait_for_ctrl_ready(pqi_state_t *s); 561*8226594fSRick McNeal boolean_t sis_get_ctrl_props(pqi_state_t *s); 562*8226594fSRick McNeal boolean_t sis_init_base_struct_addr(pqi_state_t *s); 563*8226594fSRick McNeal boolean_t sis_get_pqi_capabilities(pqi_state_t *s); 564*8226594fSRick McNeal 565*8226594fSRick McNeal /* ---- smartpqi_init.c ---- */ 566*8226594fSRick McNeal void pqi_free_io_resource(pqi_state_t *s); 567*8226594fSRick McNeal boolean_t pqi_scsi_inquiry(pqi_state_t *s, pqi_device_t *dev, int vpd, 568*8226594fSRick McNeal struct scsi_inquiry *inq, int len); 569*8226594fSRick McNeal void pqi_rescan_devices(pqi_state_t *s); 570*8226594fSRick McNeal boolean_t pqi_check_firmware(pqi_state_t *s); 571*8226594fSRick McNeal boolean_t pqi_prep_full(pqi_state_t *s); 572*8226594fSRick McNeal boolean_t pqi_reset_ctl(pqi_state_t *s); 573*8226594fSRick McNeal boolean_t pqi_hba_reset(pqi_state_t *s); 574*8226594fSRick McNeal 575*8226594fSRick McNeal /* ---- smartpqi_hba.c ---- */ 576*8226594fSRick McNeal boolean_t smartpqi_register_hba(pqi_state_t *); 577*8226594fSRick McNeal void smartpqi_unregister_hba(pqi_state_t *); 578*8226594fSRick McNeal pqi_device_t *pqi_find_target_ua(pqi_state_t *s, char *); 579*8226594fSRick McNeal int pqi_cache_constructor(void *buf, void *un, int flags); 580*8226594fSRick McNeal void pqi_cache_destructor(void *buf, void *un); 581*8226594fSRick McNeal int pqi_config_all(dev_info_t *pdip, pqi_state_t *s); 582*8226594fSRick McNeal void pqi_quiesced_notify(pqi_state_t *s); 583*8226594fSRick McNeal 584*8226594fSRick McNeal /* ---- smartpqi_hw.c ---- */ 585*8226594fSRick McNeal void pqi_start_io(pqi_state_t *s, pqi_queue_group_t *qg, pqi_path_t path, 586*8226594fSRick McNeal pqi_io_request_t *io); 587*8226594fSRick McNeal int pqi_transport_command(pqi_state_t *s, pqi_cmd_t *cmd); 588*8226594fSRick McNeal pqi_cmd_action_t pqi_fail_cmd(pqi_cmd_t *cmd, uchar_t reason, uint_t stats); 589*8226594fSRick McNeal void pqi_fail_drive_cmds(pqi_device_t *devp, uchar_t reason); 590*8226594fSRick McNeal void pqi_watchdog(void *v); 591*8226594fSRick McNeal void pqi_do_rescan(void *v); 592*8226594fSRick McNeal void pqi_event_worker(void *v); 593*8226594fSRick McNeal uint32_t pqi_disable_intr(pqi_state_t *s); 594*8226594fSRick McNeal void pqi_enable_intr(pqi_state_t *s, uint32_t old_state); 595*8226594fSRick McNeal void pqi_lun_reset(pqi_state_t *s, pqi_device_t *d); 596*8226594fSRick McNeal 597*8226594fSRick McNeal /* ---- smartpqi_util.c ---- */ 598*8226594fSRick McNeal pqi_dma_overhead_t *pqi_alloc_single(pqi_state_t *s, size_t len); 599*8226594fSRick McNeal void pqi_free_single(pqi_state_t *s, pqi_dma_overhead_t *d); 600*8226594fSRick McNeal pqi_io_request_t *pqi_alloc_io(pqi_state_t *s); 601*8226594fSRick McNeal void pqi_free_io(pqi_io_request_t *io); 602*8226594fSRick McNeal boolean_t pqi_timeout_io(pqi_io_request_t *io); 603*8226594fSRick McNeal boolean_t pqi_service_io(pqi_io_request_t *io, uint8_t generation); 604*8226594fSRick McNeal void pqi_dump_io(pqi_io_request_t *io); 605*8226594fSRick McNeal pqi_cmd_action_t pqi_cmd_action(pqi_cmd_t *cmd, pqi_cmd_action_t a); 606*8226594fSRick McNeal pqi_cmd_action_t pqi_cmd_action_nolock(pqi_cmd_t *cmd, pqi_cmd_action_t a); 607*8226594fSRick McNeal char *pqi_event_to_str(uint8_t event); 608*8226594fSRick McNeal int pqi_map_event(uint8_t event); 609*8226594fSRick McNeal boolean_t pqi_supported_event(uint8_t event_type); 610*8226594fSRick McNeal char *bool_to_str(int v); 611*8226594fSRick McNeal char *dtype_to_str(int t); 612*8226594fSRick McNeal void pqi_free_mem_len(mem_len_pair_t *m); 613*8226594fSRick McNeal mem_len_pair_t pqi_alloc_mem_len(int len); 614*8226594fSRick McNeal mem_len_pair_t build_cdb_str(uint8_t *cdb); 615*8226594fSRick McNeal boolean_t pqi_is_offline(pqi_state_t *s); 616*8226594fSRick McNeal void pqi_show_dev_state(pqi_state_t *s); 617*8226594fSRick McNeal char *cdb_to_str(uint8_t scsi_cmd); 618*8226594fSRick McNeal char *io_status_to_str(int val); 619*8226594fSRick McNeal char *scsi_status_to_str(uint8_t val); 620*8226594fSRick McNeal char *iu_type_to_str(int val); 621*8226594fSRick McNeal 622*8226594fSRick McNeal #ifdef __cplusplus 623*8226594fSRick McNeal } 624*8226594fSRick McNeal #endif 625*8226594fSRick McNeal 626*8226594fSRick McNeal #endif /* _SMARTPQI_H */ 627