xref: /illumos-gate/usr/src/uts/common/sys/scsi/adapters/smrt/smrt.h (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright (c) 2017, Joyent, Inc.
14  */
15 
16 #ifndef	_SMRT_H
17 #define	_SMRT_H
18 
19 #include <sys/types.h>
20 #include <sys/pci.h>
21 #include <sys/param.h>
22 #include <sys/errno.h>
23 #include <sys/conf.h>
24 #include <sys/map.h>
25 #include <sys/modctl.h>
26 #include <sys/kmem.h>
27 #include <sys/cmn_err.h>
28 #include <sys/stat.h>
29 #include <sys/scsi/scsi.h>
30 #include <sys/scsi/impl/spc3_types.h>
31 #include <sys/devops.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/sdt.h>
35 #include <sys/policy.h>
36 #include <sys/ctype.h>
37 
38 #if !defined(_LITTLE_ENDIAN) || !defined(_BIT_FIELDS_LTOH)
39 /*
40  * This driver contains a number of multi-byte bit fields and other structs
41  * that are only correct on a system with the same ordering as x86.
42  */
43 #error "smrt: driver works only on little endian systems"
44 #endif
45 
46 #ifdef	__cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * Some structures are statically sized based on the expected number of logical
52  * drives and controllers in the system.  These definitions are used throughout
53  * other driver-specific header files, and must appear prior to their
54  * inclusion.
55  */
56 #define	SMRT_MAX_LOGDRV		64	/* Maximum number of logical drives */
57 #define	SMRT_MAX_PHYSDEV	128	/* Maximum number of physical devices */
58 
59 #include <sys/scsi/adapters/smrt/smrt_ciss.h>
60 #include <sys/scsi/adapters/smrt/smrt_scsi.h>
61 
62 #ifdef	__cplusplus
63 extern "C" {
64 #endif
65 
66 extern ddi_device_acc_attr_t smrt_dev_attributes;
67 
68 typedef enum smrt_init_level {
69 	SMRT_INITLEVEL_BASIC =			(0x1 << 0),
70 	SMRT_INITLEVEL_I2O_MAPPED =		(0x1 << 1),
71 	SMRT_INITLEVEL_CFGTBL_MAPPED =		(0x1 << 2),
72 	SMRT_INITLEVEL_PERIODIC =		(0x1 << 3),
73 	SMRT_INITLEVEL_INT_ALLOC =		(0x1 << 4),
74 	SMRT_INITLEVEL_INT_ADDED =		(0x1 << 5),
75 	SMRT_INITLEVEL_INT_ENABLED =		(0x1 << 6),
76 	SMRT_INITLEVEL_SCSA =			(0x1 << 7),
77 	SMRT_INITLEVEL_MUTEX =			(0x1 << 8),
78 	SMRT_INITLEVEL_TASKQ =			(0x1 << 9),
79 	SMRT_INITLEVEL_ASYNC_EVENT =		(0x1 << 10),
80 } smrt_init_level_t;
81 
82 /*
83  * Commands issued to the controller carry a (generally 32-bit, though with
84  * two reserved signalling bits) identifying tag number.  In order to avoid
85  * having the controller confuse us by double-reporting the completion of a
86  * particular tag, we try to reuse them as infrequently as possible.  In
87  * practice, this means looping through a range of values.  The minimum and
88  * maximum value are defined below.  A single command tag value is set aside
89  * for polled commands sent prior to full initialisation of the driver.
90  */
91 #define	SMRT_PRE_TAG_NUMBER			0x00000bad
92 #define	SMRT_MIN_TAG_NUMBER			0x00001000
93 #define	SMRT_MAX_TAG_NUMBER			0x0fffffff
94 
95 /*
96  * Character strings that represent the names of the iports used for both
97  * physical and virtual volumes.
98  */
99 #define	SMRT_IPORT_PHYS				"p0"
100 #define	SMRT_IPORT_VIRT				"v0"
101 
102 /*
103  * Definitions to support waiting for the controller to converge on a
104  * particular state: ready or not ready.  These are used with
105  * smrt_ctlr_wait_for_state().
106  */
107 #define	SMRT_WAIT_DELAY_SECONDS			120
108 typedef enum smrt_wait_state {
109 	SMRT_WAIT_STATE_READY = 1,
110 	SMRT_WAIT_STATE_UNREADY
111 } smrt_wait_state_t;
112 
113 typedef enum smrt_ctlr_mode {
114 	SMRT_CTLR_MODE_UNKNOWN = 0,
115 	SMRT_CTLR_MODE_SIMPLE
116 } smrt_ctlr_mode_t;
117 
118 /*
119  * In addition to Logical Volumes, we also expose the controller at a
120  * pseudo target address on the SCSI bus we are essentially pretending to be.
121  */
122 #define	SMRT_CONTROLLER_TARGET			128
123 
124 /*
125  * When waiting for volume discovery to complete, we wait for a maximum
126  * duration (in seconds) before giving up.
127  */
128 #define	SMRT_DISCOVER_TIMEOUT			30
129 
130 /*
131  * The maintenance routine which checks for controller lockup and aborts
132  * commands that have passed their timeout runs periodically.  The time is
133  * expressed in seconds.
134  */
135 #define	SMRT_PERIODIC_RATE			5
136 
137 /*
138  * At times, we need to check if the controller is still responding.  To do
139  * that, we send a Nop message to the controller and make sure it completes
140  * successfully.  So that we don't wait forever, we set a timeout (in seconds).
141  */
142 #define	SMRT_PING_CHECK_TIMEOUT			60
143 
144 /*
145  * When detaching the device, we may need to have an asynchronous event
146  * cancellation be issued.  While this should be relatively smooth, we don't
147  * want to wait forever for it.  As such we set a timeout in seconds.
148  */
149 #define	SMRT_ASYNC_CANCEL_TIMEOUT		60
150 
151 /*
152  * HP PCI vendor ID and Generation 9 device ID. Used to identify generations of
153  * supported controllers.
154  */
155 #define	SMRT_VENDOR_HP				0x103c
156 #define	SMRT_DEVICE_GEN9			0x3238
157 
158 typedef enum smrt_controller_status {
159 	/*
160 	 * An attempt is being made to detach the controller instance.
161 	 */
162 	SMRT_CTLR_STATUS_DETACHING =		(0x1 << 0),
163 
164 	/*
165 	 * The controller is believed to be functioning correctly.  The driver
166 	 * is to allow command submission, process interrupts, and perform
167 	 * periodic background maintenance.
168 	 */
169 	SMRT_CTLR_STATUS_RUNNING =		(0x1 << 1),
170 
171 	/*
172 	 * The controller is currently being reset.
173 	 */
174 	SMRT_CTLR_STATUS_RESETTING =		(0x1 << 2),
175 
176 	/*
177 	 * Our async event notification command is currently in need of help
178 	 * from the broader driver.  This will be set by smrt_event_complete()
179 	 * to indicate that the command is not being processed due to a
180 	 * controller reset or because another fatal error occurred.  The
181 	 * periodic will have to pick up and recover this for us.  It is only
182 	 * safe for the driver to manipulate the event command outside of
183 	 * smrt_event_complete() if this flag is set.
184 	 */
185 	SMRT_CTLR_ASYNC_INTERVENTION =		(0x1 << 3),
186 
187 	/*
188 	 * See the theory statement on discovery and resets in smrt_ciss.c for
189 	 * an explanation of these values.
190 	 */
191 	SMRT_CTLR_DISCOVERY_REQUESTED =		(0x1 << 4),
192 	SMRT_CTLR_DISCOVERY_RUNNING =		(0x1 << 5),
193 	SMRT_CTLR_DISCOVERY_PERIODIC =		(0x1 << 6),
194 	SMRT_CTLR_DISCOVERY_REQUIRED =		(0x1 << 7),
195 } smrt_controller_status_t;
196 
197 #define	SMRT_CTLR_DISCOVERY_MASK	(SMRT_CTLR_DISCOVERY_REQUESTED | \
198     SMRT_CTLR_DISCOVERY_RUNNING | SMRT_CTLR_DISCOVERY_PERIODIC)
199 
200 typedef struct smrt_stats {
201 	uint64_t smrts_tran_aborts;
202 	uint64_t smrts_tran_resets;
203 	uint64_t smrts_tran_starts;
204 	uint64_t smrts_ctlr_resets;
205 	unsigned smrts_max_inflight;
206 	uint64_t smrts_unclaimed_interrupts;
207 	uint64_t smrts_claimed_interrupts;
208 	uint64_t smrts_ignored_scsi_cmds;
209 	uint64_t smrts_events_received;
210 	uint64_t smrts_events_errors;
211 	uint64_t smrts_events_intervened;
212 	uint64_t smrts_discovery_tq_errors;
213 } smrt_stats_t;
214 
215 typedef struct smrt_versions {
216 	uint8_t smrtv_hardware_version;
217 
218 	/*
219 	 * These strings must be large enough to hold the 4 byte version string
220 	 * retrieved from an IDENTIFY CONTROLLER response, as well as the
221 	 * terminating NUL byte:
222 	 */
223 	char smrtv_firmware_rev[5];
224 	char smrtv_recovery_rev[5];
225 	char smrtv_bootblock_rev[5];
226 } smrt_versions_t;
227 
228 typedef struct smrt smrt_t;
229 typedef struct smrt_command smrt_command_t;
230 typedef struct smrt_command_internal smrt_command_internal_t;
231 typedef struct smrt_command_scsa smrt_command_scsa_t;
232 typedef struct smrt_pkt smrt_pkt_t;
233 
234 /*
235  * Per-Controller Structure
236  */
237 struct smrt {
238 	dev_info_t *smrt_dip;
239 	int smrt_instance;
240 	smrt_controller_status_t smrt_status;
241 	smrt_stats_t smrt_stats;
242 
243 	/*
244 	 * Controller configuration discovered during initialisation.
245 	 */
246 	uint32_t smrt_host_support;
247 	uint32_t smrt_bus_support;
248 	uint32_t smrt_maxcmds;
249 	uint32_t smrt_sg_cnt;
250 	smrt_versions_t smrt_versions;
251 	uint16_t smrt_pci_vendor;
252 	uint16_t smrt_pci_device;
253 
254 	/*
255 	 * iport specific data
256 	 */
257 	dev_info_t *smrt_virt_iport;
258 	dev_info_t *smrt_phys_iport;
259 	scsi_hba_tgtmap_t *smrt_virt_tgtmap;
260 	scsi_hba_tgtmap_t *smrt_phys_tgtmap;
261 
262 	/*
263 	 * The transport mode of the controller.
264 	 */
265 	smrt_ctlr_mode_t smrt_ctlr_mode;
266 
267 	/*
268 	 * The current initialisation level of the driver.  Bits in this field
269 	 * are set during initialisation and unset during cleanup of the
270 	 * allocated resources.
271 	 */
272 	smrt_init_level_t smrt_init_level;
273 
274 	/*
275 	 * Essentially everything is protected by "smrt_mutex".  When the
276 	 * completion queue is updated, threads sleeping on "smrt_cv_finishq"
277 	 * are awoken.
278 	 */
279 	kmutex_t smrt_mutex;
280 	kcondvar_t smrt_cv_finishq;
281 
282 	/*
283 	 * List of enumerated logical volumes (smrt_volume_t).
284 	 */
285 	list_t smrt_volumes;
286 
287 	/*
288 	 * List of enumerated physical devices (smrt_physical_t).
289 	 */
290 	list_t smrt_physicals;
291 
292 	/*
293 	 * List of attached SCSA target drivers (smrt_target_t).
294 	 */
295 	list_t smrt_targets;
296 
297 	/*
298 	 * Controller Heartbeat Tracking
299 	 */
300 	uint32_t smrt_last_heartbeat;
301 	hrtime_t smrt_last_heartbeat_time;
302 
303 	hrtime_t smrt_last_interrupt_claimed;
304 	hrtime_t smrt_last_interrupt_unclaimed;
305 	hrtime_t smrt_last_reset_start;
306 	hrtime_t smrt_last_reset_finish;
307 
308 	/*
309 	 * Command object tracking.  These lists, and all commands within the
310 	 * lists, are protected by "smrt_mutex".
311 	 */
312 	uint32_t smrt_next_tag;
313 	avl_tree_t smrt_inflight;
314 	list_t smrt_commands;		/* List of all commands. */
315 	list_t smrt_finishq;		/* List of completed commands. */
316 	list_t smrt_abortq;		/* List of commands to abort. */
317 
318 	/*
319 	 * Discovery coordination
320 	 */
321 	ddi_taskq_t *smrt_discover_taskq;
322 	hrtime_t smrt_last_phys_discovery;
323 	hrtime_t smrt_last_log_discovery;
324 	uint64_t smrt_discover_gen;
325 
326 	/*
327 	 * Controller interrupt handler registration.
328 	 */
329 	int smrt_interrupt_type;
330 	int smrt_interrupt_cap;
331 	uint_t smrt_interrupt_pri;
332 	ddi_intr_handle_t smrt_interrupts[1];
333 	int smrt_ninterrupts;
334 
335 	ddi_periodic_t smrt_periodic;
336 
337 	scsi_hba_tran_t *smrt_hba_tran;
338 
339 	ddi_dma_attr_t smrt_dma_attr;
340 
341 	/*
342 	 * Access to the I2O Registers:
343 	 */
344 	unsigned smrt_i2o_bar;
345 	caddr_t smrt_i2o_space;
346 	ddi_acc_handle_t smrt_i2o_handle;
347 
348 	/*
349 	 * Access to the Configuration Table:
350 	 */
351 	unsigned smrt_ct_bar;
352 	uint32_t smrt_ct_baseaddr;
353 	CfgTable_t *smrt_ct;
354 	ddi_acc_handle_t smrt_ct_handle;
355 
356 	/*
357 	 * Asynchronous Event State
358 	 */
359 	uint32_t smrt_event_count;
360 	smrt_command_t *smrt_event_cmd;
361 	smrt_command_t *smrt_event_cancel_cmd;
362 	kcondvar_t smrt_event_queue;
363 };
364 
365 /*
366  * Logical Volume Structure
367  */
368 typedef enum smrt_volume_flags {
369 	SMRT_VOL_FLAG_WWN =			(0x1 << 0),
370 } smrt_volume_flags_t;
371 
372 typedef struct smrt_volume {
373 	LUNAddr_t smlv_addr;
374 	smrt_volume_flags_t smlv_flags;
375 
376 	uint8_t smlv_wwn[16];
377 	uint64_t smlv_gen;
378 
379 	smrt_t *smlv_ctlr;
380 	list_node_t smlv_link;
381 
382 	/*
383 	 * List of SCSA targets currently attached to this Logical Volume:
384 	 */
385 	list_t smlv_targets;
386 } smrt_volume_t;
387 
388 typedef struct smrt_physical {
389 	LUNAddr_t smpt_addr;
390 	uint64_t smpt_wwn;
391 	uint8_t smpt_dtype;
392 	uint16_t smpt_bmic;
393 	uint64_t smpt_gen;
394 	boolean_t smpt_supported;
395 	boolean_t smpt_visible;
396 	boolean_t smpt_unsup_warn;
397 	list_node_t smpt_link;
398 	list_t smpt_targets;
399 	smrt_t *smpt_ctlr;
400 	smrt_identify_physical_drive_t *smpt_info;
401 } smrt_physical_t;
402 
403 /*
404  * Per-Target Structure
405  */
406 typedef struct smrt_target {
407 	struct scsi_device *smtg_scsi_dev;
408 
409 	boolean_t smtg_physical;
410 
411 	/*
412 	 * This is only used when performing discovery during panic, as we need
413 	 * a mechanism to determine if the set of drives has shifted.
414 	 */
415 	boolean_t smtg_gone;
416 
417 	/*
418 	 * Linkage back to the device that this target represents. This may be
419 	 * either a smrt_volume_t or a smrt_physical_t. We keep a pointer to the
420 	 * address, as that's the one thing we generally care about.
421 	 */
422 	union {
423 		smrt_physical_t *smtg_phys;
424 		smrt_volume_t *smtg_vol;
425 	} smtg_lun;
426 	list_node_t smtg_link_lun;
427 	LUNAddr_t *smtg_addr;
428 
429 	/*
430 	 * Linkage back to the controller:
431 	 */
432 	smrt_t *smtg_ctlr;
433 	list_node_t smtg_link_ctlr;
434 } smrt_target_t;
435 
436 /*
437  * DMA Resource Tracking Structure
438  */
439 typedef enum smrt_dma_level {
440 	SMRT_DMALEVEL_HANDLE_ALLOC =		(0x1 << 0),
441 	SMRT_DMALEVEL_MEMORY_ALLOC =		(0x1 << 1),
442 	SMRT_DMALEVEL_HANDLE_BOUND =		(0x1 << 2),
443 } smrt_dma_level_t;
444 
445 typedef struct smrt_dma {
446 	smrt_dma_level_t smdma_level;
447 	size_t smdma_real_size;
448 	ddi_dma_handle_t smdma_dma_handle;
449 	ddi_acc_handle_t smdma_acc_handle;
450 	ddi_dma_cookie_t smdma_dma_cookies[1];
451 	uint_t smdma_dma_ncookies;
452 } smrt_dma_t;
453 
454 
455 typedef enum smrt_command_status {
456 	/*
457 	 * When a command is submitted to the controller, it is marked USED
458 	 * to avoid accidental reuse of the command without reinitialising
459 	 * critical fields.  The submitted command is also marked INFLIGHT
460 	 * to reflect its inclusion in the "smrt_inflight" AVL tree.  When
461 	 * the command is completed by the controller, INFLIGHT is unset.
462 	 */
463 	SMRT_CMD_STATUS_USED =			(0x1 << 0),
464 	SMRT_CMD_STATUS_INFLIGHT =		(0x1 << 1),
465 
466 	/*
467 	 * This flag is set during abort queue processing to record that this
468 	 * command was aborted in response to an expired timeout, and not some
469 	 * other cancellation.  If the controller is able to abort the command,
470 	 * we use this flag to let the SCSI framework know that the command
471 	 * timed out.
472 	 */
473 	SMRT_CMD_STATUS_TIMEOUT =		(0x1 << 2),
474 
475 	/*
476 	 * The controller set the error bit when completing this command.
477 	 * Details of the particular fault may be read from the error
478 	 * information written by the controller.
479 	 */
480 	SMRT_CMD_STATUS_ERROR =			(0x1 << 3),
481 
482 	/*
483 	 * This command has been abandoned by the original submitter.  This
484 	 * could happen if the command did not complete in a timely fashion.
485 	 * When it reaches the finish queue it will be freed without further
486 	 * processing.
487 	 */
488 	SMRT_CMD_STATUS_ABANDONED =		(0x1 << 4),
489 
490 	/*
491 	 * This command has made it through the completion queue and had final
492 	 * processing performed.
493 	 */
494 	SMRT_CMD_STATUS_COMPLETE =		(0x1 << 5),
495 
496 	/*
497 	 * A polled message will be ignored by the regular processing of the
498 	 * completion queue.  The blocking function doing the polling is
499 	 * responsible for watching the command on which it has set the POLLED
500 	 * flag.  Regular completion queue processing (which might happen in
501 	 * the polling function, or it might happen in the interrupt handler)
502 	 * will set POLL_COMPLETE once it is out of the finish queue
503 	 * altogether.
504 	 */
505 	SMRT_CMD_STATUS_POLLED =		(0x1 << 6),
506 	SMRT_CMD_STATUS_POLL_COMPLETE =		(0x1 << 7),
507 
508 	/*
509 	 * An abort message has been sent to the controller in an attempt to
510 	 * cancel this command.
511 	 */
512 	SMRT_CMD_STATUS_ABORT_SENT =		(0x1 << 8),
513 
514 	/*
515 	 * This command has been passed to our tran_start(9E) handler.
516 	 */
517 	SMRT_CMD_STATUS_TRAN_START =		(0x1 << 9),
518 
519 	/*
520 	 * This command was for a SCSI command that we are explicitly avoiding
521 	 * sending to the controller.
522 	 */
523 	SMRT_CMD_STATUS_TRAN_IGNORED =		(0x1 << 10),
524 
525 	/*
526 	 * This command has been submitted once, and subsequently passed to
527 	 * smrt_command_reuse().
528 	 */
529 	SMRT_CMD_STATUS_REUSED =		(0x1 << 11),
530 
531 	/*
532 	 * A controller reset has been issued, so a response for this command
533 	 * is not expected.  If one arrives before the controller reset has
534 	 * taken effect, it likely cannot be trusted.
535 	 */
536 	SMRT_CMD_STATUS_RESET_SENT =		(0x1 << 12),
537 
538 	/*
539 	 * Certain commands related to discovery and pinging need to be run
540 	 * during the context after a reset has occurred, but before the
541 	 * controller is considered.  Such commands can use this flag to bypass
542 	 * the normal smrt_submit() check.
543 	 */
544 	SMRT_CMD_IGNORE_RUNNING =		(0x1 << 13),
545 } smrt_command_status_t;
546 
547 typedef enum smrt_command_type {
548 	SMRT_CMDTYPE_INTERNAL = 1,
549 	SMRT_CMDTYPE_EVENT,
550 	SMRT_CMDTYPE_ABORTQ,
551 	SMRT_CMDTYPE_SCSA,
552 	SMRT_CMDTYPE_PREINIT,
553 } smrt_command_type_t;
554 
555 struct smrt_command {
556 	uint32_t smcm_tag;
557 	smrt_command_type_t smcm_type;
558 	smrt_command_status_t smcm_status;
559 
560 	smrt_t *smcm_ctlr;
561 	smrt_target_t *smcm_target;
562 
563 	list_node_t smcm_link;		/* Linkage for allocated list. */
564 	list_node_t smcm_link_finish;	/* Linkage for completion list. */
565 	list_node_t smcm_link_abort;	/* Linkage for abort list. */
566 	avl_node_t smcm_node;		/* Inflight AVL membership. */
567 
568 	hrtime_t smcm_time_submit;
569 	hrtime_t smcm_time_complete;
570 
571 	hrtime_t smcm_expiry;
572 
573 	/*
574 	 * The time at which an abort message was sent to try and terminate
575 	 * this command, as well as the tag of the abort message itself:
576 	 */
577 	hrtime_t smcm_abort_time;
578 	uint32_t smcm_abort_tag;
579 
580 	/*
581 	 * Ancillary data objects.  Only one of these will be allocated for any
582 	 * given command, but we nonetheless resist the temptation to use a
583 	 * union of pointers in order to make incorrect usage obvious.
584 	 */
585 	smrt_command_scsa_t *smcm_scsa;
586 	smrt_command_internal_t *smcm_internal;
587 
588 	/*
589 	 * Physical allocation tracking for the actual command to send to the
590 	 * controller.
591 	 */
592 	smrt_dma_t smcm_contig;
593 
594 	CommandList_t *smcm_va_cmd;
595 	uint32_t smcm_pa_cmd;
596 
597 	ErrorInfo_t *smcm_va_err;
598 	uint32_t smcm_pa_err;
599 };
600 
601 /*
602  * Commands issued internally to the driver (as opposed to by the HBA
603  * framework) generally require a buffer in which to assemble the command body,
604  * and for receiving the response from the controller.  The following object
605  * tracks this (optional) extra buffer.
606  */
607 struct smrt_command_internal {
608 	smrt_dma_t smcmi_contig;
609 
610 	void *smcmi_va;
611 	uint32_t smcmi_pa;
612 	size_t smcmi_len;
613 };
614 
615 /*
616  * Commands issued via the SCSI framework have a number of additional
617  * properties.
618  */
619 struct smrt_command_scsa {
620 	struct scsi_pkt *smcms_pkt;
621 	smrt_command_t *smcms_command;
622 };
623 
624 
625 /*
626  * CISS transport routines.
627  */
628 void smrt_periodic(void *);
629 void smrt_lockup_check(smrt_t *);
630 int smrt_submit(smrt_t *, smrt_command_t *);
631 void smrt_submit_simple(smrt_t *, smrt_command_t *);
632 int smrt_retrieve(smrt_t *);
633 void smrt_retrieve_simple(smrt_t *);
634 int smrt_poll_for(smrt_t *, smrt_command_t *);
635 int smrt_preinit_command_simple(smrt_t *, smrt_command_t *);
636 
637 /*
638  * Interrupt service routines.
639  */
640 int smrt_interrupts_setup(smrt_t *);
641 int smrt_interrupts_enable(smrt_t *);
642 void smrt_interrupts_teardown(smrt_t *);
643 uint32_t smrt_isr_hw_simple(caddr_t, caddr_t);
644 
645 /*
646  * Interrupt enable/disable routines.
647  */
648 void smrt_intr_set(smrt_t *, boolean_t);
649 
650 /*
651  * Controller initialisation routines.
652  */
653 int smrt_ctlr_init(smrt_t *);
654 void smrt_ctlr_teardown(smrt_t *);
655 int smrt_ctlr_reset(smrt_t *);
656 int smrt_ctlr_wait_for_state(smrt_t *, smrt_wait_state_t);
657 int smrt_ctlr_init_simple(smrt_t *);
658 void smrt_ctlr_teardown_simple(smrt_t *);
659 int smrt_cfgtbl_flush(smrt_t *);
660 int smrt_cfgtbl_transport_has_support(smrt_t *, int);
661 void smrt_cfgtbl_transport_set(smrt_t *, int);
662 int smrt_cfgtbl_transport_confirm(smrt_t *, int);
663 uint32_t smrt_ctlr_get_cmdsoutmax(smrt_t *);
664 uint32_t smrt_ctlr_get_maxsgelements(smrt_t *);
665 
666 /*
667  * Device enumeration and lookup routines.
668  */
669 void smrt_discover_request(smrt_t *);
670 
671 int smrt_logvol_discover(smrt_t *, uint16_t, uint64_t);
672 void smrt_logvol_teardown(smrt_t *);
673 smrt_volume_t *smrt_logvol_lookup_by_id(smrt_t *, unsigned long);
674 void smrt_logvol_tgtmap_activate(void *, char *, scsi_tgtmap_tgt_type_t,
675     void **);
676 boolean_t smrt_logvol_tgtmap_deactivate(void *, char *, scsi_tgtmap_tgt_type_t,
677     void *, scsi_tgtmap_deact_rsn_t);
678 
679 int smrt_phys_discover(smrt_t *, uint16_t, uint64_t);
680 smrt_physical_t *smrt_phys_lookup_by_ua(smrt_t *, const char *);
681 void smrt_phys_teardown(smrt_t *);
682 void smrt_phys_tgtmap_activate(void *, char *, scsi_tgtmap_tgt_type_t,
683     void **);
684 boolean_t smrt_phys_tgtmap_deactivate(void *, char *, scsi_tgtmap_tgt_type_t,
685     void *, scsi_tgtmap_deact_rsn_t);
686 
687 /*
688  * SCSI framework routines.
689  */
690 int smrt_ctrl_hba_setup(smrt_t *);
691 void smrt_ctrl_hba_teardown(smrt_t *);
692 
693 int smrt_logvol_hba_setup(smrt_t *, dev_info_t *);
694 void smrt_logvol_hba_teardown(smrt_t *, dev_info_t *);
695 int smrt_phys_hba_setup(smrt_t *, dev_info_t *);
696 void smrt_phys_hba_teardown(smrt_t *, dev_info_t *);
697 
698 void smrt_hba_complete(smrt_command_t *);
699 
700 void smrt_process_finishq(smrt_t *);
701 void smrt_process_abortq(smrt_t *);
702 
703 /*
704  * Command block management.
705  */
706 smrt_command_t *smrt_command_alloc(smrt_t *, smrt_command_type_t,
707     int);
708 smrt_command_t *smrt_command_alloc_preinit(smrt_t *, size_t, int);
709 int smrt_command_attach_internal(smrt_t *, smrt_command_t *, size_t,
710     int);
711 void smrt_command_free(smrt_command_t *);
712 smrt_command_t *smrt_lookup_inflight(smrt_t *, uint32_t);
713 void smrt_command_reuse(smrt_command_t *);
714 
715 /*
716  * Device message construction routines.
717  */
718 void smrt_write_lun_addr_phys(LUNAddr_t *, boolean_t, unsigned, unsigned);
719 void smrt_write_controller_lun_addr(LUNAddr_t *);
720 uint16_t smrt_lun_addr_to_bmic(PhysDevAddr_t *);
721 void smrt_write_message_abort_one(smrt_command_t *, uint32_t);
722 void smrt_write_message_abort_all(smrt_command_t *, LUNAddr_t *);
723 void smrt_write_message_nop(smrt_command_t *, int);
724 void smrt_write_message_event_notify(smrt_command_t *);
725 
726 /*
727  * Device management routines.
728  */
729 int smrt_device_setup(smrt_t *);
730 void smrt_device_teardown(smrt_t *);
731 uint32_t smrt_get32(smrt_t *, offset_t);
732 void smrt_put32(smrt_t *, offset_t, uint32_t);
733 
734 /*
735  * SATA related routines.
736  */
737 int smrt_sata_determine_wwn(smrt_t *, PhysDevAddr_t *, uint64_t *, uint16_t);
738 
739 /*
740  * Asynchronous Event Notification
741  */
742 int smrt_event_init(smrt_t *);
743 void smrt_event_fini(smrt_t *);
744 void smrt_event_complete(smrt_command_t *);
745 
746 #ifdef	__cplusplus
747 }
748 #endif
749 
750 #endif	/* _SMRT_H */
751