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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #ifndef _SYS_SCSI_ADAPTERS_EMUL64VAR_H
28 #define _SYS_SCSI_ADAPTERS_EMUL64VAR_H
30 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include <sys/emul64.h>
41 * Convenient short hand defines
47 #define CNUM(emul64) (ddi_get_instance(emul64->emul64_tran.tran_dev))
49 #define EMUL64_RETRY_DELAY 5
50 #define EMUL64_RETRIES 0 /* retry of selections */
51 #define EMUL64_INITIAL_SOFT_SPACE 5 /* Used for the softstate_init func */
53 #define MSW(x) (int16_t)(((int32_t)x >> 16) & 0xFFFF)
54 #define LSW(x) (int16_t)((int32_t)x & 0xFFFF)
56 #define TGT(sp) (CMD2PKT(sp)->pkt_address.a_target)
57 #define LUN(sp) (CMD2PKT(sp)->pkt_address.a_lun)
59 #define HW_REV(val) (((val) >>8) & 0xff)
60 #define FW_REV(val) ((val) & 0xff)
63 * max number of LUNs per target
65 #define EMUL64_NLUNS_PER_TARGET 32
68 * Default emul64 scsi-options
70 #define EMUL64_DEFAULT_SCSI_OPTIONS \
71 SCSI_OPTIONS_PARITY | \
83 * Interrupt actions returned by emul64_i_flag_event()
85 #define ACTION_CONTINUE 0 /* Continue */
86 #define ACTION_RETURN 1 /* Exit */
87 #define ACTION_IGNORE 2 /* Ignore */
90 * Reset actions for emul64_i_reset_interface()
92 #define EMUL64_RESET_BUS_IF_BUSY 0x01 /* reset scsi bus if it is busy */
93 #define EMUL64_FORCE_RESET_BUS 0x02 /* reset scsi bus on error reco */
97 * extracting period and offset from emul64_synch
99 #define PERIOD_MASK(val) ((val) & 0xff)
100 #define OFFSET_MASK(val) (((val) >>8) & 0xff)
105 #define EMUL64_GRACE 10 /* Timeout margin (sec.) */
106 #define EMUL64_TIMEOUT_DELAY(secs, delay) (secs * (1000000 / delay))
109 * delay time for polling loops
111 #define EMUL64_NOINTR_POLL_DELAY_TIME 1000 /* usecs */
114 * busy wait delay time after chip reset
116 #define EMUL64_CHIP_RESET_BUSY_WAIT_TIME 100 /* usecs */
119 * timeout for EMUL64 coming out of reset
121 #define EMUL64_RESET_WAIT 1000 /* ms */
122 #define EMUL64_SOFT_RESET_TIME 1 /* second */
125 * emul64_softstate flags for introducing hot plug
127 #define EMUL64_SS_OPEN 0x01
128 #define EMUL64_SS_DRAINING 0x02
129 #define EMUL64_SS_QUIESCED 0x04
130 #define EMUL64_SS_DRAIN_ERROR 0x08
133 * ioctl command definitions
135 #ifndef EMUL64_RESET_TARGET
136 #define EMUL64_RESET_TARGET (('i' << 8) | 0x03)
143 #define EMUL64_DEBUG if (emul64debug) emul64_i_log
144 #define EMUL64_DEBUG2 if (emul64debug > 1) emul64_i_log
147 #define REQ_TGT_LUN(tgt, lun) (((tgt) << 8) | (lun))
150 #define RESP_CQ_FLAGS(resp) ((resp->resp_header.cq_flags_seq) & 0xff)
153 #define EMUL64_NDATASEGS 4
157 * translate scsi_pkt flags into EMUL64 request packet flags
158 * It would be illegal if two flags are set; the driver does not
159 * check for this. Setting NODISCON and a tag flag is harmless.
161 #define EMUL64_SET_PKT_FLAGS(scsa_flags, emul64_flags) { \
162 emul64_flags = (scsa_flags >> 11) & 0xe; /* tags */ \
163 emul64_flags |= (scsa_flags >> 1) & 0x1; /* no disconnect */ \
167 * throttle values for EMUL64 request queue
169 #define SHUTDOWN_THROTTLE -1 /* do not submit any requests */
170 #define CLEAR_THROTTLE (EMUL64_MAX_REQUESTS -1)
173 #define EMUL64_GET_PKT_STATE(state) ((uint32_t)(state >> 8))
174 #define EMUL64_GET_PKT_STATS(stats) ((uint32_t)(stats))
176 #define EMUL64_STAT_NEGOTIATE 0x0080
178 #define EMUL64_SET_REASON(sp, reason) { \
179 if ((sp) && CMD2PKT(sp)->pkt_reason == CMD_CMPLT) \
180 CMD2PKT(sp)->pkt_reason = (reason); \
186 #define EMUL64_REQ_MUTEX(emul64) (&emul64->emul64_request_mutex)
187 #define EMUL64_RESP_MUTEX(emul64) (&emul64->emul64_response_mutex)
188 #define EMUL64_HOTPLUG_MUTEX(emul64) (&emul64->emul64_hotplug_mutex)
191 #define EMUL64_MUTEX_ENTER(emul64) mutex_enter(EMUL64_RESP_MUTEX(emul64)), \
192 mutex_enter(EMUL64_REQ_MUTEX(emul64))
193 #define EMUL64_MUTEX_EXIT(emul64) mutex_exit(EMUL64_RESP_MUTEX(emul64)), \
194 mutex_exit(EMUL64_REQ_MUTEX(emul64))
196 #define EMUL64_CV(emul64) (&(emul64)->emul64_cv)
199 * HBA interface macros
201 #define SDEV2TRAN(sd) ((sd)->sd_address.a_hba_tran)
202 #define SDEV2ADDR(sd) (&((sd)->sd_address))
203 #define PKT2TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
204 #define ADDR2TRAN(ap) ((ap)->a_hba_tran)
206 #define TRAN2EMUL64(tran) ((struct emul64 *)(tran)->tran_hba_private)
207 #define SDEV2EMUL64(sd) (TRAN2EMUL64(SDEV2TRAN(sd)))
208 #define PKT2EMUL64(pkt) (TRAN2EMUL64(PKT2TRAN(pkt)))
209 #define ADDR2EMUL64(ap) (TRAN2EMUL64(ADDR2TRAN(ap)))
211 #define CMD2ADDR(cmd) (&CMD2PKT(cmd)->pkt_address)
212 #define CMD2TRAN(cmd) (CMD2PKT(cmd)->pkt_address.a_hba_tran)
213 #define CMD2EMUL64(cmd) (TRAN2EMUL64(CMD2TRAN(cmd)))
216 * Results of checking for range overlap.
218 typedef enum emul64_rng_overlap
{
219 O_NONE
, /* No overlap */
220 O_SAME
, /* Ranges are identical */
221 O_SUBSET
, /* Blocks are contained in range */
222 O_OVERLAP
/* Ranges overlap. */
223 } emul64_rng_overlap_t
;
226 * Rather than keep the entire image of the disk, we only keep
227 * the blocks which have been written with non-zeros. As the
228 * purpose of this driver is to exercise format and perhaps other
229 * large-disk management tools, only recording the label for
232 typedef struct blklist
{
233 diskaddr_t bl_blkno
; /* Disk address of the data */
234 uchar_t
*bl_data
; /* Pointer to the data */
235 avl_node_t bl_node
; /* Our linkage in AVL tree */
239 * Structure to track a range of blocks where writes are to be ignored.
241 typedef struct emul64_nowrite
{
242 struct emul64_nowrite
*emul64_nwnext
; /* next item in list */
243 emul64_range_t emul64_blocked
; /* range to ignore writes */
246 typedef struct emul64_tgt
{
247 struct scsi_address emul64_tgt_saddr
;
248 struct emul64_tgt
*emul64_tgt_next
; /* Next tgt on ctlr */
249 emul64_nowrite_t
*emul64_tgt_nowrite
; /* List of regions to */
251 diskaddr_t emul64_tgt_sectors
; /* # sectors in dev */
252 char emul64_tgt_inq
[8+16];
253 uint_t emul64_tgt_dtype
;
254 uint_t emul64_tgt_ncyls
; /* # cylinders in dev */
255 uint_t emul64_tgt_nheads
; /* # disk heads */
256 uint_t emul64_tgt_nsect
; /* # sectors */
257 uint64_t emul64_list_length
; /* # data blks */
258 avl_tree_t emul64_tgt_data
; /* Tree of data blks */
259 kmutex_t emul64_tgt_blk_lock
; /* Protect data blks */
260 krwlock_t emul64_tgt_nw_lock
; /* Guard tgt_nowrite */
261 /* Fields for error injection */
262 ushort_t emul64_einj_state
;
263 ushort_t emul64_einj_sense_length
;
264 uint_t emul64_einj_pkt_state
;
265 uint_t emul64_einj_pkt_reason
;
266 struct scsi_status emul64_einj_scsi_status
;
267 uint8_t *emul64_einj_sense_data
;
271 * emul64 softstate structure
275 * deadline slot structure for timeout handling
278 struct emul64_cmd
*slot_cmd
;
279 clock_t slot_deadline
;
284 * Record the reset notification requests from target drivers.
286 struct emul64_reset_notify_entry
{
287 struct scsi_address
*ap
;
288 void (*callback
)(caddr_t
);
290 struct emul64_reset_notify_entry
*next
;
297 * Transport structure for this instance of the hba
299 scsi_hba_tran_t
*emul64_tran
;
302 * dev_info_t reference can be found in the transport structure
304 dev_info_t
*emul64_dip
;
307 * Interrupt block cookie
309 ddi_iblock_cookie_t emul64_iblock
;
312 * Firmware revision number
314 uint16_t emul64_major_rev
;
315 uint16_t emul64_minor_rev
;
320 timeout_id_t emul64_timeout_id
;
323 * scsi options, scsi_tag_age_limit per emul64
325 int emul64_scsi_options
;
326 int emul64_target_scsi_options
[NTARGETS_WIDE
];
327 int emul64_scsi_tag_age_limit
;
330 * scsi_reset_delay per emul64
332 clock_t emul64_scsi_reset_delay
;
337 uint8_t emul64_initiator_id
;
340 * suspended flag for power management
342 uint8_t emul64_suspended
;
345 * Host adapter capabilities and offset/period values per target
347 uint16_t emul64_cap
[NTARGETS_WIDE
];
348 int16_t emul64_synch
[NTARGETS_WIDE
];
351 * EMUL64 Hardware register pointer.
353 struct emul64regs
*emul64_reg
;
356 kmutex_t emul64_request_mutex
;
357 kmutex_t emul64_response_mutex
;
360 * for keeping track of the max LUNs per target on this bus
362 uchar_t emul64_max_lun
[NTARGETS_WIDE
];
365 * for keeping track of each target/lun
367 int nt_total_sectors
[NTARGETS_WIDE
][EMUL64_NLUNS_PER_TARGET
];
369 struct emul64_reset_notify_entry
*emul64_reset_notify_listf
;
371 ushort_t emul64_backoff
;
372 uint_t emul64_softstate
; /* flags for hotplug */
373 int emul64_hotplug_waiting
;
374 kcondvar_t emul64_cv
; /* cv for bus quiesce/unquiesce */
375 kmutex_t emul64_hotplug_mutex
; /* Mutex for hotplug */
376 taskq_t
*emul64_taskq
;
377 emul64_tgt_t
*emul64_tgt
;
380 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
381 emul64::emul64_queue_space
))
382 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
383 emul64::emul64_request_in
))
384 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
385 emul64::emul64_request_out
))
386 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
387 emul64::emul64_request_ptr
))
388 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
389 emul64::emul64_mbox
))
390 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex
,
391 emul64::emul64_slots
))
393 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex
,
394 emul64::emul64_response_in
))
395 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex
,
396 emul64::emul64_response_out
))
397 _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex
,
398 emul64::emul64_response_ptr
))
400 extern void emul64_bsd_init();
401 extern void emul64_bsd_fini();
402 extern void emul64_bsd_get_props(dev_info_t
*);
404 extern emul64_rng_overlap_t
emul64_overlap(emul64_range_t
*,
406 extern int emul64_bsd_blkcompare(const void *, const void *);
407 extern int emul64debug
;
408 extern long emul64_nowrite_count
;
409 extern kmutex_t emul64_stats_mutex
;
410 extern int emul64_collect_stats
;
411 extern uint64_t emul64_taskq_max
;
412 extern int emul64_max_task
;
413 extern int emul64_task_nthreads
;
419 #endif /* _SYS_SCSI_ADAPTERS_EMUL64VAR_H */