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