1*85Scth /* 2*85Scth * CDDL HEADER START 3*85Scth * 4*85Scth * The contents of this file are subject to the terms of the 5*85Scth * Common Development and Distribution License, Version 1.0 only 6*85Scth * (the "License"). You may not use this file except in compliance 7*85Scth * with the License. 8*85Scth * 9*85Scth * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*85Scth * or http://www.opensolaris.org/os/licensing. 11*85Scth * See the License for the specific language governing permissions 12*85Scth * and limitations under the License. 13*85Scth * 14*85Scth * When distributing Covered Code, include this CDDL HEADER in each 15*85Scth * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*85Scth * If applicable, add the following below this CDDL HEADER, with the 17*85Scth * fields enclosed by brackets "[]" replaced with your own identifying 18*85Scth * information: Portions Copyright [yyyy] [name of copyright owner] 19*85Scth * 20*85Scth * CDDL HEADER END 21*85Scth */ 22*85Scth /* 23*85Scth * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*85Scth * Use is subject to license terms. 25*85Scth */ 26*85Scth 27*85Scth #ifndef _SYS_SCSI_ADAPTERS_EMUL64VAR_H 28*85Scth #define _SYS_SCSI_ADAPTERS_EMUL64VAR_H 29*85Scth 30*85Scth #pragma ident "%Z%%M% %I% %E% SMI" 31*85Scth 32*85Scth #include <sys/avl.h> 33*85Scth #include <sys/note.h> 34*85Scth #include <sys/emul64.h> 35*85Scth 36*85Scth #ifdef __cplusplus 37*85Scth extern "C" { 38*85Scth #endif 39*85Scth 40*85Scth /* 41*85Scth * Convenient short hand defines 42*85Scth */ 43*85Scth #define TRUE 1 44*85Scth #define FALSE 0 45*85Scth #define UNDEFINED -1 46*85Scth 47*85Scth #define CNUM(emul64) (ddi_get_instance(emul64->emul64_tran.tran_dev)) 48*85Scth 49*85Scth #define EMUL64_RETRY_DELAY 5 50*85Scth #define EMUL64_RETRIES 0 /* retry of selections */ 51*85Scth #define EMUL64_INITIAL_SOFT_SPACE 5 /* Used for the softstate_init func */ 52*85Scth 53*85Scth #define MSW(x) (int16_t)(((int32_t)x >> 16) & 0xFFFF) 54*85Scth #define LSW(x) (int16_t)((int32_t)x & 0xFFFF) 55*85Scth 56*85Scth #define TGT(sp) (CMD2PKT(sp)->pkt_address.a_target) 57*85Scth #define LUN(sp) (CMD2PKT(sp)->pkt_address.a_lun) 58*85Scth 59*85Scth #define HW_REV(val) (((val) >>8) & 0xff) 60*85Scth #define FW_REV(val) ((val) & 0xff) 61*85Scth 62*85Scth /* 63*85Scth * max number of LUNs per target 64*85Scth */ 65*85Scth #define EMUL64_NLUNS_PER_TARGET 32 66*85Scth 67*85Scth /* 68*85Scth * Default emul64 scsi-options 69*85Scth */ 70*85Scth #define EMUL64_DEFAULT_SCSI_OPTIONS \ 71*85Scth SCSI_OPTIONS_PARITY | \ 72*85Scth SCSI_OPTIONS_DR | \ 73*85Scth SCSI_OPTIONS_SYNC | \ 74*85Scth SCSI_OPTIONS_TAG | \ 75*85Scth SCSI_OPTIONS_FAST | \ 76*85Scth SCSI_OPTIONS_WIDE 77*85Scth 78*85Scth /* 79*85Scth * Tag reject 80*85Scth */ 81*85Scth #define TAG_REJECT 28 82*85Scth /* 83*85Scth * Interrupt actions returned by emul64_i_flag_event() 84*85Scth */ 85*85Scth #define ACTION_CONTINUE 0 /* Continue */ 86*85Scth #define ACTION_RETURN 1 /* Exit */ 87*85Scth #define ACTION_IGNORE 2 /* Ignore */ 88*85Scth 89*85Scth /* 90*85Scth * Reset actions for emul64_i_reset_interface() 91*85Scth */ 92*85Scth #define EMUL64_RESET_BUS_IF_BUSY 0x01 /* reset scsi bus if it is busy */ 93*85Scth #define EMUL64_FORCE_RESET_BUS 0x02 /* reset scsi bus on error reco */ 94*85Scth 95*85Scth 96*85Scth /* 97*85Scth * extracting period and offset from emul64_synch 98*85Scth */ 99*85Scth #define PERIOD_MASK(val) ((val) & 0xff) 100*85Scth #define OFFSET_MASK(val) (((val) >>8) & 0xff) 101*85Scth 102*85Scth /* 103*85Scth * timeout values 104*85Scth */ 105*85Scth #define EMUL64_GRACE 10 /* Timeout margin (sec.) */ 106*85Scth #define EMUL64_TIMEOUT_DELAY(secs, delay) (secs * (1000000 / delay)) 107*85Scth 108*85Scth /* 109*85Scth * delay time for polling loops 110*85Scth */ 111*85Scth #define EMUL64_NOINTR_POLL_DELAY_TIME 1000 /* usecs */ 112*85Scth 113*85Scth /* 114*85Scth * busy wait delay time after chip reset 115*85Scth */ 116*85Scth #define EMUL64_CHIP_RESET_BUSY_WAIT_TIME 100 /* usecs */ 117*85Scth 118*85Scth /* 119*85Scth * timeout for EMUL64 coming out of reset 120*85Scth */ 121*85Scth #define EMUL64_RESET_WAIT 1000 /* ms */ 122*85Scth #define EMUL64_SOFT_RESET_TIME 1 /* second */ 123*85Scth 124*85Scth /* 125*85Scth * emul64_softstate flags for introducing hot plug 126*85Scth */ 127*85Scth #define EMUL64_SS_OPEN 0x01 128*85Scth #define EMUL64_SS_DRAINING 0x02 129*85Scth #define EMUL64_SS_QUIESCED 0x04 130*85Scth #define EMUL64_SS_DRAIN_ERROR 0x08 131*85Scth 132*85Scth /* 133*85Scth * ioctl command definitions 134*85Scth */ 135*85Scth #ifndef EMUL64_RESET_TARGET 136*85Scth #define EMUL64_RESET_TARGET (('i' << 8) | 0x03) 137*85Scth #endif 138*85Scth 139*85Scth 140*85Scth /* 141*85Scth * Debugging macros 142*85Scth */ 143*85Scth #define EMUL64_DEBUG if (emul64debug) emul64_i_log 144*85Scth #define EMUL64_DEBUG2 if (emul64debug > 1) emul64_i_log 145*85Scth 146*85Scth 147*85Scth #define REQ_TGT_LUN(tgt, lun) (((tgt) << 8) | (lun)) 148*85Scth 149*85Scth 150*85Scth #define RESP_CQ_FLAGS(resp) ((resp->resp_header.cq_flags_seq) & 0xff) 151*85Scth 152*85Scth 153*85Scth #define EMUL64_NDATASEGS 4 154*85Scth 155*85Scth 156*85Scth /* 157*85Scth * translate scsi_pkt flags into EMUL64 request packet flags 158*85Scth * It would be illegal if two flags are set; the driver does not 159*85Scth * check for this. Setting NODISCON and a tag flag is harmless. 160*85Scth */ 161*85Scth #define EMUL64_SET_PKT_FLAGS(scsa_flags, emul64_flags) { \ 162*85Scth emul64_flags = (scsa_flags >> 11) & 0xe; /* tags */ \ 163*85Scth emul64_flags |= (scsa_flags >> 1) & 0x1; /* no disconnect */ \ 164*85Scth } 165*85Scth 166*85Scth /* 167*85Scth * throttle values for EMUL64 request queue 168*85Scth */ 169*85Scth #define SHUTDOWN_THROTTLE -1 /* do not submit any requests */ 170*85Scth #define CLEAR_THROTTLE (EMUL64_MAX_REQUESTS -1) 171*85Scth 172*85Scth 173*85Scth #define EMUL64_GET_PKT_STATE(state) ((uint32_t)(state >> 8)) 174*85Scth #define EMUL64_GET_PKT_STATS(stats) ((uint32_t)(stats)) 175*85Scth 176*85Scth #define EMUL64_STAT_NEGOTIATE 0x0080 177*85Scth 178*85Scth #define EMUL64_SET_REASON(sp, reason) { \ 179*85Scth if ((sp) && CMD2PKT(sp)->pkt_reason == CMD_CMPLT) \ 180*85Scth CMD2PKT(sp)->pkt_reason = (reason); \ 181*85Scth } 182*85Scth 183*85Scth /* 184*85Scth * mutex short hands 185*85Scth */ 186*85Scth #define EMUL64_REQ_MUTEX(emul64) (&emul64->emul64_request_mutex) 187*85Scth #define EMUL64_RESP_MUTEX(emul64) (&emul64->emul64_response_mutex) 188*85Scth #define EMUL64_HOTPLUG_MUTEX(emul64) (&emul64->emul64_hotplug_mutex) 189*85Scth 190*85Scth 191*85Scth #define EMUL64_MUTEX_ENTER(emul64) mutex_enter(EMUL64_RESP_MUTEX(emul64)), \ 192*85Scth mutex_enter(EMUL64_REQ_MUTEX(emul64)) 193*85Scth #define EMUL64_MUTEX_EXIT(emul64) mutex_exit(EMUL64_RESP_MUTEX(emul64)), \ 194*85Scth mutex_exit(EMUL64_REQ_MUTEX(emul64)) 195*85Scth 196*85Scth #define EMUL64_CV(emul64) (&(emul64)->emul64_cv) 197*85Scth 198*85Scth /* 199*85Scth * HBA interface macros 200*85Scth */ 201*85Scth #define SDEV2TRAN(sd) ((sd)->sd_address.a_hba_tran) 202*85Scth #define SDEV2ADDR(sd) (&((sd)->sd_address)) 203*85Scth #define PKT2TRAN(pkt) ((pkt)->pkt_address.a_hba_tran) 204*85Scth #define ADDR2TRAN(ap) ((ap)->a_hba_tran) 205*85Scth 206*85Scth #define TRAN2EMUL64(tran) ((struct emul64 *)(tran)->tran_hba_private) 207*85Scth #define SDEV2EMUL64(sd) (TRAN2EMUL64(SDEV2TRAN(sd))) 208*85Scth #define PKT2EMUL64(pkt) (TRAN2EMUL64(PKT2TRAN(pkt))) 209*85Scth #define ADDR2EMUL64(ap) (TRAN2EMUL64(ADDR2TRAN(ap))) 210*85Scth 211*85Scth #define CMD2ADDR(cmd) (&CMD2PKT(cmd)->pkt_address) 212*85Scth #define CMD2TRAN(cmd) (CMD2PKT(cmd)->pkt_address.a_hba_tran) 213*85Scth #define CMD2EMUL64(cmd) (TRAN2EMUL64(CMD2TRAN(cmd))) 214*85Scth 215*85Scth /* 216*85Scth * Results of checking for range overlap. 217*85Scth */ 218*85Scth typedef enum emul64_rng_overlap { 219*85Scth O_NONE, /* No overlap */ 220*85Scth O_SAME, /* Ranges are identical */ 221*85Scth O_SUBSET, /* Blocks are contained in range */ 222*85Scth O_OVERLAP /* Ranges overlap. */ 223*85Scth } emul64_rng_overlap_t; 224*85Scth 225*85Scth /* 226*85Scth * Rather than keep the entire image of the disk, we only keep 227*85Scth * the blocks which have been written with non-zeros. As the 228*85Scth * purpose of this driver is to exercise format and perhaps other 229*85Scth * large-disk management tools, only recording the label for 230*85Scth * i/o is sufficient 231*85Scth */ 232*85Scth typedef struct blklist { 233*85Scth diskaddr_t bl_blkno; /* Disk address of the data */ 234*85Scth uchar_t *bl_data; /* Pointer to the data */ 235*85Scth avl_node_t bl_node; /* Our linkage in AVL tree */ 236*85Scth } blklist_t; 237*85Scth 238*85Scth /* 239*85Scth * Structure to track a range of blocks where writes are to be ignored. 240*85Scth */ 241*85Scth typedef struct emul64_nowrite { 242*85Scth struct emul64_nowrite *emul64_nwnext; /* next item in list */ 243*85Scth emul64_range_t emul64_blocked; /* range to ignore writes */ 244*85Scth } emul64_nowrite_t; 245*85Scth 246*85Scth typedef struct emul64_tgt { 247*85Scth struct scsi_address emul64_tgt_saddr; 248*85Scth struct emul64_tgt *emul64_tgt_next; /* Next tgt on ctlr */ 249*85Scth emul64_nowrite_t *emul64_tgt_nowrite; /* List of regions to */ 250*85Scth /* skip writes */ 251*85Scth diskaddr_t emul64_tgt_sectors; /* # sectors in dev */ 252*85Scth char emul64_tgt_inq[8+16]; 253*85Scth uint_t emul64_tgt_dtype; 254*85Scth uint_t emul64_tgt_ncyls; /* # cylinders in dev */ 255*85Scth uint_t emul64_tgt_nheads; /* # disk heads */ 256*85Scth uint_t emul64_tgt_nsect; /* # sectors */ 257*85Scth uint64_t emul64_list_length; /* # data blks */ 258*85Scth avl_tree_t emul64_tgt_data; /* Tree of data blks */ 259*85Scth kmutex_t emul64_tgt_blk_lock; /* Protect data blks */ 260*85Scth krwlock_t emul64_tgt_nw_lock; /* Guard tgt_nowrite */ 261*85Scth } emul64_tgt_t; 262*85Scth 263*85Scth /* 264*85Scth * emul64 softstate structure 265*85Scth */ 266*85Scth 267*85Scth /* 268*85Scth * deadline slot structure for timeout handling 269*85Scth */ 270*85Scth struct emul64_slot { 271*85Scth struct emul64_cmd *slot_cmd; 272*85Scth clock_t slot_deadline; 273*85Scth }; 274*85Scth 275*85Scth 276*85Scth /* 277*85Scth * Record the reset notification requests from target drivers. 278*85Scth */ 279*85Scth struct emul64_reset_notify_entry { 280*85Scth struct scsi_address *ap; 281*85Scth void (*callback)(caddr_t); 282*85Scth caddr_t arg; 283*85Scth struct emul64_reset_notify_entry *next; 284*85Scth }; 285*85Scth 286*85Scth 287*85Scth struct emul64 { 288*85Scth 289*85Scth /* 290*85Scth * Transport structure for this instance of the hba 291*85Scth */ 292*85Scth scsi_hba_tran_t *emul64_tran; 293*85Scth 294*85Scth /* 295*85Scth * dev_info_t reference can be found in the transport structure 296*85Scth */ 297*85Scth dev_info_t *emul64_dip; 298*85Scth 299*85Scth /* 300*85Scth * Interrupt block cookie 301*85Scth */ 302*85Scth ddi_iblock_cookie_t emul64_iblock; 303*85Scth 304*85Scth /* 305*85Scth * Firmware revision number 306*85Scth */ 307*85Scth uint16_t emul64_major_rev; 308*85Scth uint16_t emul64_minor_rev; 309*85Scth 310*85Scth /* 311*85Scth * timeout id 312*85Scth */ 313*85Scth timeout_id_t emul64_timeout_id; 314*85Scth 315*85Scth /* 316*85Scth * scsi options, scsi_tag_age_limit per emul64 317*85Scth */ 318*85Scth int emul64_scsi_options; 319*85Scth int emul64_target_scsi_options[NTARGETS_WIDE]; 320*85Scth int emul64_scsi_tag_age_limit; 321*85Scth 322*85Scth /* 323*85Scth * scsi_reset_delay per emul64 324*85Scth */ 325*85Scth clock_t emul64_scsi_reset_delay; 326*85Scth 327*85Scth /* 328*85Scth * current host ID 329*85Scth */ 330*85Scth uint8_t emul64_initiator_id; 331*85Scth 332*85Scth /* 333*85Scth * suspended flag for power management 334*85Scth */ 335*85Scth uint8_t emul64_suspended; 336*85Scth 337*85Scth /* 338*85Scth * Host adapter capabilities and offset/period values per target 339*85Scth */ 340*85Scth uint16_t emul64_cap[NTARGETS_WIDE]; 341*85Scth int16_t emul64_synch[NTARGETS_WIDE]; 342*85Scth 343*85Scth /* 344*85Scth * EMUL64 Hardware register pointer. 345*85Scth */ 346*85Scth struct emul64regs *emul64_reg; 347*85Scth 348*85Scth 349*85Scth kmutex_t emul64_request_mutex; 350*85Scth kmutex_t emul64_response_mutex; 351*85Scth 352*85Scth /* 353*85Scth * for keeping track of the max LUNs per target on this bus 354*85Scth */ 355*85Scth uchar_t emul64_max_lun[NTARGETS_WIDE]; 356*85Scth 357*85Scth /* 358*85Scth * for keeping track of each target/lun 359*85Scth */ 360*85Scth int nt_total_sectors[NTARGETS_WIDE][EMUL64_NLUNS_PER_TARGET]; 361*85Scth 362*85Scth struct emul64_reset_notify_entry *emul64_reset_notify_listf; 363*85Scth 364*85Scth ushort_t emul64_backoff; 365*85Scth uint_t emul64_softstate; /* flags for hotplug */ 366*85Scth int emul64_hotplug_waiting; 367*85Scth kcondvar_t emul64_cv; /* cv for bus quiesce/unquiesce */ 368*85Scth kmutex_t emul64_hotplug_mutex; /* Mutex for hotplug */ 369*85Scth taskq_t *emul64_taskq; 370*85Scth emul64_tgt_t *emul64_tgt; 371*85Scth }; 372*85Scth 373*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 374*85Scth emul64::emul64_queue_space)) 375*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 376*85Scth emul64::emul64_request_in)) 377*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 378*85Scth emul64::emul64_request_out)) 379*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 380*85Scth emul64::emul64_request_ptr)) 381*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 382*85Scth emul64::emul64_mbox)) 383*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex, 384*85Scth emul64::emul64_slots)) 385*85Scth 386*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex, 387*85Scth emul64::emul64_response_in)) 388*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex, 389*85Scth emul64::emul64_response_out)) 390*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex, 391*85Scth emul64::emul64_response_ptr)) 392*85Scth 393*85Scth extern void emul64_bsd_init(); 394*85Scth extern void emul64_bsd_fini(); 395*85Scth extern void emul64_bsd_get_props(dev_info_t *); 396*85Scth 397*85Scth extern emul64_rng_overlap_t emul64_overlap(emul64_range_t *, 398*85Scth diskaddr_t, size_t); 399*85Scth extern int emul64_bsd_blkcompare(const void *, const void *); 400*85Scth extern int emul64debug; 401*85Scth extern long emul64_nowrite_count; 402*85Scth extern kmutex_t emul64_stats_mutex; 403*85Scth extern int emul64_collect_stats; 404*85Scth extern uint64_t emul64_taskq_max; 405*85Scth extern int emul64_max_task; 406*85Scth extern int emul64_task_nthreads; 407*85Scth 408*85Scth #ifdef __cplusplus 409*85Scth } 410*85Scth #endif 411*85Scth 412*85Scth #endif /* _SYS_SCSI_ADAPTERS_EMUL64VAR_H */ 413