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