4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
25 * Copyright (c) 2016 by Delphix. All rights reserved.
31 * Generic SCSI Host Bus Adapter interface implementation
33 #include <sys/scsi/scsi.h>
34 #include <sys/scsi/generic/sas.h>
36 #include <sys/disp.h> /* for minclsyspri */
37 #include <sys/ddi_impldefs.h>
38 #include <sys/ndi_impldefs.h>
39 #include <sys/sunndi.h>
41 #include <sys/sunmdi.h>
42 #include <sys/mdi_impldefs.h>
43 #include <sys/callb.h>
45 #include <sys/damap.h>
47 #include <sys/sunldi.h>
48 #include <sys/fm/protocol.h>
50 extern struct scsi_pkt
*scsi_init_cache_pkt(struct scsi_address
*,
51 struct scsi_pkt
*, struct buf
*, int, int, int, int,
52 int (*)(caddr_t
), caddr_t
);
53 extern void scsi_free_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
54 extern void scsi_cache_dmafree(struct scsi_address
*, struct scsi_pkt
*);
55 extern void scsi_sync_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
56 extern int modrootloaded
;
59 * Round up all allocations so that we can guarantee
60 * long-long alignment. This is the same alignment
61 * provided by kmem_alloc().
63 #define ROUNDUP(x) (((x) + 0x07) & ~0x07)
65 /* Magic number to track correct allocations in wrappers */
66 #define PKT_WRAPPER_MAGIC 0xa110ced /* alloced correctly */
68 kmutex_t scsi_flag_nointr_mutex
;
69 kcondvar_t scsi_flag_nointr_cv
;
70 kmutex_t scsi_log_mutex
;
72 /* asynchronous probe barrier deletion data structures */
73 static kmutex_t scsi_hba_barrier_mutex
;
74 static kcondvar_t scsi_hba_barrier_cv
;
75 static struct scsi_hba_barrier
{
76 struct scsi_hba_barrier
*barrier_next
;
77 clock_t barrier_endtime
;
78 dev_info_t
*barrier_probe
;
79 } *scsi_hba_barrier_list
;
80 static int scsi_hba_devi_is_barrier(dev_info_t
*probe
);
81 static void scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
);
82 static void scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
);
83 static int scsi_hba_remove_node(dev_info_t
*child
);
84 static void scsi_hba_barrier_daemon(void *arg
);
86 /* LUN-change ASC/ASCQ processing data structures (stage1 and stage2) */
87 static kmutex_t scsi_lunchg1_mutex
;
88 static kcondvar_t scsi_lunchg1_cv
;
89 static struct scsi_pkt
*scsi_lunchg1_list
;
90 static void scsi_lunchg1_daemon(void *arg
);
91 static kmutex_t scsi_lunchg2_mutex
;
92 static kcondvar_t scsi_lunchg2_cv
;
93 static struct scsi_lunchg2
{
94 struct scsi_lunchg2
*lunchg2_next
;
97 static void scsi_lunchg2_daemon(void *arg
);
99 static int scsi_findchild(dev_info_t
*self
, char *name
, char *addr
,
100 int init
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
);
102 /* return value defines for scsi_findchild */
103 #define CHILD_TYPE_NONE 0
104 #define CHILD_TYPE_DEVINFO 1
105 #define CHILD_TYPE_PATHINFO 2
108 * Enumeration code path currently being followed. SE_BUSCONFIG results in
109 * DEVI_SID_NODEID, and SE_HP (hotplug) results in DEVI_SID_HP_NODEID.
111 * Since hotplug enumeration is based on information obtained from hardware
112 * (tgtmap/report_lun) the type/severity of enumeration error messages is
113 * sometimes based SE_HP (indirectly via ndi_dev_is_hotplug_node()). By
114 * convention, these messages are all produced by scsi_enumeration_failed().
116 typedef enum { SE_BUSCONFIG
= 0, SE_HP
= 1 } scsi_enum_t
;
118 /* compatible properties of driver to use during probe/enumeration operations */
119 static char *compatible_probe
= "scsa,probe";
120 static char *compatible_nodev
= "scsa,nodev";
121 static char *scsi_probe_ascii
[] = SCSIPROBE_ASCII
;
123 /* number of LUNs we attempt to get on the first SCMD_REPORT_LUNS command */
124 int scsi_lunrpt_default_max
= 256;
125 int scsi_lunrpt_timeout
= 3; /* seconds */
128 * Only enumerate one lun if reportluns fails on a SCSI_VERSION_3 device
129 * (tunable based on calling context).
131 int scsi_lunrpt_failed_do1lun
= (1 << SE_HP
);
133 /* 'scsi-binding-set' value for legacy enumerated 'spi' transports */
134 char *scsi_binding_set_spi
= "spi";
136 /* enable NDI_DEVI_DEBUG for bus_[un]config operations */
137 int scsi_hba_bus_config_debug
= 0;
139 /* DEBUG: enable NDI_DEVI_REMOVE for bus_unconfig of dynamic node */
140 int scsi_hba_bus_unconfig_remove
= 0;
142 /* number of probe serilization messages */
143 int scsi_hba_wait_msg
= 5;
146 * Establish the timeout used to cache (in the probe node) the fact that the
147 * device does not exist. This replaces the target specific probe cache.
149 int scsi_hba_barrier_timeout
= (60); /* seconds */
152 int scsi_hba_bus_config_failure_msg
= 0;
153 int scsi_hba_bus_config_failure_dbg
= 0;
154 int scsi_hba_bus_config_success_msg
= 0;
155 int scsi_hba_bus_config_success_dbg
= 0;
159 * Structure for scsi_hba_iportmap_* implementation/wrap.
161 typedef struct impl_scsi_iportmap
{
162 dev_info_t
*iportmap_hba_dip
;
163 damap_t
*iportmap_dam
;
164 int iportmap_create_window
;
165 uint64_t iportmap_create_time
; /* clock64_t */
166 int iportmap_create_csync_usec
;
167 int iportmap_settle_usec
;
168 int iportmap_sync_cnt
;
169 } impl_scsi_iportmap_t
;
172 * Structure for scsi_hba_tgtmap_* implementation/wrap.
174 * Every call to scsi_hba_tgtmap_set_begin will increment tgtmap_reports,
175 * and a call to scsi_hba_tgtmap_set_end will reset tgtmap_reports to zero.
176 * If, in scsi_hba_tgtmap_set_begin, we detect a tgtmap_reports value of
177 * scsi_hba_tgtmap_reports_max we produce a message to indicate that
178 * the caller is never completing an observation (i.e. we are not making
179 * any forward progress). If this message occurs, it indicates that the
180 * solaris hotplug ramifications at the target and lun level are no longer
183 * NOTE: LUNMAPSIZE OK for now, but should be dynamic in reportlun code.
185 typedef struct impl_scsi_tgtmap
{
186 scsi_hba_tran_t
*tgtmap_tran
;
187 int tgtmap_reports
; /* _begin, no _end */
189 scsi_tgt_activate_cb_t tgtmap_activate_cb
;
190 scsi_tgt_deactivate_cb_t tgtmap_deactivate_cb
;
191 void *tgtmap_mappriv
;
192 damap_t
*tgtmap_dam
[SCSI_TGT_NTYPES
];
193 int tgtmap_create_window
;
194 uint64_t tgtmap_create_time
; /* clock64_t */
195 int tgtmap_create_csync_usec
;
196 int tgtmap_settle_usec
;
198 } impl_scsi_tgtmap_t
;
199 #define LUNMAPSIZE 256 /* 256 LUNs/target */
201 /* Produce warning if number of begins without an end exceed this value */
202 int scsi_hba_tgtmap_reports_max
= 256;
204 static int scsi_tgtmap_sync(scsi_hba_tgtmap_t
*, int);
206 /* Default settle_usec damap_sync factor */
207 int scsi_hba_map_settle_f
= 10;
210 /* Prototype for static dev_ops devo_*() functions */
211 static int scsi_hba_info(
213 ddi_info_cmd_t infocmd
,
217 /* Prototypes for static bus_ops bus_*() functions */
218 static int scsi_hba_bus_ctl(
225 static int scsi_hba_map_fault(
236 static int scsi_hba_get_eventcookie(
240 ddi_eventcookie_t
*eventp
);
242 static int scsi_hba_add_eventcall(
245 ddi_eventcookie_t event
,
248 ddi_eventcookie_t event
,
252 ddi_callback_id_t
*cb_id
);
254 static int scsi_hba_remove_eventcall(
256 ddi_callback_id_t id
);
258 static int scsi_hba_post_event(
261 ddi_eventcookie_t event
,
264 static int scsi_hba_bus_config(
267 ddi_bus_config_op_t op
,
269 dev_info_t
**childp
);
271 static int scsi_hba_bus_unconfig(
274 ddi_bus_config_op_t op
,
277 static int scsi_hba_fm_init_child(
281 ddi_iblock_cookie_t
*ibc
);
283 static int scsi_hba_bus_power(
286 pm_bus_power_op_t op
,
290 /* bus_ops vector for SCSI HBA's. */
291 static struct bus_ops scsi_hba_busops
= {
293 nullbusmap
, /* bus_map */
294 NULL
, /* bus_get_intrspec */
295 NULL
, /* bus_add_intrspec */
296 NULL
, /* bus_remove_intrspec */
297 scsi_hba_map_fault
, /* bus_map_fault */
298 NULL
, /* bus_dma_map */
299 ddi_dma_allochdl
, /* bus_dma_allochdl */
300 ddi_dma_freehdl
, /* bus_dma_freehdl */
301 ddi_dma_bindhdl
, /* bus_dma_bindhdl */
302 ddi_dma_unbindhdl
, /* bus_unbindhdl */
303 ddi_dma_flush
, /* bus_dma_flush */
304 ddi_dma_win
, /* bus_dma_win */
305 ddi_dma_mctl
, /* bus_dma_ctl */
306 scsi_hba_bus_ctl
, /* bus_ctl */
307 ddi_bus_prop_op
, /* bus_prop_op */
308 scsi_hba_get_eventcookie
, /* bus_get_eventcookie */
309 scsi_hba_add_eventcall
, /* bus_add_eventcall */
310 scsi_hba_remove_eventcall
, /* bus_remove_eventcall */
311 scsi_hba_post_event
, /* bus_post_event */
312 NULL
, /* bus_intr_ctl */
313 scsi_hba_bus_config
, /* bus_config */
314 scsi_hba_bus_unconfig
, /* bus_unconfig */
315 scsi_hba_fm_init_child
, /* bus_fm_init */
316 NULL
, /* bus_fm_fini */
317 NULL
, /* bus_fm_access_enter */
318 NULL
, /* bus_fm_access_exit */
319 scsi_hba_bus_power
/* bus_power */
322 /* cb_ops for hotplug :devctl and :scsi support */
323 static struct cb_ops scsi_hba_cbops
= {
326 nodev
, /* strategy */
331 scsi_hba_ioctl
, /* ioctl */
336 ddi_prop_op
, /* prop_op */
338 D_NEW
|D_MP
|D_HOTPLUG
, /* cb_flag */
340 nodev
, /* int (*cb_aread)() */
341 nodev
/* int (*cb_awrite)() */
344 /* Prototypes for static scsi_hba.c/SCSA private lunmap interfaces */
345 static int scsi_lunmap_create(
347 impl_scsi_tgtmap_t
*tgtmap
,
349 static void scsi_lunmap_destroy(
351 impl_scsi_tgtmap_t
*tgtmap
,
353 static void scsi_lunmap_set_begin(
356 static int scsi_lunmap_set_add(
360 scsi_lun64_t lun_num
,
362 static void scsi_lunmap_set_end(
366 /* Prototypes for static misc. scsi_hba.c private bus_config interfaces */
367 static int scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
368 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
369 static int scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
370 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
371 static dev_info_t
*scsi_hba_bus_config_port(dev_info_t
*self
,
372 char *nameaddr
, scsi_enum_t se
);
375 static int scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
376 void *arg
, dev_info_t
**childp
);
381 * SCSI_HBA_LOG is used for all messages. A logging level is specified when
382 * generating a message. Some levels correspond directly to cmn_err levels,
383 * some are associated with increasing levels diagnostic/debug output (LOG1-4),
384 * and others are associated with specific levels of interface (LOGMAP).
385 * For _LOG() messages, a __func__ prefix will identify the function origin
386 * of the message. For _LOG_NF messages, there is no function prefix or
387 * self/child context. Filtering of messages is provided based on logging
388 * level, but messages with cmn_err logging level and messages generated
389 * generated with _LOG_NF() are never filtered.
391 * For debugging, more complete information can be displayed with each message
392 * (full device path and pointer values) by adjusting scsi_hba_log_info.
395 #define SCSI_HBA_LOGCONT CE_CONT
396 #define SCSI_HBA_LOGNOTE CE_NOTE
397 #define SCSI_HBA_LOGWARN CE_WARN
398 #define SCSI_HBA_LOGPANIC CE_PANIC
399 #define SCSI_HBA_LOGIGNORE CE_IGNORE
400 #define SCSI_HBA_LOG_CE_MASK 0x0000000F /* no filter for these levels */
401 #define SCSI_HBA_LOG1 0x00000010 /* DIAG1 level enable */
402 #define SCSI_HBA_LOG2 0x00000020 /* DIAG2 level enable */
403 #define SCSI_HBA_LOG3 0x00000040 /* DIAG3 level enable */
404 #define SCSI_HBA_LOG4 0x00000080 /* DIAG4 level enable */
405 #define SCSI_HBA_LOGMAPPHY 0x00000100 /* MAPPHY level enable */
406 #define SCSI_HBA_LOGMAPIPT 0x00000200 /* MAPIPT level enable */
407 #define SCSI_HBA_LOGMAPTGT 0x00000400 /* MAPTGT level enable */
408 #define SCSI_HBA_LOGMAPLUN 0x00000800 /* MAPLUN level enable */
409 #define SCSI_HBA_LOGMAPCFG 0x00001000 /* MAPCFG level enable */
410 #define SCSI_HBA_LOGMAPUNCFG 0x00002000 /* MAPUNCFG level enable */
411 #define SCSI_HBA_LOGTRACE 0x00010000 /* TRACE enable */
412 #if (CE_CONT | CE_NOTE | CE_WARN | CE_PANIC | CE_IGNORE) > SCSI_HBA_LOG_CE_MASK
413 Error
, problem with CE_ definitions
417 * Tunable log message augmentation and filters: filters do not apply to
418 * SCSI_HBA_LOG_CE_MASK level messages or LOG_NF() messages.
420 * An example set of /etc/system tunings to simplify debug a SCSA pHCI HBA
421 * driver called "pmcs", including "scsi_vhci" operation, by capturing
422 * log information in the system log might be:
424 * echo "set scsi:scsi_hba_log_filter_level=0x3ff0" >> /etc/system
425 * echo "set scsi:scsi_hba_log_filter_phci=\"pmcs\"" >> /etc/system
426 * echo "set scsi:scsi_hba_log_filter_vhci=\"scsi_vhci\"" >> /etc/system
428 * To capture information on just HBA-SCSAv3 *map operation, use
429 * echo "set scsi:scsi_hba_log_filter_level=0x3f10" >> /etc/system
431 * For debugging an HBA driver, you may also want to set:
433 * echo "set scsi:scsi_hba_log_align=1" >> /etc/system
434 * echo "set scsi:scsi_hba_log_mt_disable=0x6" >> /etc/system
435 * echo "set mtc_off=1" >> /etc/system
436 * echo "set mdi_mtc_off=1" >> /etc/system
437 * echo "set scsi:scsi_hba_log_fcif=0" >> /etc/system
439 int scsi_hba_log_filter_level
=
442 char *scsi_hba_log_filter_phci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
443 char *scsi_hba_log_filter_vhci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
444 int scsi_hba_log_align
= 0; /* NOTE: will not cause truncation */
445 int scsi_hba_log_fcif
= '!'; /* "^!?" first char in format */
446 /* NOTE: iff level > SCSI_HBA_LOG1 */
447 /* '\0'0x00 -> console and system log */
448 /* '^' 0x5e -> console_only */
449 /* '!' 0x21 -> system log only */
450 /* '?' 0x2F -> See cmn_err(9F) */
451 int scsi_hba_log_info
= /* augmentation: extra info output */
452 (0 << 0) | /* 0x0001: process information */
453 (0 << 1) | /* 0x0002: full /devices path */
454 (0 << 2); /* 0x0004: devinfo pointer */
456 int scsi_hba_log_mt_disable
=
457 /* SCSI_ENUMERATION_MT_LUN_DISABLE | (ie 0x02) */
458 /* SCSI_ENUMERATION_MT_TARGET_DISABLE | (ie 0x04) */
461 /* static data for HBA logging subsystem */
462 static kmutex_t scsi_hba_log_mutex
;
463 static char scsi_hba_log_i
[512];
464 static char scsi_hba_log_buf
[512];
465 static char scsi_hba_fmt
[512];
467 /* Macros to use in scsi_hba.c source code below */
468 #define SCSI_HBA_LOG(x) scsi_hba_log x
469 #define _LOG(level) SCSI_HBA_LOG##level, __func__
470 #define _MAP(map) SCSI_HBA_LOGMAP##map, __func__
471 #define _LOG_NF(level) SCSI_HBA_LOG##level, NULL, NULL, NULL
472 #define _LOG_TRACE _LOG(TRACE)
473 #define _LOGLUN _MAP(LUN)
474 #define _LOGTGT _MAP(TGT)
475 #define _LOGIPT _MAP(IPT)
476 #define _LOGPHY _MAP(PHY)
477 #define _LOGCFG _MAP(CFG)
478 #define _LOGUNCFG _MAP(UNCFG)
482 scsi_hba_log(int level
, const char *func
, dev_info_t
*self
, dev_info_t
*child
,
483 const char *fmt
, ...)
492 /* derive self from child's parent */
493 if ((self
== NULL
) && child
)
494 self
= ddi_get_parent(child
);
496 /* no filtering of SCSI_HBA_LOG_CE_MASK or LOG_NF messages */
497 if (((level
& SCSI_HBA_LOG_CE_MASK
) != level
) && (func
!= NULL
)) {
498 /* scsi_hba_log_filter_level: filter on level as bitmask */
499 if ((level
& scsi_hba_log_filter_level
) == 0)
502 /* scsi_hba_log_filter_phci/vhci: on name of driver */
503 if (*scsi_hba_log_filter_phci
&&
505 (ddi_driver_name(self
) == NULL
) ||
506 strcmp(ddi_driver_name(self
), scsi_hba_log_filter_phci
))) {
507 /* does not match pHCI, check vHCI */
508 if (*scsi_hba_log_filter_vhci
&&
510 (ddi_driver_name(self
) == NULL
) ||
511 strcmp(ddi_driver_name(self
),
512 scsi_hba_log_filter_vhci
))) {
513 /* does not match vHCI */
519 /* passed filters, determine align */
520 align
= scsi_hba_log_align
;
522 /* shorten func for filtered output */
523 if (strncmp(func
, "scsi_hba_", 9) == 0)
525 if (strncmp(func
, "scsi_", 5) == 0)
528 /* don't align output that is never filtered */
532 /* determine the cmn_err form from the level */
533 clevel
= ((level
& SCSI_HBA_LOG_CE_MASK
) == level
) ? level
: CE_CONT
;
535 /* protect common buffers used to format output */
536 mutex_enter(&scsi_hba_log_mutex
);
538 /* skip special first characters, we add them back below */
540 if (*f
&& strchr("^!?", *f
))
543 (void) vsprintf(scsi_hba_log_buf
, f
, ap
);
546 /* augment message with 'information' */
547 info
= scsi_hba_log_i
;
549 if ((scsi_hba_log_info
& 0x0001) && curproc
&& PTOU(curproc
)->u_comm
) {
550 (void) sprintf(info
, "%s[%d]%p ",
551 PTOU(curproc
)->u_comm
, curproc
->p_pid
, (void *)curthread
);
552 info
+= strlen(info
);
555 if ((scsi_hba_log_info
& 0x0004) && (child
|| self
)) {
556 (void) sprintf(info
, "%p ",
557 (void *)(child
? child
: self
));
558 info
+= strlen(info
);
560 if (scsi_hba_log_info
& 0x0002) {
561 (void) ddi_pathname(child
? child
: self
, info
);
562 (void) strcat(info
, " ");
563 info
+= strlen(info
);
566 /* always provide 'default' information about self &child */
567 (void) sprintf(info
, "%s%d ", ddi_driver_name(self
),
568 ddi_get_instance(self
));
569 info
+= strlen(info
);
571 ua
= ddi_get_name_addr(child
);
572 (void) sprintf(info
, "%s@%s ",
573 ddi_node_name(child
), (ua
&& *ua
) ? ua
: "");
574 info
+= strlen(info
);
578 /* turn off alignment if truncation would occur */
579 if (align
&& ((strlen(func
) > 18) || (strlen(scsi_hba_log_i
) > 36)))
582 /* adjust for aligned output */
586 /* remove trailing blank with align output */
587 if ((info
!= scsi_hba_log_i
) && (*(info
-1) == '\b'))
591 /* special "first character in format" must be in format itself */
593 if (fmt
[0] && strchr("^!?", fmt
[0]))
595 else if (scsi_hba_log_fcif
&& (level
> SCSI_HBA_LOG1
))
596 *f
++ = (char)scsi_hba_log_fcif
; /* add global fcif */
598 (void) sprintf(f
, "%s", "%-18.18s: %36.36s: %s%s");
600 (void) sprintf(f
, "%s", func
? "%s: %s%s%s" : "%s%s%s");
603 cmn_err(clevel
, scsi_hba_fmt
, func
, scsi_hba_log_i
,
604 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
606 cmn_err(clevel
, scsi_hba_fmt
, scsi_hba_log_i
,
607 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
608 mutex_exit(&scsi_hba_log_mutex
);
611 int scsi_enumeration_failed_panic
= 0;
612 int scsi_enumeration_failed_hotplug
= 1;
615 scsi_enumeration_failed(dev_info_t
*child
, scsi_enum_t se
,
616 char *arg
, char *when
)
618 /* If 'se' is -1 the 'se' value comes from child. */
621 se
= ndi_dev_is_hotplug_node(child
) ? SE_HP
: SE_BUSCONFIG
;
624 if (scsi_enumeration_failed_panic
) {
625 /* set scsi_enumeration_failed_panic to debug */
626 SCSI_HBA_LOG((_LOG(PANIC
), NULL
, child
,
627 "%s%senumeration failed during %s",
628 arg
? arg
: "", arg
? " " : "", when
));
629 } else if (scsi_enumeration_failed_hotplug
&& (se
== SE_HP
)) {
630 /* set scsi_enumeration_failed_hotplug for console messages */
631 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
,
632 "%s%senumeration failed during %s",
633 arg
? arg
: "", arg
? " " : "", when
));
636 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
637 "%s%senumeration failed during %s",
638 arg
? arg
: "", arg
? " " : "", when
));
643 * scsi_hba version of [nm]di_devi_enter/[nm]di_devi_exit that detects if HBA
644 * is a PHCI, and chooses mdi/ndi locking implementation.
647 scsi_hba_devi_enter(dev_info_t
*self
, int *circp
)
650 mdi_devi_enter(self
, circp
);
652 ndi_devi_enter(self
, circp
);
656 scsi_hba_devi_tryenter(dev_info_t
*self
, int *circp
)
659 return (mdi_devi_tryenter(self
, circp
));
661 return (ndi_devi_tryenter(self
, circp
));
665 scsi_hba_devi_exit(dev_info_t
*self
, int circ
)
668 mdi_devi_exit(self
, circ
);
670 ndi_devi_exit(self
, circ
);
674 scsi_hba_devi_enter_phci(dev_info_t
*self
, int *circp
)
677 mdi_devi_enter_phci(self
, circp
);
681 scsi_hba_devi_exit_phci(dev_info_t
*self
, int circ
)
684 mdi_devi_exit_phci(self
, circ
);
688 scsi_hba_dev_is_sid(dev_info_t
*child
)
691 * Use ndi_dev_is_persistent_node instead of ddi_dev_is_sid to avoid
692 * any possible locking issues in mixed nexus devctl code (like usb).
694 return (ndi_dev_is_persistent_node(child
));
698 * Called from _init() when loading "scsi" module
701 scsi_initialize_hba_interface()
703 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
705 /* We need "scsiprobe" and "scsinodev" as an alias or a driver. */
706 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
) {
707 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
708 "driver alias, defaulting to 'nulldriver'",
711 /* If no "nulldriver" driver nothing will work... */
712 compatible_probe
= "nulldriver";
713 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
)
714 SCSI_HBA_LOG((_LOG_NF(WARN
), "no probe '%s' driver, "
715 "system misconfigured", compatible_probe
));
717 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
) {
718 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
719 "driver alias, defaulting to 'nulldriver'",
722 /* If no "nulldriver" driver nothing will work... */
723 compatible_nodev
= "nulldriver";
724 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
)
725 SCSI_HBA_LOG((_LOG_NF(WARN
), "no nodev '%s' driver, "
726 "system misconfigured", compatible_nodev
));
730 * Verify our special node name "probe" will not be used in other ways.
731 * Don't expect things to work if they are.
733 if (ddi_major_to_name(ddi_name_to_major("probe")))
734 SCSI_HBA_LOG((_LOG_NF(WARN
),
735 "driver already using special node name 'probe'"));
737 mutex_init(&scsi_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
738 mutex_init(&scsi_flag_nointr_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
739 cv_init(&scsi_flag_nointr_cv
, NULL
, CV_DRIVER
, NULL
);
740 mutex_init(&scsi_hba_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
742 /* initialize the asynchronous barrier deletion daemon */
743 mutex_init(&scsi_hba_barrier_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
744 cv_init(&scsi_hba_barrier_cv
, NULL
, CV_DRIVER
, NULL
);
745 (void) thread_create(NULL
, 0,
746 (void (*)())scsi_hba_barrier_daemon
, NULL
,
747 0, &p0
, TS_RUN
, minclsyspri
);
749 /* initialize lun change ASC/ASCQ processing daemon (stage1 & stage2) */
750 mutex_init(&scsi_lunchg1_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
751 cv_init(&scsi_lunchg1_cv
, NULL
, CV_DRIVER
, NULL
);
752 (void) thread_create(NULL
, 0,
753 (void (*)())scsi_lunchg1_daemon
, NULL
,
754 0, &p0
, TS_RUN
, minclsyspri
);
755 mutex_init(&scsi_lunchg2_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
756 cv_init(&scsi_lunchg2_cv
, NULL
, CV_DRIVER
, NULL
);
757 (void) thread_create(NULL
, 0,
758 (void (*)())scsi_lunchg2_daemon
, NULL
,
759 0, &p0
, TS_RUN
, minclsyspri
);
763 scsi_hba_pkt_constructor(void *buf
, void *arg
, int kmflag
)
765 struct scsi_pkt_cache_wrapper
*pktw
;
766 struct scsi_pkt
*pkt
;
767 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
772 * allocate a chunk of memory for the following:
776 * pkt_cdbp, if needed
777 * (pkt_private always null)
778 * pkt_scbp, if needed
780 pkt_len
= tran
->tran_hba_len
+ sizeof (struct scsi_pkt_cache_wrapper
);
781 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
782 pkt_len
+= DEFAULT_CDBLEN
;
783 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
784 pkt_len
+= DEFAULT_SCBLEN
;
789 ptr
+= sizeof (struct scsi_pkt_cache_wrapper
);
790 pkt
= &(pktw
->pcw_pkt
);
791 pkt
->pkt_ha_private
= (opaque_t
)ptr
;
793 pktw
->pcw_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
795 * keep track of the granularity at the time this handle was
798 pktw
->pcw_granular
= tran
->tran_dma_attr
.dma_attr_granular
;
800 if (ddi_dma_alloc_handle(tran
->tran_hba_dip
, &tran
->tran_dma_attr
,
801 kmflag
== KM_SLEEP
? SLEEP_FUNC
: NULL_FUNC
, NULL
,
802 &pkt
->pkt_handle
) != DDI_SUCCESS
) {
806 ptr
+= tran
->tran_hba_len
;
807 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) {
808 pkt
->pkt_cdbp
= (opaque_t
)ptr
;
809 ptr
+= DEFAULT_CDBLEN
;
811 pkt
->pkt_private
= NULL
;
812 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
813 pkt
->pkt_scbp
= (opaque_t
)ptr
;
814 if (tran
->tran_pkt_constructor
)
815 return ((*tran
->tran_pkt_constructor
)(pkt
, arg
, kmflag
));
820 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
823 scsi_hba_pkt_destructor(void *buf
, void *arg
)
825 struct scsi_pkt_cache_wrapper
*pktw
= buf
;
826 struct scsi_pkt
*pkt
= &(pktw
->pcw_pkt
);
827 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
829 ASSERT(pktw
->pcw_magic
== PKT_WRAPPER_MAGIC
);
830 ASSERT((pktw
->pcw_flags
& PCW_BOUND
) == 0);
831 if (tran
->tran_pkt_destructor
)
832 (*tran
->tran_pkt_destructor
)(pkt
, arg
);
834 /* make sure nobody messed with our pointers */
835 ASSERT(pkt
->pkt_ha_private
== (opaque_t
)((char *)pkt
+
836 sizeof (struct scsi_pkt_cache_wrapper
)));
837 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
) == 0) ||
838 (pkt
->pkt_scbp
== (opaque_t
)((char *)pkt
+
840 (((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ?
841 0 : DEFAULT_CDBLEN
) +
842 DEFAULT_PRIVLEN
+ sizeof (struct scsi_pkt_cache_wrapper
))));
843 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ||
844 (pkt
->pkt_cdbp
== (opaque_t
)((char *)pkt
+
846 sizeof (struct scsi_pkt_cache_wrapper
))));
847 ASSERT(pkt
->pkt_handle
);
848 ddi_dma_free_handle(&pkt
->pkt_handle
);
849 pkt
->pkt_handle
= NULL
;
850 pkt
->pkt_numcookies
= 0;
851 pktw
->pcw_total_xfer
= 0;
852 pktw
->pcw_totalwin
= 0;
853 pktw
->pcw_curwin
= 0;
857 * Called by an HBA from _init() to plumb in common SCSA bus_ops and
858 * cb_ops for the HBA's :devctl and :scsi minor nodes.
861 scsi_hba_init(struct modlinkage
*modlp
)
863 struct dev_ops
*hba_dev_ops
;
865 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
868 * Get a pointer to the dev_ops structure of the HBA and plumb our
869 * bus_ops vector into the HBA's dev_ops structure.
871 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
872 ASSERT(hba_dev_ops
->devo_bus_ops
== NULL
);
873 hba_dev_ops
->devo_bus_ops
= &scsi_hba_busops
;
876 * Plumb our cb_ops vector into the HBA's dev_ops structure to
877 * provide getinfo and hotplugging ioctl support if the HBA driver
878 * does not already provide this support.
880 if (hba_dev_ops
->devo_cb_ops
== NULL
) {
881 hba_dev_ops
->devo_cb_ops
= &scsi_hba_cbops
;
883 if (hba_dev_ops
->devo_cb_ops
->cb_open
== scsi_hba_open
) {
884 ASSERT(hba_dev_ops
->devo_cb_ops
->cb_close
== scsi_hba_close
);
885 hba_dev_ops
->devo_getinfo
= scsi_hba_info
;
891 * Called by an HBA attach(9E) to allocate a scsi_hba_tran(9S) structure. An
892 * HBA driver will then initialize the structure and then call
893 * scsi_hba_attach_setup(9F).
901 scsi_hba_tran_t
*tran
;
903 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
905 /* allocate SCSA flavors for self */
906 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
908 tran
= kmem_zalloc(sizeof (scsi_hba_tran_t
),
909 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
912 tran
->tran_interconnect_type
= INTERCONNECT_PARALLEL
;
915 * HBA driver called scsi_hba_tran_alloc(), so tran structure
916 * is proper size and unused/newer fields are zero.
918 * NOTE: We use SCSA_HBA_SCSA_TA as an obtuse form of
919 * versioning to detect old HBA drivers that do not use
920 * scsi_hba_tran_alloc, and would present garbage data
921 * (instead of valid/zero data) for newer tran fields.
923 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
;
930 * Called by an HBA to free a scsi_hba_tran structure
934 scsi_hba_tran_t
*tran
)
936 SCSI_HBA_LOG((_LOG_TRACE
, tran
->tran_hba_dip
, NULL
, __func__
));
938 kmem_free(tran
, sizeof (scsi_hba_tran_t
));
943 scsi_hba_tran_t
*tran
,
948 int ret
= DDI_FAILURE
;
950 tran_ext
= kmem_zalloc(length
,
951 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
952 if (tran_ext
!= NULL
) {
953 tran
->tran_extension
= tran_ext
;
961 scsi_hba_tran_t
*tran
,
964 if (tran
->tran_extension
!= NULL
) {
965 kmem_free(tran
->tran_extension
, length
);
966 tran
->tran_extension
= NULL
;
971 * Common nexus teardown code: used by both scsi_hba_detach() on SCSA HBA node
972 * and iport_postdetach_tran_scsi_device() on a SCSA HBA iport node (and for
973 * failure cleanup). Undo scsa_nexus_setup in reverse order.
975 * NOTE: Since we are in the Solaris IO framework, we can depend on
976 * undocumented cleanup operations performed by other parts of the framework:
977 * like detach_node() calling ddi_prop_remove_all() and
978 * ddi_remove_minor_node(,NULL).
981 scsa_nexus_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
984 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_FM
) {
986 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_FM
;
991 * Common nexus setup code: used by both scsi_hba_attach_setup() on SCSA HBA
992 * node and iport_preattach_tran_scsi_device() on a SCSA HBA iport node.
994 * This code makes no assumptions about tran use by scsi_device children.
997 scsa_nexus_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1003 * NOTE: SCSA maintains an 'fm-capable' domain, in tran_fm_capable,
1004 * that is not dependent (limited by) the capabilities of its parents.
1005 * For example a devinfo node in a branch that is not
1006 * DDI_FM_EREPORT_CAPABLE may report as capable, via tran_fm_capable,
1007 * to its scsi_device children.
1009 * Get 'fm-capable' property from driver.conf, if present. If not
1010 * present, default to the scsi_fm_capable global (which has
1011 * DDI_FM_EREPORT_CAPABLE set by default).
1013 if (tran
->tran_fm_capable
== DDI_FM_NOT_CAPABLE
)
1014 tran
->tran_fm_capable
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
1015 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1016 "fm-capable", scsi_fm_capable
);
1019 * If an HBA is *not* doing its own fma support by calling
1020 * ddi_fm_init() prior to scsi_hba_attach_setup(), we provide a minimal
1021 * common SCSA implementation so that scsi_device children can generate
1022 * ereports via scsi_fm_ereport_post(). We use ddi_fm_capable() to
1023 * detect an HBA calling ddi_fm_init() prior to scsi_hba_attach_setup().
1025 if (tran
->tran_fm_capable
&&
1026 (ddi_fm_capable(self
) == DDI_FM_NOT_CAPABLE
)) {
1028 * We are capable of something, pass our capabilities up the
1029 * tree, but use a local variable so our parent can't limit
1030 * our capabilities (we don't want our parent to clear
1031 * DDI_FM_EREPORT_CAPABLE).
1033 * NOTE: iblock cookies are not important because scsi HBAs
1034 * always interrupt below LOCK_LEVEL.
1036 capable
= tran
->tran_fm_capable
;
1037 ddi_fm_init(self
, &capable
, NULL
);
1040 * Set SCSI_HBA_SCSA_FM bit to mark us as using the common
1041 * minimal SCSA fm implementation - we called ddi_fm_init(),
1042 * so we are responsible for calling ddi_fm_fini() in
1043 * scsi_hba_detach().
1045 * NOTE: if ddi_fm_init fails to establish handle, SKIP cleanup.
1047 if (DEVI(self
)->devi_fmhdl
)
1048 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_FM
;
1051 /* If SCSA responsible for for minor nodes, create :devctl minor. */
1052 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1053 scsi_hba_open
) ? 1 : 0;
1054 if (scsa_minor
&& ((ddi_create_minor_node(self
, "devctl", S_IFCHR
,
1055 INST2DEVCTL(ddi_get_instance(self
)), DDI_NT_SCSI_NEXUS
, 0) !=
1057 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1058 "can't create :devctl minor node"));
1062 return (DDI_SUCCESS
);
1064 fail
: scsa_nexus_teardown(self
, tran
);
1065 return (DDI_FAILURE
);
1069 * Common tran teardown code: used by iport_postdetach_tran_scsi_device() on a
1070 * SCSA HBA iport node and (possibly) by scsi_hba_detach() on SCSA HBA node
1071 * (and for failure cleanup). Undo scsa_tran_setup in reverse order.
1073 * NOTE: Since we are in the Solaris IO framework, we can depend on
1074 * undocumented cleanup operations performed by other parts of the framework:
1075 * like detach_node() calling ddi_prop_remove_all() and
1076 * ddi_remove_minor_node(,NULL).
1079 scsa_tran_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1081 tran
->tran_iport_dip
= NULL
;
1083 /* Teardown pHCI registration */
1084 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_PHCI
) {
1085 (void) mdi_phci_unregister(self
, 0);
1086 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_PHCI
;
1091 * Common tran setup code: used by iport_preattach_tran_scsi_device() on a
1092 * SCSA HBA iport node and (possibly) by scsi_hba_attach_setup() on SCSA HBA
1096 scsa_tran_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1100 char *scsi_binding_set
;
1101 static const char *interconnect
[] = INTERCONNECT_TYPE_ASCII
;
1103 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1105 /* If SCSA responsible for for minor nodes, create ":scsi" */
1106 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1107 scsi_hba_open
) ? 1 : 0;
1108 if (scsa_minor
&& (ddi_create_minor_node(self
, "scsi", S_IFCHR
,
1109 INST2SCSI(ddi_get_instance(self
)),
1110 DDI_NT_SCSI_ATTACHMENT_POINT
, 0) != DDI_SUCCESS
)) {
1111 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1112 "can't create :scsi minor node"));
1117 * If the property does not already exist on self then see if we can
1118 * pull it from further up the tree and define it on self. If the
1119 * property does not exist above (including options.conf) then use the
1120 * default value specified (global variable). We pull things down from
1121 * above for faster "DDI_PROP_NOTPROM | DDI_PROP_DONTPASS" runtime
1124 * Future: Should we avoid creating properties when value == global?
1126 #define CONFIG_INT_PROP(s, p, dv) { \
1127 if ((ddi_prop_exists(DDI_DEV_T_ANY, s, \
1128 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, p) == 0) && \
1129 (ndi_prop_update_int(DDI_DEV_T_NONE, s, p, \
1130 ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(s), \
1131 DDI_PROP_NOTPROM, p, dv)) != DDI_PROP_SUCCESS)) \
1132 SCSI_HBA_LOG((_LOG(WARN), NULL, s, \
1133 "can't create property '%s'", p)); \
1136 /* Decorate with scsi configuration properties */
1137 CONFIG_INT_PROP(self
, "scsi-enumeration", scsi_enumeration
);
1138 CONFIG_INT_PROP(self
, "scsi-options", scsi_options
);
1139 CONFIG_INT_PROP(self
, "scsi-reset-delay", scsi_reset_delay
);
1140 CONFIG_INT_PROP(self
, "scsi-watchdog-tick", scsi_watchdog_tick
);
1141 CONFIG_INT_PROP(self
, "scsi-selection-timeout", scsi_selection_timeout
);
1142 CONFIG_INT_PROP(self
, "scsi-tag-age-limit", scsi_tag_age_limit
);
1145 * Pull down the scsi-initiator-id from further up the tree, or as
1146 * defined by OBP. Place on node for faster access. NOTE: there is
1147 * some confusion about what the name of the property should be.
1149 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0, "initiator-id", -1);
1151 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0,
1152 "scsi-initiator-id", -1);
1154 CONFIG_INT_PROP(self
, "scsi-initiator-id", id
);
1157 * If we are responsible for tran allocation, establish
1158 * 'initiator-interconnect-type'.
1160 if ((tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
) &&
1161 (tran
->tran_interconnect_type
> 0) &&
1162 (tran
->tran_interconnect_type
< INTERCONNECT_MAX
)) {
1163 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1164 "initiator-interconnect-type",
1165 (char *)interconnect
[tran
->tran_interconnect_type
])
1166 != DDI_PROP_SUCCESS
) {
1167 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1168 "failed to establish "
1169 "'initiator-interconnect-type'"));
1175 * The 'scsi-binding-set' property can be defined in driver.conf
1176 * files of legacy drivers on an as-needed basis. If 'scsi-binding-set'
1177 * is not driver.conf defined, and the HBA is not implementing its own
1178 * private bus_config, we define scsi-binding-set to the default
1179 * 'spi' legacy value.
1181 * NOTE: This default 'spi' value will be deleted if an HBA driver
1182 * ends up using the scsi_hba_tgtmap_create() enumeration services.
1184 * NOTE: If we were ever to decide to derive 'scsi-binding-set' from
1185 * the IEEE-1275 'device_type' property then this is where that code
1186 * should go - there is not enough consistency in 'device_type' to do
1187 * this correctly at this point in time.
1189 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
1190 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
1191 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
1192 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1193 "external 'scsi-binding-set' \"%s\"", scsi_binding_set
));
1194 ddi_prop_free(scsi_binding_set
);
1195 } else if (scsi_binding_set_spi
&&
1196 ((tran
->tran_bus_config
== NULL
) ||
1197 (tran
->tran_bus_config
== scsi_hba_bus_config_spi
))) {
1198 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1199 "scsi-binding-set", scsi_binding_set_spi
) !=
1201 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1202 "failed to establish 'scsi_binding_set' default"));
1205 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1206 "default 'scsi-binding-set' \"%s\"", scsi_binding_set_spi
));
1208 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1209 "no 'scsi-binding-set'"));
1212 * If SCSI_HBA_TRAN_PHCI is set, take care of pHCI registration of the
1215 if ((tran
->tran_hba_flags
& SCSI_HBA_TRAN_PHCI
) &&
1216 (mdi_phci_register(MDI_HCI_CLASS_SCSI
, self
, 0) == MDI_SUCCESS
))
1217 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_PHCI
;
1219 /* NOTE: tran_hba_dip is for DMA operation at the HBA node level */
1220 tran
->tran_iport_dip
= self
; /* for iport association */
1221 return (DDI_SUCCESS
);
1223 fail
: scsa_tran_teardown(self
, tran
);
1224 return (DDI_FAILURE
);
1228 * Called by a SCSA HBA driver to attach an instance of the driver to
1229 * SCSA HBA node enumerated by PCI.
1232 scsi_hba_attach_setup(
1234 ddi_dma_attr_t
*hba_dma_attr
,
1235 scsi_hba_tran_t
*tran
,
1239 char cache_name
[96];
1241 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1244 * Verify that we are a driver so other code does not need to
1245 * check for NULL ddi_get_driver() result.
1247 if (ddi_get_driver(self
) == NULL
)
1248 return (DDI_FAILURE
);
1251 * Verify that we are called on a SCSA HBA node (function enumerated
1252 * by PCI), not on an iport node.
1254 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1255 if (scsi_hba_iport_unit_address(self
))
1256 return (DDI_FAILURE
); /* self can't be an iport */
1258 /* Caller must provide the tran. */
1261 return (DDI_FAILURE
);
1264 * Verify correct scsi_hba_tran_t form:
1266 * o Both or none of tran_get_name/tran_get_addr.
1267 * NOTE: Older SCSA HBA drivers for SCSI transports with addressing
1268 * that did not fit the SPI "struct scsi_address" model were required
1269 * to implement tran_get_name and tran_get_addr. This is no longer
1270 * true - modern transport drivers should now use common SCSA
1271 * enumeration services. The SCSA enumeration code will represent
1272 * the unit-address using well-known address properties
1273 * (SCSI_ADDR_PROP_TARGET_PORT, SCSI_ADDR_PROP_LUN64) during
1274 * devinfo/pathinfo node creation. The HBA driver can obtain values
1275 * using scsi_device_prop_lookup_*() from its tran_tgt_init(9E).
1278 if ((tran
->tran_get_name
== NULL
) ^ (tran
->tran_get_bus_addr
== NULL
)) {
1279 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1280 "should support both or neither: "
1281 "tran_get_name, tran_get_bus_addr"));
1282 return (DDI_FAILURE
);
1286 * Establish the devinfo context of this tran structure, preserving
1287 * knowledge of how the tran was allocated.
1289 tran
->tran_hba_dip
= self
; /* for DMA */
1290 tran
->tran_hba_flags
= (flags
& ~SCSI_HBA_SCSA_TA
) |
1291 (tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
);
1293 /* Establish flavor of transport (and ddi_get_driver_private()) */
1294 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
1297 * Note: We only need dma_attr_minxfer and dma_attr_burstsizes
1298 * from the DMA attributes. scsi_hba_attach(9f) only guarantees
1299 * that these two fields are initialized properly. If this
1300 * changes, be sure to revisit the implementation of
1301 * scsi_hba_attach(9F).
1303 (void) memcpy(&tran
->tran_dma_attr
, hba_dma_attr
,
1304 sizeof (ddi_dma_attr_t
));
1306 /* Create tran_setup_pkt(9E) kmem_cache. */
1307 if (tran
->tran_setup_pkt
) {
1308 ASSERT(tran
->tran_init_pkt
== NULL
);
1309 ASSERT(tran
->tran_destroy_pkt
== NULL
);
1310 if (tran
->tran_init_pkt
|| tran
->tran_destroy_pkt
)
1313 tran
->tran_init_pkt
= scsi_init_cache_pkt
;
1314 tran
->tran_destroy_pkt
= scsi_free_cache_pkt
;
1315 tran
->tran_sync_pkt
= scsi_sync_cache_pkt
;
1316 tran
->tran_dmafree
= scsi_cache_dmafree
;
1318 len
= sizeof (struct scsi_pkt_cache_wrapper
);
1319 len
+= ROUNDUP(tran
->tran_hba_len
);
1320 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
1321 len
+= ROUNDUP(DEFAULT_CDBLEN
);
1322 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
1323 len
+= ROUNDUP(DEFAULT_SCBLEN
);
1325 (void) snprintf(cache_name
, sizeof (cache_name
),
1326 "pkt_cache_%s_%d", ddi_driver_name(self
),
1327 ddi_get_instance(self
));
1329 tran
->tran_pkt_cache_ptr
= kmem_cache_create(
1330 cache_name
, len
, 8, scsi_hba_pkt_constructor
,
1331 scsi_hba_pkt_destructor
, NULL
, tran
, NULL
, 0);
1334 /* Perform node setup independent of initiator role */
1335 if (scsa_nexus_setup(self
, tran
) != DDI_SUCCESS
)
1339 * The SCSI_HBA_HBA flag is passed to scsi_hba_attach_setup when the
1340 * HBA driver knows that *all* children of the SCSA HBA node will be
1341 * 'iports'. If the SCSA HBA node can have iport children and also
1342 * function as an initiator for xxx_device children then it should
1343 * not specify SCSI_HBA_HBA in its scsi_hba_attach_setup call. An
1344 * HBA driver that does not manage iports should not set SCSA_HBA_HBA.
1346 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
1348 * Set the 'ddi-config-driver-node' property on the nexus
1349 * node that notify attach_driver_nodes() to configure all
1350 * immediate children so that nodes which bind to the
1351 * same driver as parent are able to be added into per-driver
1354 if (ndi_prop_create_boolean(DDI_DEV_T_NONE
,
1355 self
, "ddi-config-driver-node") != DDI_PROP_SUCCESS
)
1358 if (scsa_tran_setup(self
, tran
) != DDI_SUCCESS
)
1362 return (DDI_SUCCESS
);
1364 fail
: (void) scsi_hba_detach(self
);
1365 return (DDI_FAILURE
);
1369 * Called by an HBA to detach an instance of the driver. This may be called
1370 * for SCSA HBA nodes and for SCSA iport nodes.
1373 scsi_hba_detach(dev_info_t
*self
)
1375 scsi_hba_tran_t
*tran
;
1377 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1378 if (scsi_hba_iport_unit_address(self
))
1379 return (DDI_FAILURE
); /* self can't be an iport */
1381 /* Check all error return conditions upfront */
1382 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1385 return (DDI_FAILURE
);
1387 ASSERT(tran
->tran_open_flag
== 0);
1388 if (tran
->tran_open_flag
)
1389 return (DDI_FAILURE
);
1391 if (!(tran
->tran_hba_flags
& SCSI_HBA_HBA
))
1392 scsa_tran_teardown(self
, tran
);
1393 scsa_nexus_teardown(self
, tran
);
1395 /* Teardown tran_setup_pkt(9E) kmem_cache. */
1396 if (tran
->tran_pkt_cache_ptr
) {
1397 kmem_cache_destroy(tran
->tran_pkt_cache_ptr
);
1398 tran
->tran_pkt_cache_ptr
= NULL
;
1401 (void) memset(&tran
->tran_dma_attr
, 0, sizeof (ddi_dma_attr_t
));
1403 /* Teardown flavor of transport (and ddi_get_driver_private()) */
1404 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
1406 tran
->tran_hba_dip
= NULL
;
1408 return (DDI_SUCCESS
);
1413 * Called by an HBA from _fini()
1416 scsi_hba_fini(struct modlinkage
*modlp
)
1418 struct dev_ops
*hba_dev_ops
;
1420 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
1422 /* Get the devops structure of this module and clear bus_ops vector. */
1423 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
1425 if (hba_dev_ops
->devo_cb_ops
== &scsi_hba_cbops
)
1426 hba_dev_ops
->devo_cb_ops
= NULL
;
1428 if (hba_dev_ops
->devo_getinfo
== scsi_hba_info
)
1429 hba_dev_ops
->devo_getinfo
= NULL
;
1431 hba_dev_ops
->devo_bus_ops
= NULL
;
1435 * SAS specific functions
1438 smp_hba_tran_alloc(dev_info_t
*self
)
1440 /* allocate SCSA flavors for self */
1441 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
1442 return (kmem_zalloc(sizeof (smp_hba_tran_t
), KM_SLEEP
));
1446 smp_hba_tran_free(smp_hba_tran_t
*tran
)
1448 kmem_free(tran
, sizeof (smp_hba_tran_t
));
1452 smp_hba_attach_setup(
1454 smp_hba_tran_t
*tran
)
1456 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1457 if (scsi_hba_iport_unit_address(self
))
1458 return (DDI_FAILURE
); /* self can't be an iport */
1461 * The owner of the this devinfo_t was responsible
1462 * for informing the framework already about
1463 * additional flavors.
1465 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, tran
);
1466 return (DDI_SUCCESS
);
1470 smp_hba_detach(dev_info_t
*self
)
1472 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1473 if (scsi_hba_iport_unit_address(self
))
1474 return (DDI_FAILURE
); /* self can't be an iport */
1476 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, NULL
);
1477 return (DDI_SUCCESS
);
1481 * SMP child flavored functions
1484 smp_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1489 /* limit ndi_devi_findchild_by_callback to expected flavor */
1490 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1491 return (DDI_FAILURE
);
1493 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1494 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1495 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1496 (void) snprintf(addr
, maxlen
, "%s", tport
);
1497 ddi_prop_free(tport
);
1498 return (DDI_SUCCESS
);
1502 * NOTE: the following code should be deleted when mpt is changed to
1503 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1505 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1506 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1507 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1508 (void) snprintf(addr
, maxlen
, "w%s", wwn
);
1510 return (DDI_SUCCESS
);
1512 return (DDI_FAILURE
);
1516 smp_busctl_reportdev(dev_info_t
*child
)
1518 dev_info_t
*self
= ddi_get_parent(child
);
1522 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1523 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1524 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1525 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: target-port %s",
1526 ddi_driver_name(child
), ddi_get_instance(child
),
1527 ddi_driver_name(self
), ddi_get_instance(self
), tport
));
1528 ddi_prop_free(tport
);
1529 return (DDI_SUCCESS
);
1533 * NOTE: the following code should be deleted when mpt is changed to
1534 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1536 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1537 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1538 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1539 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: wwn %s",
1540 ddi_driver_name(child
), ddi_get_instance(child
),
1541 ddi_driver_name(self
), ddi_get_instance(self
), wwn
));
1543 return (DDI_SUCCESS
);
1545 return (DDI_FAILURE
);
1549 smp_busctl_initchild(dev_info_t
*child
)
1551 dev_info_t
*self
= ddi_get_parent(child
);
1552 smp_hba_tran_t
*tran
;
1554 char addr
[SCSI_MAXNAMELEN
];
1555 struct smp_device
*smp_sd
;
1558 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1561 return (DDI_FAILURE
);
1563 if (smp_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
1564 return (DDI_NOT_WELL_FORMED
);
1565 if (scsi_wwnstr_to_wwn(addr
, &wwn
))
1566 return (DDI_NOT_WELL_FORMED
);
1568 /* Prevent duplicate nodes. */
1569 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
1572 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SMP
);
1573 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SMP
) {
1574 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1575 "init failed: %s@%s: not SMP flavored",
1576 ddi_node_name(child
), addr
));
1577 return (DDI_FAILURE
);
1580 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1581 "init failed: %s@%s: detected duplicate %p",
1582 ddi_node_name(child
), addr
, (void *)dup
));
1583 return (DDI_FAILURE
);
1588 /* set the node @addr string */
1589 ddi_set_name_addr(child
, addr
);
1591 /* Allocate and initialize smp_device. */
1592 smp_sd
= kmem_zalloc(sizeof (struct smp_device
), KM_SLEEP
);
1593 smp_sd
->smp_sd_dev
= child
;
1594 smp_sd
->smp_sd_address
.smp_a_hba_tran
= tran
;
1595 bcopy(&wwn
, smp_sd
->smp_sd_address
.smp_a_wwn
, SAS_WWN_BYTE_SIZE
);
1597 ddi_set_driver_private(child
, smp_sd
);
1599 if (tran
->smp_tran_init
&& ((*tran
->smp_tran_init
)(self
, child
,
1600 tran
, smp_sd
) != DDI_SUCCESS
)) {
1601 kmem_free(smp_sd
, sizeof (struct smp_device
));
1602 scsi_enumeration_failed(child
, -1, NULL
, "smp_tran_init");
1603 ddi_set_driver_private(child
, NULL
);
1604 ddi_set_name_addr(child
, NULL
);
1605 return (DDI_FAILURE
);
1608 return (DDI_SUCCESS
);
1613 smp_busctl_uninitchild(dev_info_t
*child
)
1615 dev_info_t
*self
= ddi_get_parent(child
);
1616 struct smp_device
*smp_sd
= ddi_get_driver_private(child
);
1617 smp_hba_tran_t
*tran
;
1619 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1620 ASSERT(smp_sd
&& tran
);
1621 if ((smp_sd
== NULL
) || (tran
== NULL
))
1622 return (DDI_FAILURE
);
1624 if (tran
->smp_tran_free
)
1625 (*tran
->smp_tran_free
) (self
, child
, tran
, smp_sd
);
1627 kmem_free(smp_sd
, sizeof (*smp_sd
));
1628 ddi_set_driver_private(child
, NULL
);
1629 ddi_set_name_addr(child
, NULL
);
1630 return (DDI_SUCCESS
);
1633 /* Find an "smp" child at the specified address. */
1635 smp_findchild(dev_info_t
*self
, char *addr
)
1639 /* Search "smp" devinfo child at specified address. */
1640 ASSERT(self
&& DEVI_BUSY_OWNED(self
) && addr
);
1641 for (child
= ddi_get_child(self
); child
;
1642 child
= ddi_get_next_sibling(child
)) {
1643 /* skip non-"smp" nodes */
1644 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1647 /* Attempt initchild to establish unit-address */
1648 if (i_ddi_node_state(child
) < DS_INITIALIZED
)
1649 (void) ddi_initchild(self
, child
);
1651 /* Verify state and non-NULL unit-address. */
1652 if ((i_ddi_node_state(child
) < DS_INITIALIZED
) ||
1653 (ddi_get_name_addr(child
) == NULL
))
1656 /* Return "smp" child if unit-address matches. */
1657 if (strcmp(ddi_get_name_addr(child
), addr
) == 0)
1664 * Search for "smp" child of self at the specified address. If found, online
1665 * and return with a hold. Unlike general SCSI configuration, we can assume
1666 * the the device is actually there when we are called (i.e., device is
1667 * created by hotplug, not by bus_config).
1670 smp_hba_bus_config(dev_info_t
*self
, char *addr
, dev_info_t
**childp
)
1675 ASSERT(self
&& addr
&& childp
);
1678 /* Search for "smp" child. */
1679 scsi_hba_devi_enter(self
, &circ
);
1680 if ((child
= smp_findchild(self
, addr
)) == NULL
) {
1681 scsi_hba_devi_exit(self
, circ
);
1682 return (NDI_FAILURE
);
1685 /* Attempt online. */
1686 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
1687 scsi_hba_devi_exit(self
, circ
);
1688 return (NDI_FAILURE
);
1691 /* On success, return with active hold. */
1692 ndi_hold_devi(child
);
1693 scsi_hba_devi_exit(self
, circ
);
1695 return (NDI_SUCCESS
);
1700 /* Create "smp" child devinfo node at specified unit-address. */
1702 smp_hba_bus_config_taddr(dev_info_t
*self
, char *addr
)
1708 * NOTE: If we ever uses a generic node name (.vs. a driver name)
1709 * or define a 'compatible' property, this code will need to use
1710 * a 'probe' node (ala scsi_device support) to obtain identity
1711 * information from the device.
1714 /* Search for "smp" child. */
1715 scsi_hba_devi_enter(self
, &circ
);
1716 child
= smp_findchild(self
, addr
);
1718 /* Child exists, note if this was a new reinsert. */
1719 if (ndi_devi_device_insert(child
))
1720 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
1721 "devinfo smp@%s device_reinsert", addr
));
1723 scsi_hba_devi_exit(self
, circ
);
1724 return (NDI_SUCCESS
);
1727 /* Allocate "smp" child devinfo node and establish flavor of child. */
1728 ndi_devi_alloc_sleep(self
, "smp", DEVI_SID_HP_NODEID
, &child
);
1730 ndi_flavor_set(child
, SCSA_FLAVOR_SMP
);
1732 /* Add unit-address property to child. */
1733 if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
1734 SCSI_ADDR_PROP_TARGET_PORT
, addr
) != DDI_PROP_SUCCESS
) {
1735 (void) ndi_devi_free(child
);
1736 scsi_hba_devi_exit(self
, circ
);
1737 return (NDI_FAILURE
);
1740 /* Attempt to online the new "smp" node. */
1741 (void) ndi_devi_online(child
, 0);
1743 scsi_hba_devi_exit(self
, circ
);
1744 return (NDI_SUCCESS
);
1748 * Wrapper to scsi_ua_get which takes a devinfo argument instead of a
1749 * scsi_device structure.
1752 scsi_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1754 struct scsi_device
*sd
;
1756 /* limit ndi_devi_findchild_by_callback to expected flavor */
1757 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
)
1758 return (DDI_FAILURE
);
1760 /* nodes are named by tran_get_name or default "tgt,lun" */
1761 sd
= ddi_get_driver_private(child
);
1762 if (sd
&& (scsi_ua_get(sd
, addr
, maxlen
) == 1))
1763 return (DDI_SUCCESS
);
1765 return (DDI_FAILURE
);
1769 scsi_busctl_reportdev(dev_info_t
*child
)
1771 dev_info_t
*self
= ddi_get_parent(child
);
1772 struct scsi_device
*sd
= ddi_get_driver_private(child
);
1773 scsi_hba_tran_t
*tran
;
1774 char ua
[SCSI_MAXNAMELEN
];
1775 char ra
[SCSI_MAXNAMELEN
];
1777 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, child
, __func__
));
1779 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1781 if ((tran
== NULL
) || (sd
== NULL
))
1782 return (DDI_FAILURE
);
1784 /* get the unit_address and bus_addr information */
1785 if ((scsi_ua_get(sd
, ua
, sizeof (ua
)) == 0) ||
1786 (scsi_ua_get_reportdev(sd
, ra
, sizeof (ra
)) == 0)) {
1787 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
, "REPORTDEV failure"));
1788 return (DDI_FAILURE
);
1791 if (tran
->tran_get_name
== NULL
)
1792 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s",
1793 ddi_driver_name(child
), ddi_get_instance(child
),
1794 ddi_driver_name(self
), ddi_get_instance(self
), ra
));
1796 SCSI_HBA_LOG((_LOG_NF(CONT
),
1797 "?%s%d at %s%d: unit-address %s: %s",
1798 ddi_driver_name(child
), ddi_get_instance(child
),
1799 ddi_driver_name(self
), ddi_get_instance(self
), ua
, ra
));
1801 SCSI_HBA_LOG((_LOG_NF(CONT
),
1802 "?%s%d at %s%d: unit-address %s",
1803 ddi_driver_name(child
), ddi_get_instance(child
),
1804 ddi_driver_name(self
), ddi_get_instance(self
), ua
));
1806 return (DDI_SUCCESS
);
1811 * scsi_busctl_initchild is called to initialize the SCSA transport for
1812 * communication with a particular child scsi target device. Successful
1813 * initialization requires properties on the node which describe the address
1814 * of the target device. If the address of the target device can't be
1815 * determined from properties then DDI_NOT_WELL_FORMED is returned. Nodes that
1816 * are DDI_NOT_WELL_FORMED are considered an implementation artifact and
1817 * are hidden from devinfo snapshots by calling ndi_devi_set_hidden().
1818 * The child may be one of the following types of devinfo nodes:
1821 * OBP does not enumerate target devices attached a SCSI bus. These
1822 * template/stub/wild-card nodes are a legacy artifact for support of old
1823 * driver loading methods. Since they have no properties,
1824 * DDI_NOT_WELL_FORMED will be returned.
1827 * The node may be either a:
1828 * o probe/barrier SID node
1829 * o a dynamic SID target node
1831 * driver.conf node: The situation for this nexus is different than most.
1832 * Typically a driver.conf node definition is used to either define a
1833 * new child devinfo node or to further decorate (via merge) a SID
1834 * child with properties. In our case we use the nodes for *both*
1837 * In both the SID node and driver.conf node cases we must form the nodes
1838 * "@addr" from the well-known scsi(9P) device unit-address properties on
1841 * For HBA drivers that implement the deprecated tran_get_name interface,
1842 * "@addr" construction involves having that driver interpret properties via
1843 * scsi_busctl_ua -> scsi_ua_get -> tran_get_name: there is no
1844 * requirement for the property names to be well-known.
1846 * NOTE: We don't currently support "merge". When this support is added a
1847 * specific property, like "unit-address", should *always* identify a
1848 * driver.conf node that needs to be merged into a specific SID node. When
1849 * enumeration is enabled, a .conf node without the "unit-address" property
1850 * should be ignored. The best way to establish the "unit-address" property
1851 * would be to have the system assign parent= and unit-address= from an
1852 * instance=# driver.conf entry (by using the instance tree).
1855 scsi_busctl_initchild(dev_info_t
*child
)
1857 dev_info_t
*self
= ddi_get_parent(child
);
1859 scsi_hba_tran_t
*tran
;
1860 struct scsi_device
*sd
;
1861 scsi_hba_tran_t
*tran_clone
;
1866 int err
= DDI_FAILURE
;
1867 char addr
[SCSI_MAXNAMELEN
];
1869 ASSERT(DEVI_BUSY_OWNED(self
));
1870 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init begin"));
1873 * For a driver like fp with multiple upper-layer-protocols
1874 * it is possible for scsi_hba_init in _init to plumb SCSA
1875 * and have the load of fcp (which does scsi_hba_attach_setup)
1876 * to fail. In this case we may get here with a NULL hba.
1878 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1880 return (DDI_NOT_WELL_FORMED
);
1883 * OBP may create template/stub/wild-card nodes for legacy driver
1884 * loading methods. These nodes have no properties, so we lack the
1885 * addressing properties to initchild them. Hide the node and return
1886 * DDI_NOT_WELL_FORMED.
1888 * Future: define/use a ndi_devi_has_properties(dip) type interface.
1890 * NOTE: It would be nice if we could delete these ill formed nodes by
1891 * implementing a DDI_NOT_WELL_FORMED_DELETE return code. This can't
1892 * be done until leadville debug code removes its dependencies
1893 * on the devinfo still being present after a failed ndi_devi_online.
1895 if ((DEVI(child
)->devi_hw_prop_ptr
== NULL
) &&
1896 (DEVI(child
)->devi_drv_prop_ptr
== NULL
) &&
1897 (DEVI(child
)->devi_sys_prop_ptr
== NULL
)) {
1898 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1899 "init failed: no properties"));
1900 ndi_devi_set_hidden(child
);
1901 return (DDI_NOT_WELL_FORMED
);
1904 /* get legacy SPI addressing properties */
1905 if ((tgt
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1906 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1907 SCSI_ADDR_PROP_TARGET
, -1)) == -1) {
1910 * A driver.conf node for merging always has a target= property,
1911 * even if it is just a dummy that does not contain the real
1912 * target address. However drivers that register devids may
1913 * create stub driver.conf nodes without a target= property so
1914 * that pathological devid resolution works. Hide the stub
1915 * node and return DDI_NOT_WELL_FORMED.
1917 if (!scsi_hba_dev_is_sid(child
)) {
1918 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1919 "init failed: stub .conf node"));
1920 ndi_devi_set_hidden(child
);
1921 return (DDI_NOT_WELL_FORMED
);
1924 lun
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1925 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_LUN
, 0);
1926 sfunc
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1927 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_SFUNC
, -1);
1930 * The scsi_address structure may not specify all the addressing
1931 * information. For an old HBA that doesn't support tran_get_name
1932 * (most pre-SCSI-3 HBAs) the scsi_address structure is still used,
1933 * so the target property must exist and the LUN must be < 256.
1935 if ((tran
->tran_get_name
== NULL
) &&
1936 ((tgt
>= USHRT_MAX
) || (lun
>= 256))) {
1937 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1938 "init failed: illegal/missing properties"));
1939 ndi_devi_set_hidden(child
);
1940 return (DDI_NOT_WELL_FORMED
);
1944 * We need to initialize a fair amount of our environment to invoke
1945 * tran_get_name (via scsi_busctl_ua and scsi_ua_get) to
1946 * produce the "@addr" name from addressing properties. Allocate and
1947 * initialize scsi device structure.
1949 sd
= kmem_zalloc(sizeof (struct scsi_device
), KM_SLEEP
);
1950 mutex_init(&sd
->sd_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
1952 sd
->sd_pathinfo
= NULL
;
1953 sd
->sd_uninit_prevent
= 0;
1954 ddi_set_driver_private(child
, sd
);
1956 if (tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
) {
1958 * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
1959 * scsi_device in the scsi_address structure. This allows an
1960 * HBA driver to find its per-scsi_device private data
1961 * (accessible to the HBA given just the scsi_address by using
1962 * scsi_address_device(9F)/scsi_device_hba_private_get(9F)).
1964 sd
->sd_address
.a
.a_sd
= sd
;
1968 * Initialize the scsi_address so that a SCSI-2 target driver
1969 * talking to a SCSI-2 device on a SCSI-3 bus (spi) continues
1970 * to work. We skew the secondary function value so that we
1971 * can tell from the address structure if we are processing
1972 * a secondary function request.
1974 sd
->sd_address
.a_target
= (ushort_t
)tgt
;
1975 sd
->sd_address
.a_lun
= (uchar_t
)lun
;
1977 sd
->sd_address
.a_sublun
= (uchar_t
)0;
1979 sd
->sd_address
.a_sublun
= (uchar_t
)sfunc
+ 1;
1982 * NOTE: Don't limit LUNs to scsi_options value because a
1983 * scsi_device discovered via SPI dynamic enumeration might
1984 * still support SCMD_REPORT_LUNS.
1988 * Deprecated: Use SCSI_HBA_ADDR_COMPLEX:
1989 * Clone transport structure if requested. Cloning allows
1990 * an HBA to maintain target-specific information if
1991 * necessary, such as target addressing information that
1992 * does not adhere to the scsi_address structure format.
1994 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
1995 tran_clone
= kmem_alloc(
1996 sizeof (scsi_hba_tran_t
), KM_SLEEP
);
1997 bcopy((caddr_t
)tran
,
1998 (caddr_t
)tran_clone
, sizeof (scsi_hba_tran_t
));
2003 ASSERT(tran
->tran_sd
== NULL
);
2007 /* establish scsi_address pointer to the HBA's tran structure */
2008 sd
->sd_address
.a_hba_tran
= tran
;
2011 * This is a grotty hack that allows direct-access (non-scsa) drivers
2012 * (like chs, ata, and mlx which all make cmdk children) to put its
2013 * own vector in the 'a_hba_tran' field. When all the drivers that do
2014 * this are fixed, please remove this hack.
2016 * NOTE: This hack is also shows up in the DEVP_TO_TRAN implementation
2017 * in scsi_confsubr.c.
2019 sd
->sd_tran_safe
= tran
;
2022 * If the class property is not already established, set it to "scsi".
2023 * This is done so that parent= driver.conf nodes have class.
2025 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2026 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "class",
2027 &class) == DDI_PROP_SUCCESS
) {
2028 ddi_prop_free(class);
2029 } else if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
2030 "class", "scsi") != DDI_PROP_SUCCESS
) {
2031 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: class"));
2032 ndi_devi_set_hidden(child
);
2033 err
= DDI_NOT_WELL_FORMED
;
2037 /* Establish the @addr name of the child. */
2039 if (scsi_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
) {
2041 * Some driver.conf files add bogus target properties (relative
2042 * to their nexus representation of target) to their stub
2043 * nodes, causing the check above to not filter them.
2045 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
2046 "init failed: scsi_busctl_ua call"));
2047 ndi_devi_set_hidden(child
);
2048 err
= DDI_NOT_WELL_FORMED
;
2051 if (*addr
== '\0') {
2052 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: ua"));
2053 ndi_devi_set_hidden(child
);
2054 err
= DDI_NOT_WELL_FORMED
;
2058 /* Prevent duplicate nodes. */
2059 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2062 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SCSI_DEVICE
);
2063 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SCSI_DEVICE
) {
2064 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2065 "init failed: %s@%s: not SCSI_DEVICE flavored",
2066 ddi_node_name(child
), addr
));
2070 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2071 "init failed: %s@%s: detected duplicate %p",
2072 ddi_node_name(child
), addr
, (void *)dup
));
2077 /* set the node @addr string */
2078 ddi_set_name_addr(child
, addr
);
2080 /* call HBA's target init entry point if it exists */
2081 if (tran
->tran_tgt_init
!= NULL
) {
2082 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init tran_tgt_init"));
2083 sd
->sd_tran_tgt_free_done
= 0;
2084 if ((*tran
->tran_tgt_init
)
2085 (self
, child
, tran
, sd
) != DDI_SUCCESS
) {
2086 scsi_enumeration_failed(child
, -1, NULL
,
2092 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "init successful"));
2093 return (DDI_SUCCESS
);
2097 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2098 mutex_destroy(&sd
->sd_mutex
);
2099 kmem_free(sd
, sizeof (*sd
));
2100 ddi_set_driver_private(child
, NULL
);
2101 ddi_set_name_addr(child
, NULL
);
2103 return (err
); /* remove the node */
2107 scsi_busctl_uninitchild(dev_info_t
*child
)
2109 dev_info_t
*self
= ddi_get_parent(child
);
2110 struct scsi_device
*sd
= ddi_get_driver_private(child
);
2111 scsi_hba_tran_t
*tran
;
2112 scsi_hba_tran_t
*tran_clone
;
2114 ASSERT(DEVI_BUSY_OWNED(self
));
2116 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
2118 if ((tran
== NULL
) || (sd
== NULL
))
2119 return (DDI_FAILURE
);
2122 * We use sd_uninit_prevent to avoid uninitializing barrier/probe
2123 * nodes that are still in use. Since barrier/probe nodes are not
2124 * attached we can't prevent their state demotion via ndi_hold_devi.
2126 if (sd
->sd_uninit_prevent
) {
2127 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "uninit prevented"));
2128 return (DDI_FAILURE
);
2132 * Don't uninitialize a client node if it still has paths.
2134 if (MDI_CLIENT(child
) && mdi_client_get_path_count(child
)) {
2135 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
2136 "uninit prevented, client has paths"));
2137 return (DDI_FAILURE
);
2140 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit begin"));
2142 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
2143 tran_clone
= sd
->sd_address
.a_hba_tran
;
2145 /* ... grotty hack, involving sd_tran_safe, continued. */
2146 if (tran_clone
!= sd
->sd_tran_safe
) {
2147 tran_clone
= sd
->sd_tran_safe
;
2150 * Complain so things get fixed and hack can, at
2151 * some point in time, be removed.
2153 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2154 "'%s' is corrupting a_hba_tran", sd
->sd_dev
?
2155 ddi_driver_name(sd
->sd_dev
) : "unknown_driver"));
2159 ASSERT(tran_clone
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
);
2160 ASSERT(tran_clone
->tran_sd
== sd
);
2164 ASSERT(tran
->tran_sd
== NULL
);
2168 * To simplify host adapter drivers we guarantee that multiple
2169 * tran_tgt_init(9E) calls of the same unit address are never
2170 * active at the same time. This requires that we always call
2171 * tran_tgt_free on probe/barrier nodes directly prior to
2174 * NOTE: To correctly support SCSI_HBA_TRAN_CLONE, we must use
2175 * the (possibly cloned) hba_tran pointer from the scsi_device
2176 * instead of hba_tran.
2178 if (tran
->tran_tgt_free
) {
2179 if (!sd
->sd_tran_tgt_free_done
) {
2180 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2181 "uninit tran_tgt_free"));
2182 (*tran
->tran_tgt_free
) (self
, child
, tran
, sd
);
2183 sd
->sd_tran_tgt_free_done
= 1;
2185 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2186 "uninit tran_tgt_free already done"));
2191 * If a inquiry data is still allocated (by scsi_probe()) we
2192 * free the allocation here. This keeps scsi_inq valid for the
2193 * same duration as the corresponding inquiry properties. It
2194 * also allows a tran_tgt_init() implementation that establishes
2195 * sd_inq to deal with deallocation in its tran_tgt_free
2196 * (setting sd_inq back to NULL) without upsetting the
2197 * framework. Moving the inquiry free here also allows setting
2198 * of sd_uninit_prevent to preserve the data for lun0 based
2199 * scsi_get_device_type_scsi_options() calls.
2202 kmem_free(sd
->sd_inq
, SUN_INQSIZE
);
2206 mutex_destroy(&sd
->sd_mutex
);
2208 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2209 kmem_free(sd
, sizeof (*sd
));
2211 ddi_set_driver_private(child
, NULL
);
2212 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit complete"));
2213 ddi_set_name_addr(child
, NULL
);
2214 return (DDI_SUCCESS
);
2218 iport_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
2222 /* limit ndi_devi_findchild_by_callback to expected flavor */
2223 if (ndi_flavor_get(child
) != SCSA_FLAVOR_IPORT
)
2224 return (DDI_FAILURE
);
2226 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2227 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2228 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
) {
2229 return (DDI_FAILURE
);
2232 (void) snprintf(addr
, maxlen
, "%s", iport_ua
);
2233 ddi_prop_free(iport_ua
);
2234 return (DDI_SUCCESS
);
2238 iport_busctl_reportdev(dev_info_t
*child
)
2240 dev_info_t
*self
= ddi_get_parent(child
);
2242 char *initiator_port
= NULL
;
2244 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2245 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2246 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
)
2247 return (DDI_FAILURE
);
2249 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2250 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2251 SCSI_ADDR_PROP_INITIATOR_PORT
, &initiator_port
);
2253 if (initiator_port
) {
2254 SCSI_HBA_LOG((_LOG_NF(CONT
),
2255 "?%s%d at %s%d: %s %s %s %s",
2256 ddi_driver_name(child
), ddi_get_instance(child
),
2257 ddi_driver_name(self
), ddi_get_instance(self
),
2258 SCSI_ADDR_PROP_INITIATOR_PORT
, initiator_port
,
2259 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2260 ddi_prop_free(initiator_port
);
2262 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s %s",
2263 ddi_driver_name(child
), ddi_get_instance(child
),
2264 ddi_driver_name(self
), ddi_get_instance(self
),
2265 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2267 ddi_prop_free(iport_ua
);
2268 return (DDI_SUCCESS
);
2271 /* initchild SCSA iport 'child' node */
2273 iport_busctl_initchild(dev_info_t
*child
)
2275 dev_info_t
*self
= ddi_get_parent(child
);
2276 dev_info_t
*dup
= NULL
;
2277 char addr
[SCSI_MAXNAMELEN
];
2279 if (iport_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
2280 return (DDI_NOT_WELL_FORMED
);
2282 /* Prevent duplicate nodes. */
2283 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2286 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_IPORT
);
2287 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_IPORT
) {
2288 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2289 "init failed: %s@%s: not IPORT flavored",
2290 ddi_node_name(child
), addr
));
2291 return (DDI_FAILURE
);
2294 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2295 "init failed: %s@%s: detected duplicate %p",
2296 ddi_node_name(child
), addr
, (void *)dup
));
2297 return (DDI_FAILURE
);
2301 /* set the node @addr string */
2302 ddi_set_name_addr(child
, addr
);
2304 return (DDI_SUCCESS
);
2307 /* uninitchild SCSA iport 'child' node */
2309 iport_busctl_uninitchild(dev_info_t
*child
)
2311 ddi_set_name_addr(child
, NULL
);
2312 return (DDI_SUCCESS
);
2315 /* Uninitialize scsi_device flavor of transport on SCSA iport 'child' node. */
2317 iport_postdetach_tran_scsi_device(dev_info_t
*child
)
2319 scsi_hba_tran_t
*tran
;
2321 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SCSI_DEVICE
);
2325 scsa_tran_teardown(child
, tran
);
2326 scsa_nexus_teardown(child
, tran
);
2328 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
2329 scsi_hba_tran_free(tran
);
2332 /* Initialize scsi_device flavor of transport on SCSA iport 'child' node. */
2334 iport_preattach_tran_scsi_device(dev_info_t
*child
)
2336 dev_info_t
*hba
= ddi_get_parent(child
);
2337 scsi_hba_tran_t
*htran
;
2338 scsi_hba_tran_t
*tran
;
2340 /* parent HBA node scsi_device tran is required */
2341 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SCSI_DEVICE
);
2344 /* Allocate iport child's scsi_device transport vector */
2345 tran
= scsi_hba_tran_alloc(child
, SCSI_HBA_CANSLEEP
);
2348 /* Structure-copy scsi_device transport of HBA to iport. */
2352 * Reset scsi_device transport fields not shared with the
2353 * parent, and not established below.
2355 tran
->tran_open_flag
= 0;
2356 tran
->tran_hba_private
= NULL
;
2358 /* Establish the devinfo context of this tran structure. */
2359 tran
->tran_iport_dip
= child
;
2361 /* Clear SCSI_HBA_SCSA flags (except TA) */
2362 tran
->tran_hba_flags
&=
2363 ~(SCSI_HBA_SCSA_FM
| SCSI_HBA_SCSA_PHCI
); /* clear parent state */
2364 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
; /* always TA */
2365 tran
->tran_hba_flags
&= ~SCSI_HBA_HBA
; /* never HBA */
2367 /* Establish flavor of transport (and ddi_get_driver_private()) */
2368 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
2370 /* Setup iport node */
2371 if ((scsa_nexus_setup(child
, tran
) != DDI_SUCCESS
) ||
2372 (scsa_tran_setup(child
, tran
) != DDI_SUCCESS
))
2373 iport_postdetach_tran_scsi_device(child
);
2376 /* Uninitialize smp_device flavor of transport on SCSA iport 'child' node. */
2378 iport_postdetach_tran_smp_device(dev_info_t
*child
)
2380 smp_hba_tran_t
*tran
;
2382 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SMP
);
2386 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2387 smp_hba_tran_free(tran
);
2390 /* Initialize smp_device flavor of transport on SCSA iport 'child' node. */
2392 iport_preattach_tran_smp_device(dev_info_t
*child
)
2394 dev_info_t
*hba
= ddi_get_parent(child
);
2395 smp_hba_tran_t
*htran
;
2396 smp_hba_tran_t
*tran
;
2398 /* parent HBA node smp_device tran is optional */
2399 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SMP
);
2400 if (htran
== NULL
) {
2401 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2405 /* Allocate iport child's smp_device transport vector */
2406 tran
= smp_hba_tran_alloc(child
);
2408 /* Structure-copy smp_device transport of HBA to iport. */
2411 /* Establish flavor of transport */
2412 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, tran
);
2416 * Generic bus_ctl operations for SCSI HBA's,
2417 * hiding the busctl interface from the HBA.
2428 int child_flavor
= 0;
2430 ddi_dma_attr_t
*attr
;
2431 scsi_hba_tran_t
*tran
;
2432 struct attachspec
*as
;
2433 struct detachspec
*ds
;
2435 /* For some ops, child is 'arg'. */
2436 if ((op
== DDI_CTLOPS_INITCHILD
) || (op
== DDI_CTLOPS_UNINITCHILD
))
2437 child
= (dev_info_t
*)arg
;
2439 /* Determine the flavor of the child: scsi, smp, iport */
2440 child_flavor
= ndi_flavor_get(child
);
2443 case DDI_CTLOPS_INITCHILD
:
2444 switch (child_flavor
) {
2445 case SCSA_FLAVOR_SCSI_DEVICE
:
2446 return (scsi_busctl_initchild(child
));
2447 case SCSA_FLAVOR_SMP
:
2448 return (smp_busctl_initchild(child
));
2449 case SCSA_FLAVOR_IPORT
:
2450 return (iport_busctl_initchild(child
));
2452 return (DDI_FAILURE
);
2456 case DDI_CTLOPS_UNINITCHILD
:
2457 switch (child_flavor
) {
2458 case SCSA_FLAVOR_SCSI_DEVICE
:
2459 return (scsi_busctl_uninitchild(child
));
2460 case SCSA_FLAVOR_SMP
:
2461 return (smp_busctl_uninitchild(child
));
2462 case SCSA_FLAVOR_IPORT
:
2463 return (iport_busctl_uninitchild(child
));
2465 return (DDI_FAILURE
);
2469 case DDI_CTLOPS_REPORTDEV
:
2470 switch (child_flavor
) {
2471 case SCSA_FLAVOR_SCSI_DEVICE
:
2472 return (scsi_busctl_reportdev(child
));
2473 case SCSA_FLAVOR_SMP
:
2474 return (smp_busctl_reportdev(child
));
2475 case SCSA_FLAVOR_IPORT
:
2476 return (iport_busctl_reportdev(child
));
2478 return (DDI_FAILURE
);
2482 case DDI_CTLOPS_ATTACH
:
2483 as
= (struct attachspec
*)arg
;
2485 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2486 return (DDI_SUCCESS
);
2488 /* iport processing */
2489 if (as
->when
== DDI_PRE
) {
2490 /* setup pre attach(9E) */
2491 iport_preattach_tran_scsi_device(child
);
2492 iport_preattach_tran_smp_device(child
);
2493 } else if ((as
->when
== DDI_POST
) &&
2494 (as
->result
!= DDI_SUCCESS
)) {
2495 /* cleanup if attach(9E) failed */
2496 iport_postdetach_tran_scsi_device(child
);
2497 iport_postdetach_tran_smp_device(child
);
2499 return (DDI_SUCCESS
);
2501 case DDI_CTLOPS_DETACH
:
2502 ds
= (struct detachspec
*)arg
;
2504 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2505 return (DDI_SUCCESS
);
2507 /* iport processing */
2508 if ((ds
->when
== DDI_POST
) &&
2509 (ds
->result
== DDI_SUCCESS
)) {
2510 /* cleanup if detach(9E) was successful */
2511 iport_postdetach_tran_scsi_device(child
);
2512 iport_postdetach_tran_smp_device(child
);
2514 return (DDI_SUCCESS
);
2516 case DDI_CTLOPS_IOMIN
:
2517 tran
= ddi_get_driver_private(self
);
2520 return (DDI_FAILURE
);
2523 * The 'arg' value of nonzero indicates 'streaming'
2524 * mode. If in streaming mode, pick the largest
2525 * of our burstsizes available and say that that
2526 * is our minimum value (modulo what minxfer is).
2528 attr
= &tran
->tran_dma_attr
;
2529 val
= *((int *)result
);
2530 val
= maxbit(val
, attr
->dma_attr_minxfer
);
2531 *((int *)result
) = maxbit(val
, ((intptr_t)arg
?
2532 (1<<ddi_ffs(attr
->dma_attr_burstsizes
)-1) :
2533 (1<<(ddi_fls(attr
->dma_attr_burstsizes
)-1))));
2535 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2537 case DDI_CTLOPS_SIDDEV
:
2538 return (ndi_dev_is_persistent_node(child
) ?
2539 DDI_SUCCESS
: DDI_FAILURE
);
2541 case DDI_CTLOPS_POWER
:
2542 return (DDI_SUCCESS
);
2545 * These ops correspond to functions that "shouldn't" be called
2546 * by a SCSI target driver. So we whine when we're called.
2548 case DDI_CTLOPS_DMAPMAPC
:
2549 case DDI_CTLOPS_REPORTINT
:
2550 case DDI_CTLOPS_REGSIZE
:
2551 case DDI_CTLOPS_NREGS
:
2552 case DDI_CTLOPS_SLAVEONLY
:
2553 case DDI_CTLOPS_AFFINITY
:
2554 case DDI_CTLOPS_POKE
:
2555 case DDI_CTLOPS_PEEK
:
2556 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
, "invalid op (%d)", op
));
2557 return (DDI_FAILURE
);
2559 /* Everything else we pass up */
2560 case DDI_CTLOPS_PTOB
:
2561 case DDI_CTLOPS_BTOP
:
2562 case DDI_CTLOPS_BTOPR
:
2563 case DDI_CTLOPS_DVMAPAGESIZE
:
2565 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2571 * Private wrapper for scsi_pkt's allocated via scsi_hba_pkt_alloc()
2573 struct scsi_pkt_wrapper
{
2574 struct scsi_pkt scsi_pkt
;
2575 int pkt_wrapper_magic
;
2576 int pkt_wrapper_len
;
2579 _NOTE(SCHEME_PROTECTS_DATA("unique per thread", scsi_pkt_wrapper
))
2580 _NOTE(SCHEME_PROTECTS_DATA("Unshared Data", dev_ops
))
2583 * Called by an HBA to allocate a scsi_pkt
2589 struct scsi_address
*ap
,
2594 int (*callback
)(caddr_t arg
),
2597 struct scsi_pkt
*pkt
;
2598 struct scsi_pkt_wrapper
*hba_pkt
;
2600 int acmdlen
, astatuslen
, atgtlen
, ahbalen
;
2604 if (callback
!= SLEEP_FUNC
&& callback
!= NULL_FUNC
)
2605 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2606 "callback must be SLEEP_FUNC or NULL_FUNC"));
2609 * Round up so everything gets allocated on long-word boundaries
2611 acmdlen
= ROUNDUP(cmdlen
);
2612 astatuslen
= ROUNDUP(statuslen
);
2613 atgtlen
= ROUNDUP(tgtlen
);
2614 ahbalen
= ROUNDUP(hbalen
);
2615 pktlen
= sizeof (struct scsi_pkt_wrapper
) +
2616 acmdlen
+ astatuslen
+ atgtlen
+ ahbalen
;
2618 hba_pkt
= kmem_zalloc(pktlen
,
2619 (callback
== SLEEP_FUNC
) ? KM_SLEEP
: KM_NOSLEEP
);
2620 if (hba_pkt
== NULL
) {
2621 ASSERT(callback
== NULL_FUNC
);
2626 * Set up our private info on this pkt
2628 hba_pkt
->pkt_wrapper_len
= pktlen
;
2629 hba_pkt
->pkt_wrapper_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
2630 pkt
= &hba_pkt
->scsi_pkt
;
2633 * Set up pointers to private data areas, cdb, and status.
2635 p
= (caddr_t
)(hba_pkt
+ 1);
2637 pkt
->pkt_ha_private
= (opaque_t
)p
;
2641 pkt
->pkt_private
= (opaque_t
)p
;
2644 if (statuslen
> 0) {
2645 pkt
->pkt_scbp
= (uchar_t
*)p
;
2649 pkt
->pkt_cdbp
= (uchar_t
*)p
;
2653 * Initialize the pkt's scsi_address
2655 pkt
->pkt_address
= *ap
;
2658 * NB: It may not be safe for drivers, esp target drivers, to depend
2659 * on the following fields being set until all the scsi_pkt
2660 * allocation violations discussed in scsi_pkt.h are all resolved.
2662 pkt
->pkt_cdblen
= cmdlen
;
2663 pkt
->pkt_tgtlen
= tgtlen
;
2664 pkt
->pkt_scblen
= statuslen
;
2670 * Called by an HBA to free a scsi_pkt
2675 struct scsi_address
*ap
,
2676 struct scsi_pkt
*pkt
)
2678 kmem_free(pkt
, ((struct scsi_pkt_wrapper
*)pkt
)->pkt_wrapper_len
);
2682 * Return 1 if the scsi_pkt used a proper allocator.
2684 * The DDI does not allow a driver to allocate it's own scsi_pkt(9S), a
2685 * driver should not have *any* compiled in dependencies on "sizeof (struct
2686 * scsi_pkt)". While this has been the case for many years, a number of
2687 * drivers have still not been fixed. This function can be used to detect
2688 * improperly allocated scsi_pkt structures, and produce messages identifying
2689 * drivers that need to be fixed.
2691 * While drivers in violation are being fixed, this function can also
2692 * be used by the framework to detect packets that violated allocation
2695 * NB: It is possible, but very unlikely, for this code to return a false
2696 * positive (finding correct magic, but for wrong reasons). Careful
2697 * consideration is needed for callers using this interface to condition
2698 * access to newer scsi_pkt fields (those after pkt_reason).
2700 * NB: As an aid to minimizing the amount of work involved in 'fixing' legacy
2701 * drivers that violate scsi_*(9S) allocation rules, private
2702 * scsi_pkt_size()/scsi_size_clean() functions are available (see their
2703 * implementation for details).
2705 * *** Non-legacy use of scsi_pkt_size() is discouraged. ***
2707 * NB: When supporting broken HBA drivers is not longer a concern, this
2708 * code should be removed.
2711 scsi_pkt_allocated_correctly(struct scsi_pkt
*pkt
)
2713 struct scsi_pkt_wrapper
*hba_pkt
= (struct scsi_pkt_wrapper
*)pkt
;
2717 int *pspwm
, *pspcwm
;
2720 * We are getting scsi packets from two 'correct' wrapper schemes,
2721 * make sure we are looking at the same place in both to detect
2722 * proper allocation.
2724 pspwm
= &((struct scsi_pkt_wrapper
*)0)->pkt_wrapper_magic
;
2725 pspcwm
= &((struct scsi_pkt_cache_wrapper
*)0)->pcw_magic
;
2726 ASSERT(pspwm
== pspcwm
);
2731 * Check to see if driver is scsi_size_clean(), assume it
2732 * is using the scsi_pkt_size() interface everywhere it needs to
2733 * if the driver indicates it is scsi_size_clean().
2735 major
= ddi_driver_major(P_TO_TRAN(pkt
)->tran_hba_dip
);
2736 if (devnamesp
[major
].dn_flags
& DN_SCSI_SIZE_CLEAN
)
2737 return (1); /* ok */
2740 * Special case crossing a page boundary. If the scsi_pkt was not
2741 * allocated correctly, then across a page boundary we have a
2744 if ((((uintptr_t)(&hba_pkt
->scsi_pkt
)) & MMU_PAGEMASK
) ==
2745 (((uintptr_t)(&hba_pkt
->pkt_wrapper_magic
)) & MMU_PAGEMASK
)) {
2746 /* fastpath, no cross-page hazard */
2747 magic
= hba_pkt
->pkt_wrapper_magic
;
2749 /* add protection for cross-page hazard */
2750 if (ddi_peek32((dev_info_t
*)NULL
,
2751 &hba_pkt
->pkt_wrapper_magic
, &magic
) == DDI_FAILURE
) {
2752 return (0); /* violation */
2756 /* properly allocated packet always has correct magic */
2757 return ((magic
== PKT_WRAPPER_MAGIC
) ? 1 : 0);
2761 * Private interfaces to simplify conversion of legacy drivers so they don't
2762 * depend on scsi_*(9S) size. Instead of using these private interface, HBA
2763 * drivers should use DDI sanctioned allocation methods:
2765 * scsi_pkt Use scsi_hba_pkt_alloc(9F), or implement
2766 * tran_setup_pkt(9E).
2768 * scsi_device You are doing something strange/special, a scsi_device
2769 * structure should only be allocated by scsi_hba.c
2770 * initchild code or scsi_vhci.c code.
2772 * scsi_hba_tran Use scsi_hba_tran_alloc(9F).
2777 return (sizeof (struct scsi_pkt
));
2781 scsi_hba_tran_size()
2783 return (sizeof (scsi_hba_tran_t
));
2789 return (sizeof (struct scsi_device
));
2793 * Legacy compliance to scsi_pkt(9S) allocation rules through use of
2794 * scsi_pkt_size() is detected by the 'scsi-size-clean' driver.conf property
2795 * or an HBA driver calling to scsi_size_clean() from attach(9E). A driver
2796 * developer should only indicate that a legacy driver is clean after using
2797 * SCSI_SIZE_CLEAN_VERIFY to ensure compliance (see scsi_pkt.h).
2800 scsi_size_clean(dev_info_t
*self
)
2803 struct devnames
*dnp
;
2806 major
= ddi_driver_major(self
);
2807 ASSERT(major
< devcnt
);
2808 if (major
>= devcnt
) {
2809 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2810 "scsi_pkt_size: bogus major: %d", major
));
2814 /* Set DN_SCSI_SIZE_CLEAN flag in dn_flags. */
2815 dnp
= &devnamesp
[major
];
2816 if ((dnp
->dn_flags
& DN_SCSI_SIZE_CLEAN
) == 0) {
2817 LOCK_DEV_OPS(&dnp
->dn_lock
);
2818 dnp
->dn_flags
|= DN_SCSI_SIZE_CLEAN
;
2819 UNLOCK_DEV_OPS(&dnp
->dn_lock
);
2825 * Called by an HBA to map strings to capability indices
2828 scsi_hba_lookup_capstr(
2832 * Capability strings: only add entries to mask the legacy
2833 * '_' vs. '-' misery. All new capabilities should use '-',
2834 * and be captured be added to SCSI_CAP_ASCII.
2836 static struct cap_strings
{
2840 { "dma_max", SCSI_CAP_DMA_MAX
},
2841 { "msg_out", SCSI_CAP_MSG_OUT
},
2842 { "wide_xfer", SCSI_CAP_WIDE_XFER
},
2845 static char *cap_ascii
[] = SCSI_CAP_ASCII
;
2848 struct cap_strings
*cp
;
2850 for (cap
= cap_ascii
, i
= 0; *cap
!= NULL
; cap
++, i
++)
2851 if (strcmp(*cap
, capstr
) == 0)
2854 for (cp
= cap_strings
; cp
->cap_string
!= NULL
; cp
++)
2855 if (strcmp(cp
->cap_string
, capstr
) == 0)
2856 return (cp
->cap_index
);
2862 * Called by an HBA to determine if the system is in 'panic' state.
2867 return (panicstr
!= NULL
);
2871 * If a SCSI target driver attempts to mmap memory,
2872 * the buck stops here.
2887 return (DDI_FAILURE
);
2891 scsi_hba_get_eventcookie(
2895 ddi_eventcookie_t
*eventp
)
2897 scsi_hba_tran_t
*tran
;
2899 tran
= ddi_get_driver_private(self
);
2900 if (tran
->tran_get_eventcookie
&&
2901 ((*tran
->tran_get_eventcookie
)(self
,
2902 child
, name
, eventp
) == DDI_SUCCESS
)) {
2903 return (DDI_SUCCESS
);
2906 return (ndi_busop_get_eventcookie(self
, child
, name
, eventp
));
2910 scsi_hba_add_eventcall(
2913 ddi_eventcookie_t event
,
2916 ddi_eventcookie_t event
,
2918 void *bus_impldata
),
2920 ddi_callback_id_t
*cb_id
)
2922 scsi_hba_tran_t
*tran
;
2924 tran
= ddi_get_driver_private(self
);
2925 if (tran
->tran_add_eventcall
&&
2926 ((*tran
->tran_add_eventcall
)(self
, child
,
2927 event
, callback
, arg
, cb_id
) == DDI_SUCCESS
)) {
2928 return (DDI_SUCCESS
);
2931 return (DDI_FAILURE
);
2935 scsi_hba_remove_eventcall(dev_info_t
*self
, ddi_callback_id_t cb_id
)
2937 scsi_hba_tran_t
*tran
;
2940 tran
= ddi_get_driver_private(self
);
2941 if (tran
->tran_remove_eventcall
&&
2942 ((*tran
->tran_remove_eventcall
)(
2943 self
, cb_id
) == DDI_SUCCESS
)) {
2944 return (DDI_SUCCESS
);
2947 return (DDI_FAILURE
);
2951 scsi_hba_post_event(
2954 ddi_eventcookie_t event
,
2957 scsi_hba_tran_t
*tran
;
2959 tran
= ddi_get_driver_private(self
);
2960 if (tran
->tran_post_event
&&
2961 ((*tran
->tran_post_event
)(self
,
2962 child
, event
, bus_impldata
) == DDI_SUCCESS
)) {
2963 return (DDI_SUCCESS
);
2966 return (DDI_FAILURE
);
2970 * Default getinfo(9e) for scsi_hba
2974 scsi_hba_info(dev_info_t
*self
, ddi_info_cmd_t infocmd
, void *arg
,
2977 int error
= DDI_SUCCESS
;
2980 case DDI_INFO_DEVT2INSTANCE
:
2981 *result
= (void *)(intptr_t)(MINOR2INST(getminor((dev_t
)arg
)));
2984 error
= DDI_FAILURE
;
2990 * Default open and close routine for scsi_hba
2994 scsi_hba_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
2997 scsi_hba_tran_t
*tran
;
3000 if (otyp
!= OTYP_CHR
)
3003 if ((self
= e_ddi_hold_devi_by_dev(*devp
, 0)) == NULL
)
3006 tran
= ddi_get_driver_private(self
);
3008 ddi_release_devi(self
);
3013 * tran_open_flag bit field:
3015 * 1: shared open by minor at bit position
3016 * 1 at 31st bit: exclusive open
3018 mutex_enter(&(tran
->tran_open_lock
));
3019 if (flags
& FEXCL
) {
3020 if (tran
->tran_open_flag
!= 0) {
3021 rv
= EBUSY
; /* already open */
3023 tran
->tran_open_flag
= TRAN_OPEN_EXCL
;
3026 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3027 rv
= EBUSY
; /* already excl. open */
3029 int minor
= getminor(*devp
) & TRAN_MINOR_MASK
;
3030 tran
->tran_open_flag
|= (1 << minor
);
3032 * Ensure that the last framework reserved minor
3033 * is unused. Otherwise, the exclusive open
3034 * mechanism may break.
3036 ASSERT(minor
!= 31);
3039 mutex_exit(&(tran
->tran_open_lock
));
3041 ddi_release_devi(self
);
3047 scsi_hba_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
3050 scsi_hba_tran_t
*tran
;
3052 if (otyp
!= OTYP_CHR
)
3055 if ((self
= e_ddi_hold_devi_by_dev(dev
, 0)) == NULL
)
3058 tran
= ddi_get_driver_private(self
);
3060 ddi_release_devi(self
);
3064 mutex_enter(&(tran
->tran_open_lock
));
3065 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3066 tran
->tran_open_flag
= 0;
3068 int minor
= getminor(dev
) & TRAN_MINOR_MASK
;
3069 tran
->tran_open_flag
&= ~(1 << minor
);
3071 mutex_exit(&(tran
->tran_open_lock
));
3073 ddi_release_devi(self
);
3078 * standard ioctl commands for SCSI hotplugging
3082 scsi_hba_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
3086 struct devctl_iocdata
*dcp
= NULL
;
3087 dev_info_t
*child
= NULL
;
3088 mdi_pathinfo_t
*path
= NULL
;
3089 struct scsi_device
*sd
;
3090 scsi_hba_tran_t
*tran
;
3097 self
= e_ddi_hold_devi_by_dev(dev
, 0);
3103 tran
= ddi_get_driver_private(self
);
3109 /* Ioctls for which the generic implementation suffices. */
3111 case DEVCTL_BUS_GETSTATE
:
3112 rv
= ndi_devctl_ioctl(self
, cmd
, arg
, mode
, 0);
3116 /* read devctl ioctl data */
3117 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
) {
3122 /* Ioctls that require child identification */
3124 case DEVCTL_DEVICE_GETSTATE
:
3125 case DEVCTL_DEVICE_ONLINE
:
3126 case DEVCTL_DEVICE_OFFLINE
:
3127 case DEVCTL_DEVICE_REMOVE
:
3128 case DEVCTL_DEVICE_RESET
:
3129 name
= ndi_dc_getname(dcp
);
3130 addr
= ndi_dc_getaddr(dcp
);
3131 if ((name
== NULL
) || (addr
== NULL
)) {
3137 * Find child with name@addr - might find a devinfo
3138 * child (child), a pathinfo child (path), or nothing.
3140 scsi_hba_devi_enter(self
, &circ
);
3142 (void) scsi_findchild(self
, name
, addr
, 1, &child
, &path
, NULL
);
3144 /* Found a pathinfo */
3145 ASSERT(path
&& (child
== NULL
));
3146 mdi_hold_path(path
);
3147 scsi_hba_devi_exit_phci(self
, circ
);
3150 /* Found a devinfo */
3151 ASSERT(child
&& (path
== NULL
));
3153 /* verify scsi_device of child */
3154 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3155 sd
= ddi_get_driver_private(child
);
3159 ASSERT((path
== NULL
) && (child
== NULL
));
3160 scsi_hba_devi_exit(self
, circ
);
3161 rv
= ENXIO
; /* found nothing */
3166 case DEVCTL_BUS_RESETALL
: /* ioctl that operate on any child */
3168 * Find a child's scsi_address so we can invoke tran_reset.
3170 * Future: If no child exists, we could fake a child. This will
3171 * be a enhancement for the future - for now, we fall back to
3174 scsi_hba_devi_enter(self
, &circ
);
3175 child
= ddi_get_child(self
);
3178 /* verify scsi_device of child */
3179 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3180 sd
= ddi_get_driver_private(child
);
3183 * NOTE: node has a scsi_device structure, so
3184 * it must be initialized.
3186 ndi_hold_devi(child
);
3189 child
= ddi_get_next_sibling(child
);
3191 scsi_hba_devi_exit(self
, circ
);
3196 case DEVCTL_DEVICE_GETSTATE
:
3198 if (mdi_dc_return_dev_state(path
, dcp
) != MDI_SUCCESS
)
3201 if (ndi_dc_return_dev_state(child
, dcp
) != NDI_SUCCESS
)
3208 case DEVCTL_DEVICE_RESET
:
3213 if (tran
->tran_reset
== NULL
) {
3218 /* Start with the small stick */
3219 if (scsi_reset(&sd
->sd_address
, RESET_LUN
) == 1)
3220 break; /* LUN reset worked */
3221 if (scsi_reset(&sd
->sd_address
, RESET_TARGET
) != 1)
3222 rv
= EIO
; /* Target reset failed */
3225 case DEVCTL_BUS_QUIESCE
:
3226 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3227 (bus_state
== BUS_QUIESCED
))
3229 else if (tran
->tran_quiesce
== NULL
)
3230 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3231 else if (tran
->tran_quiesce(self
) != 0)
3233 else if (ndi_set_bus_state(self
, BUS_QUIESCED
) != NDI_SUCCESS
)
3237 case DEVCTL_BUS_UNQUIESCE
:
3238 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3239 (bus_state
== BUS_ACTIVE
))
3241 else if (tran
->tran_unquiesce
== NULL
)
3242 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3243 else if (tran
->tran_unquiesce(self
) != 0)
3245 else if (ndi_set_bus_state(self
, BUS_ACTIVE
) != NDI_SUCCESS
)
3249 case DEVCTL_BUS_RESET
:
3250 if (tran
->tran_bus_reset
== NULL
)
3251 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3252 else if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3256 case DEVCTL_BUS_RESETALL
:
3258 (scsi_reset(&sd
->sd_address
, RESET_ALL
) == 1)) {
3259 break; /* reset all worked */
3261 if (tran
->tran_bus_reset
== NULL
) {
3262 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3265 if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3266 rv
= EIO
; /* bus reset failed */
3269 case DEVCTL_BUS_CONFIGURE
:
3270 if (ndi_devi_config(self
, NDI_DEVFS_CLEAN
| NDI_DEVI_PERSIST
|
3271 NDI_CONFIG_REPROBE
) != NDI_SUCCESS
) {
3276 case DEVCTL_BUS_UNCONFIGURE
:
3277 if (ndi_devi_unconfig(self
,
3278 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
) {
3283 case DEVCTL_DEVICE_ONLINE
:
3284 ASSERT(child
|| path
);
3286 if (mdi_pi_online(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3289 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
)
3294 case DEVCTL_DEVICE_OFFLINE
:
3295 ASSERT(child
|| path
);
3297 (void) scsi_clear_task_set(&sd
->sd_address
);
3299 if (mdi_pi_offline(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3302 if (ndi_devi_offline(child
,
3303 NDI_DEVFS_CLEAN
) != NDI_SUCCESS
)
3308 case DEVCTL_DEVICE_REMOVE
:
3309 ASSERT(child
|| path
);
3311 (void) scsi_clear_task_set(&sd
->sd_address
);
3313 /* NOTE: don't pass NDI_DEVI_REMOVE to mdi_pi_offline */
3314 if (mdi_pi_offline(path
, NDI_USER_REQ
) == MDI_SUCCESS
) {
3315 scsi_hba_devi_enter_phci(self
, &circ
);
3316 mdi_rele_path(path
);
3318 /* ... here is the DEVICE_REMOVE part. */
3319 (void) mdi_pi_free(path
, 0);
3325 if (ndi_devi_offline(child
,
3326 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
)
3332 ASSERT(dcp
!= NULL
);
3337 /* all done -- clean up and return */
3339 /* release hold on what we found */
3341 scsi_hba_devi_enter_phci(self
, &circ
);
3342 mdi_rele_path(path
);
3345 scsi_hba_devi_exit(self
, circ
);
3348 ndi_dc_freehdl(dcp
);
3351 ddi_release_devi(self
);
3360 scsi_hba_fm_init_child(dev_info_t
*self
, dev_info_t
*child
, int cap
,
3361 ddi_iblock_cookie_t
*ibc
)
3363 scsi_hba_tran_t
*tran
= ddi_get_driver_private(self
);
3365 return (tran
? tran
->tran_fm_capable
: scsi_fm_capable
);
3369 scsi_hba_bus_power(dev_info_t
*self
, void *impl_arg
, pm_bus_power_op_t op
,
3370 void *arg
, void *result
)
3372 scsi_hba_tran_t
*tran
;
3374 tran
= ddi_get_driver_private(self
);
3375 if (tran
&& tran
->tran_bus_power
) {
3376 return (tran
->tran_bus_power(self
, impl_arg
,
3380 return (pm_busop_bus_power(self
, impl_arg
, op
, arg
, result
));
3384 * Return the lun64 value from a address string: "addr,lun[,sfunc]". Either
3385 * the lun is after the first ',' or the entire address string is the lun.
3386 * Return SCSI_LUN64_ILLEGAL if the format is incorrect. A lun64 is at most
3387 * 16 hex digits long.
3389 * If the address string specified has incorrect syntax (busconfig one of
3390 * bogus /devices path) then scsi_addr_to_lun64 can return SCSI_LUN64_ILLEGAL.
3393 scsi_addr_to_lun64(char *addr
)
3400 s
= strchr(addr
, ','); /* "addr,lun" */
3402 s
++; /* skip ',', at lun */
3404 s
= addr
; /* "lun" */
3406 for (lun64
= 0, i
= 0; *s
&& (i
< 16); s
++, i
++) {
3407 if (*s
>= '0' && *s
<= '9')
3408 lun64
= (lun64
<< 4) + (*s
- '0');
3409 else if (*s
>= 'A' && *s
<= 'F')
3410 lun64
= (lun64
<< 4) + 10 + (*s
- 'A');
3411 else if (*s
>= 'a' && *s
<= 'f')
3412 lun64
= (lun64
<< 4) + 10 + (*s
- 'a');
3416 if (*s
&& (*s
!= ',')) /* [,sfunc] is OK */
3417 lun64
= SCSI_LUN64_ILLEGAL
;
3419 lun64
= SCSI_LUN64_ILLEGAL
;
3421 if (lun64
== SCSI_LUN64_ILLEGAL
)
3422 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
3423 "addr_to_lun64 %s lun %" PRIlun64
,
3424 addr
? addr
: "NULL", lun64
));
3429 * Return the sfunc value from a address string: "addr,lun[,sfunc]". Either the
3430 * sfunc is after the second ',' or the entire address string is the sfunc.
3431 * Return -1 if there is only one ',' in the address string or the string is
3432 * invalid. An sfunc is at most two hex digits long.
3435 scsi_addr_to_sfunc(char *addr
)
3442 s
= strchr(addr
, ','); /* "addr,lun" */
3444 s
++; /* skip ',', at lun */
3445 s
= strchr(s
, ','); /* "lun,sfunc" */
3447 return (-1); /* no ",sfunc" */
3448 s
++; /* skip ',', at sfunc */
3450 s
= addr
; /* "sfunc" */
3452 for (sfunc
= 0, i
= 0; *s
&& (i
< 2); s
++, i
++) {
3453 if (*s
>= '0' && *s
<= '9')
3454 sfunc
= (sfunc
<< 4) + (*s
- '0');
3455 else if (*s
>= 'A' && *s
<= 'F')
3456 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'A');
3457 else if (*s
>= 'a' && *s
<= 'f')
3458 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'a');
3463 sfunc
= -1; /* illegal */
3470 * Convert scsi ascii string data to NULL terminated (semi) legal IEEE 1275
3471 * "compatible" (name) property form.
3473 * For ASCII INQUIRY data, a one-way conversion algorithm is needed to take
3474 * SCSI_ASCII (20h - 7Eh) to a 1275-like compatible form. The 1275 spec allows
3475 * letters, digits, one ",", and ". _ + -", all limited by a maximum 31
3476 * character length. Since ", ." are used as separators in the compatible
3477 * string itself, they are converted to "_". All SCSI_ASCII characters that
3478 * are illegal in 1275, as well as any illegal SCSI_ASCII characters
3479 * encountered, are converted to "_". To reduce length, trailing blanks are
3480 * trimmed from SCSI_ASCII fields prior to conversion.
3482 * Example: SCSI_ASCII "ST32550W SUN2.1G" -> "ST32550W_SUN2_1G"
3484 * NOTE: the 1275 string form is always less than or equal to the scsi form.
3487 string_scsi_to_1275(char *s_1275
, char *s_scsi
, int len
)
3489 (void) strncpy(s_1275
, s_scsi
, len
);
3490 s_1275
[len
--] = '\0';
3493 if (s_1275
[len
] == ' ')
3494 s_1275
[len
--] = '\0'; /* trim trailing " " */
3500 if (((s_1275
[len
] >= 'a') && (s_1275
[len
] <= 'z')) ||
3501 ((s_1275
[len
] >= 'A') && (s_1275
[len
] <= 'Z')) ||
3502 ((s_1275
[len
] >= '0') && (s_1275
[len
] <= '9')) ||
3503 (s_1275
[len
] == '_') ||
3504 (s_1275
[len
] == '+') ||
3505 (s_1275
[len
] == '-'))
3506 len
--; /* legal 1275 */
3508 s_1275
[len
--] = '_'; /* illegal SCSI_ASCII | 1275 */
3515 * Given the inquiry data, binding_set, and dtype_node for a scsi device,
3516 * return the nodename and compatible property for the device. The "compatible"
3517 * concept comes from IEEE-1275. The compatible information is returned is in
3518 * the correct form for direct use defining the "compatible" string array
3519 * property. Internally, "compatible" is also used to determine the nodename
3522 * This function is provided as a separate entry point for use by drivers that
3523 * currently issue their own non-SCSA inquiry command and perform their own
3524 * node creation based their own private compiled in tables. Converting these
3525 * drivers to use this interface provides a quick easy way of obtaining
3526 * consistency as well as the flexibility associated with the 1275 techniques.
3528 * The dtype_node is passed as a separate argument (instead of having the
3529 * implementation use inq_dtype). It indicates that information about
3530 * a secondary function embedded service should be produced.
3532 * Callers must always use scsi_hba_nodename_compatible_free, even if
3533 * *nodenamep is null, to free the nodename and compatible information
3536 * If a nodename can't be determined then **compatiblep will point to a
3537 * diagnostic string containing all the compatible forms.
3539 * NOTE: some compatible strings may violate the 31 character restriction
3540 * imposed by IEEE-1275. This is not a problem because Solaris does not care
3541 * about this 31 character limit.
3543 * Each compatible form belongs to a form-group. The form-groups currently
3544 * defined are generic ("scsiclass"), binding-set ("scsa.b"), and failover
3547 * The following compatible forms, in high to low precedence
3548 * order, are defined for SCSI target device nodes.
3550 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (1 *1&2)
3551 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (2 *1)
3552 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (3 *2)
3553 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (4)
3554 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (5 *1&2)
3555 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP (6 *1)
3556 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (7 *2)
3557 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP (8)
3558 * scsa,DD.bBBBBBBBB (8.5 *3)
3559 * scsiclass,DDEEFFF (9 *1&2)
3560 * scsiclass,DDEE (10 *1)
3561 * scsiclass,DDFFF (11 *2)
3563 * scsa.fFFF (12.5 *4)
3566 * *1 only produced on a secondary function node
3567 * *2 only produced when generic form-group flags exist.
3568 * *3 only produced when binding-set form-group legacy support is needed
3569 * *4 only produced when failover form-group flags exist.
3573 * v is the letter 'v'. Denotest the
3574 * beginning of VVVVVVVV.
3576 * VVVVVVVV Translated scsi_vendor.
3578 * p is the letter 'p'. Denotes the
3579 * beginning of PPPPPPPPPPPPPPPP.
3581 * PPPPPPPPPPPPPPPP Translated scsi_product.
3583 * r is the letter 'r'. Denotes the
3584 * beginning of RRRR.
3586 * RRRR Translated scsi_revision.
3588 * DD is a two digit ASCII hexadecimal
3589 * number. The value of the two digits is
3590 * based one the SCSI "Peripheral device
3591 * type" command set associated with the
3592 * node. On a primary node this is the
3593 * scsi_dtype of the primary command set,
3594 * on a secondary node this is the
3595 * scsi_dtype associated with the secondary
3596 * function embedded command set.
3598 * EE Same encoding used for DD. This form is
3599 * only generated on secondary function
3600 * nodes. The DD secondary function is embedded
3603 * FFF Concatenation, in alphabetical order,
3604 * of the flag characters within a form-group.
3605 * For a given form-group, the following
3606 * flags are defined.
3608 * scsiclass: (generic form-group):
3609 * R Removable_Media: Used when
3611 * S SAF-TE device: Used when
3612 * inquiry information indicates
3615 * scsa.f: (failover form-group):
3616 * E Explicit Target_Port_Group: Used
3617 * when inq_tpgse is set and 'G' is
3619 * G GUID: Used when a GUID can be
3620 * generated for the device.
3621 * I Implicit Target_Port_Group: Used
3622 * when inq_tpgs is set and 'G' is
3625 * Forms using FFF are only be generated
3626 * if there are applicable flag
3629 * b is the letter 'b'. Denotes the
3630 * beginning of BBBBBBBB.
3632 * BBBBBBBB Binding-set. Operating System Specific:
3633 * scsi-binding-set property of HBA.
3635 #define NCOMPAT (1 + (13 + 2) + 1)
3636 #define COMPAT_LONGEST (strlen( \
3637 "scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR" + 1))
3640 * Private version with extra device 'identity' arguments to allow code
3641 * to determine GUID FFF support.
3644 scsi_hba_ident_nodename_compatible_get(struct scsi_inquiry
*inq
,
3645 uchar_t
*inq80
, size_t inq80len
, uchar_t
*inq83
, size_t inq83len
,
3646 char *binding_set
, int dtype_node
, char *compat0
,
3647 char **nodenamep
, char **drivernamep
,
3648 char ***compatiblep
, int *ncompatiblep
)
3650 char vid
[sizeof (inq
->inq_vid
) + 1 ];
3651 char pid
[sizeof (inq
->inq_pid
) + 1];
3652 char rev
[sizeof (inq
->inq_revision
) + 1];
3653 char gf
[sizeof ("RS\0")];
3654 char ff
[sizeof ("EGI\0")];
3656 int ncompat
; /* number of compatible */
3657 char **compatp
; /* compatible ptrs */
3659 char *nname
; /* nodename */
3660 char *dname
; /* driver name */
3668 uchar_t
*iqd
= (uchar_t
*)inq
;
3671 * Nodename_aliases: This table was originally designed to be
3672 * implemented via a new nodename_aliases file - a peer to the
3673 * driver_aliases that selects a nodename based on compatible
3674 * forms in much the same say driver_aliases is used to select
3675 * driver bindings from compatible forms. Each compatible form
3676 * is an 'alias'. Until a more general need for a
3677 * nodename_aliases file exists, which may never occur, the
3678 * scsi mappings are described here via a compiled in table.
3680 * This table contains nodename mappings for self-identifying
3681 * scsi devices enumerated by the Solaris kernel. For a given
3682 * device, the highest precedence "compatible" form with a
3683 * mapping is used to select the nodename for the device. This
3684 * will typically be a generic nodename, however in some legacy
3685 * compatibility cases a driver nodename mapping may be selected.
3687 * Because of possible breakage associated with switching SCSI
3688 * target devices from driver nodenames to generic nodenames,
3689 * we are currently unable to support generic nodenames for all
3690 * SCSI devices (binding-sets). Although /devices paths are
3691 * defined as unstable, avoiding possible breakage is
3692 * important. Some of the newer SCSI transports (USB) already
3693 * use generic nodenames. All new SCSI transports and target
3694 * devices should use generic nodenames. At times this decision
3695 * may be architecture dependent (sparc .vs. intel) based on when
3696 * a transport was supported on a particular architecture.
3698 * We provide a base set of generic nodename mappings based on
3699 * scsiclass dtype and higher-precedence driver nodename
3700 * mappings based on scsa "binding-set" to cover legacy
3701 * issues. The binding-set is typically associated with
3702 * "scsi-binding-set" property value of the HBA. The legacy
3703 * mappings are provided independent of whether the driver they
3704 * refer to is installed. This allows a correctly named node
3705 * be created at discovery time, and binding to occur when/if
3706 * an add_drv of the legacy driver occurs.
3708 * We also have mappings for legacy SUN hardware that
3709 * misidentifies itself (enclosure services which identify
3710 * themselves as processors). All future hardware should use
3711 * the correct dtype.
3713 * As SCSI HBAs are modified to use the SCSA interfaces for
3714 * self-identifying SCSI target devices (PSARC/2004/116) the
3715 * nodename_aliases table (PSARC/2004/420) should be augmented
3716 * with legacy mappings in order to maintain compatibility with
3717 * existing /devices paths, especially for devices that house
3718 * an OS. Failure to do this may cause upgrade problems.
3719 * Additions for new target devices or transports should not
3720 * add scsa binding-set compatible mappings.
3722 static struct nodename_aliases
{
3723 char *na_nodename
; /* nodename */
3724 char *na_alias
; /* compatible form match */
3726 /* # mapping to generic nodenames based on scsi dtype */
3727 {"disk", "scsiclass,00"},
3728 {"tape", "scsiclass,01"},
3729 {"printer", "scsiclass,02"},
3730 {"processor", "scsiclass,03"},
3731 {"worm", "scsiclass,04"},
3732 {"cdrom", "scsiclass,05"},
3733 {"scanner", "scsiclass,06"},
3734 {"optical-disk", "scsiclass,07"},
3735 {"medium-changer", "scsiclass,08"},
3736 {"obsolete", "scsiclass,09"},
3737 {"prepress-a", "scsiclass,0a"},
3738 {"prepress-b", "scsiclass,0b"},
3739 {"array-controller", "scsiclass,0c"},
3740 {"enclosure", "scsiclass,0d"},
3741 {"disk", "scsiclass,0e"},
3742 {"card-reader", "scsiclass,0f"},
3743 {"bridge", "scsiclass,10"},
3744 {"object-store", "scsiclass,11"},
3745 {"reserved", "scsiclass,12"},
3746 {"reserved", "scsiclass,13"},
3747 {"reserved", "scsiclass,14"},
3748 {"reserved", "scsiclass,15"},
3749 {"reserved", "scsiclass,16"},
3750 {"reserved", "scsiclass,17"},
3751 {"reserved", "scsiclass,18"},
3752 {"reserved", "scsiclass,19"},
3753 {"reserved", "scsiclass,1a"},
3754 {"reserved", "scsiclass,1b"},
3755 {"reserved", "scsiclass,1c"},
3756 {"reserved", "scsiclass,1d"},
3757 {"well-known-lun", "scsiclass,1e"},
3758 {"unknown", "scsiclass,1f"},
3761 /* # legacy mapping to driver nodenames for fcp binding-set */
3762 {"ssd", "scsa,00.bfcp"},
3763 {"st", "scsa,01.bfcp"},
3764 {"sgen", "scsa,08.bfcp"},
3765 {"ses", "scsa,0d.bfcp"},
3767 /* # legacy mapping to driver nodenames for vhci binding-set */
3768 {"ssd", "scsa,00.bvhci"},
3769 {"st", "scsa,01.bvhci"},
3770 {"sgen", "scsa,08.bvhci"},
3771 {"ses", "scsa,0d.bvhci"},
3773 /* # for x86 fcp and vhci use generic nodenames */
3776 /* # legacy mapping to driver nodenames for spi binding-set */
3777 {"sd", "scsa,00.bspi"},
3778 {"sd", "scsa,05.bspi"},
3779 {"sd", "scsa,07.bspi"},
3780 {"st", "scsa,01.bspi"},
3781 {"ses", "scsa,0d.bspi"},
3783 /* # SUN misidentified spi hardware */
3784 {"ses", "scsiclass,03.vSUN.pD2"},
3785 {"ses", "scsiclass,03.vSYMBIOS.pD1000"},
3787 /* # legacy mapping to driver nodenames for atapi binding-set */
3788 {"sd", "scsa,00.batapi"},
3789 {"sd", "scsa,05.batapi"},
3790 {"sd", "scsa,07.batapi"},
3791 {"st", "scsa,01.batapi"},
3792 {"unknown", "scsa,0d.batapi"},
3794 /* # legacy mapping to generic nodenames for usb binding-set */
3795 {"disk", "scsa,05.busb"},
3796 {"disk", "scsa,07.busb"},
3797 {"changer", "scsa,08.busb"},
3798 {"comm", "scsa,09.busb"},
3799 {"array_ctlr", "scsa,0c.busb"},
3800 {"esi", "scsa,0d.busb"},
3803 * mapping nodenames for mpt based on scsi dtype
3804 * for being compatible with the original node names
3805 * under mpt controller
3807 {"sd", "scsa,00.bmpt"},
3808 {"sd", "scsa,05.bmpt"},
3809 {"sd", "scsa,07.bmpt"},
3810 {"st", "scsa,01.bmpt"},
3811 {"ses", "scsa,0d.bmpt"},
3812 {"sgen", "scsa,08.bmpt"},
3815 struct nodename_aliases
*nap
;
3817 /* NOTE: drivernamep can be NULL */
3818 ASSERT(nodenamep
&& compatiblep
&& ncompatiblep
&&
3819 (binding_set
== NULL
|| (strlen(binding_set
) <= 8)));
3820 if ((nodenamep
== NULL
) || (compatiblep
== NULL
) ||
3821 (ncompatiblep
== NULL
))
3825 * In order to reduce runtime we allocate one block of memory that
3826 * contains both the NULL terminated array of pointers to compatible
3827 * forms and the individual compatible strings. This block is
3828 * somewhat larger than needed, but is short lived - it only exists
3829 * until the caller can transfer the information into the "compatible"
3830 * string array property and call scsi_hba_nodename_compatible_free.
3832 tlen
= NCOMPAT
* COMPAT_LONGEST
;
3833 compatp
= kmem_alloc((NCOMPAT
* sizeof (char *)) + tlen
, KM_SLEEP
);
3835 /* convert inquiry data from SCSI ASCII to 1275 string */
3836 (void) string_scsi_to_1275(vid
, inq
->inq_vid
,
3837 sizeof (inq
->inq_vid
));
3838 (void) string_scsi_to_1275(pid
, inq
->inq_pid
,
3839 sizeof (inq
->inq_pid
));
3840 (void) string_scsi_to_1275(rev
, inq
->inq_revision
,
3841 sizeof (inq
->inq_revision
));
3842 ASSERT((strlen(vid
) <= sizeof (inq
->inq_vid
)) &&
3843 (strlen(pid
) <= sizeof (inq
->inq_pid
)) &&
3844 (strlen(rev
) <= sizeof (inq
->inq_revision
)));
3847 * Form flags in ***ALPHABETICAL*** order within form-group:
3849 * NOTE: When adding a new flag to an existing form-group, careful
3850 * consideration must be given to not breaking existing bindings
3851 * based on that form-group.
3855 * generic form-group flags
3857 * Set when inq_rmb is set and for well known scsi dtypes. For a
3858 * bus where the entire device is removable (like USB), we expect
3859 * the HBA to intercept the inquiry data and set inq_rmb.
3860 * Since OBP does not distinguish removable media in its generic
3861 * name selection we avoid setting the 'R' flag if the root is not
3864 * Set when the device type is SAT-TE.
3867 dtype_device
= inq
->inq_dtype
& DTYPE_MASK
;
3868 if (modrootloaded
&& (inq
->inq_rmb
||
3869 (dtype_device
== DTYPE_WORM
) ||
3870 (dtype_device
== DTYPE_RODIRECT
) ||
3871 (dtype_device
== DTYPE_OPTICAL
)))
3872 gf
[i
++] = 'R'; /* removable */
3875 if (modrootloaded
&&
3876 (dtype_device
== DTYPE_PROCESSOR
) &&
3877 (strncmp((char *)&iqd
[44], "SAF-TE", 4) == 0))
3882 * failover form-group flags
3883 * E Explicit Target_Port_Group_Supported:
3884 * Set for a device that has a GUID if inq_tpgse also set.
3886 * Set when we have identity information, can determine a devid
3887 * from the identity information, and can generate a guid from
3889 * I Implicit Target_Port_Group_Supported:
3890 * Set for a device that has a GUID if inq_tpgs also set.
3893 if ((inq80
|| inq83
) &&
3894 (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, NULL
,
3895 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
3896 &devid
) == DDI_SUCCESS
)) {
3897 guid
= ddi_devid_to_guid(devid
);
3898 ddi_devid_free(devid
);
3901 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_EXPLICIT
))
3902 ff
[i
++] = 'E'; /* EXPLICIT TPGS */
3904 ff
[i
++] = 'G'; /* GUID */
3905 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_IMPLICIT
))
3906 ff
[i
++] = 'I'; /* IMPLICIT TPGS */
3909 ddi_devid_free_guid(guid
);
3912 * Construct all applicable compatible forms. See comment at the
3913 * head of the function for a description of the compatible forms.
3916 p
= (char *)(compatp
+ NCOMPAT
);
3918 /* ( 0) driver (optional, not documented in scsi(4)) */
3921 (void) snprintf(p
, tlen
, "%s", compat0
);
3922 len
= strlen(p
) + 1;
3927 /* ( 1) scsiclass,DDEEFFF.vV.pP.rR */
3928 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
&& *rev
) {
3930 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s.r%s",
3931 dtype_node
, dtype_device
, gf
, vid
, pid
, rev
);
3932 len
= strlen(p
) + 1;
3937 /* ( 2) scsiclass,DDEE.vV.pP.rR */
3938 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
&& *rev
) {
3940 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s.r%s",
3941 dtype_node
, dtype_device
, vid
, pid
, rev
);
3942 len
= strlen(p
) + 1;
3947 /* ( 3) scsiclass,DDFFF.vV.pP.rR */
3948 if (*gf
&& *vid
&& *pid
&& *rev
) {
3950 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s.r%s",
3951 dtype_node
, gf
, vid
, pid
, rev
);
3952 len
= strlen(p
) + 1;
3957 /* ( 4) scsiclass,DD.vV.pP.rR */
3958 if (*vid
&& *pid
&& *rev
) {
3960 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s.r%s",
3961 dtype_node
, vid
, pid
, rev
);
3962 len
= strlen(p
) + 1;
3967 /* ( 5) scsiclass,DDEEFFF.vV.pP */
3968 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
) {
3970 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s",
3971 dtype_node
, dtype_device
, gf
, vid
, pid
);
3972 len
= strlen(p
) + 1;
3977 /* ( 6) scsiclass,DDEE.vV.pP */
3978 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
) {
3980 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s",
3981 dtype_node
, dtype_device
, vid
, pid
);
3982 len
= strlen(p
) + 1;
3987 /* ( 7) scsiclass,DDFFF.vV.pP */
3988 if (*gf
&& *vid
&& *pid
) {
3990 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s",
3991 dtype_node
, gf
, vid
, pid
);
3992 len
= strlen(p
) + 1;
3997 /* ( 8) scsiclass,DD.vV.pP */
4000 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s",
4001 dtype_node
, vid
, pid
);
4002 len
= strlen(p
) + 1;
4007 /* (8.5) scsa,DD.bB (not documented in scsi(4)) */
4010 (void) snprintf(p
, tlen
, "scsa,%02x.b%s",
4011 dtype_node
, binding_set
);
4012 len
= strlen(p
) + 1;
4017 /* ( 9) scsiclass,DDEEFFF */
4018 if ((dtype_device
!= dtype_node
) && *gf
) {
4020 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s",
4021 dtype_node
, dtype_device
, gf
);
4022 len
= strlen(p
) + 1;
4027 /* (10) scsiclass,DDEE */
4028 if (dtype_device
!= dtype_node
) {
4030 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x",
4031 dtype_node
, dtype_device
);
4032 len
= strlen(p
) + 1;
4037 /* (11) scsiclass,DDFFF */
4040 (void) snprintf(p
, tlen
, "scsiclass,%02x%s",
4042 len
= strlen(p
) + 1;
4047 /* (12) scsiclass,DD */
4049 (void) snprintf(p
, tlen
, "scsiclass,%02x", dtype_node
);
4050 len
= strlen(p
) + 1;
4054 /* (12.5) scsa.fFFF */
4057 (void) snprintf(p
, tlen
, "scsa.f%s", ff
);
4058 len
= strlen(p
) + 1;
4063 /* (13) scsiclass */
4065 (void) snprintf(p
, tlen
, "scsiclass");
4066 len
= strlen(p
) + 1;
4071 *csp
= NULL
; /* NULL terminate array of pointers */
4072 ncompat
= csp
- compatp
;
4075 * When determining a nodename, a nodename_aliases specified
4076 * mapping has precedence over using a driver_aliases specified
4077 * driver binding as a nodename.
4079 * See if any of the compatible forms have a nodename_aliases
4080 * specified nodename. These mappings are described by
4081 * nodename_aliases entries like:
4083 * disk "scsiclass,00"
4084 * enclosure "scsiclass,03.vSYMBIOS.pD1000"
4085 * ssd "scsa,00.bfcp"
4087 * All nodename_aliases mappings should idealy be to generic
4088 * names, however a higher precedence legacy mapping to a
4089 * driver name may exist. The highest precedence mapping
4090 * provides the nodename, so legacy driver nodename mappings
4091 * (if they exist) take precedence over generic nodename
4094 for (nname
= NULL
, csp
= compatp
; (nname
== NULL
) && *csp
; csp
++) {
4095 for (nap
= na
; nap
->na_nodename
; nap
++) {
4096 if (strcmp(*csp
, nap
->na_alias
) == 0) {
4097 nname
= nap
->na_nodename
;
4104 * Determine the driver name based on compatible (which may
4105 * have the passed in compat0 as the first item). The driver_aliases
4106 * file has entries like
4110 * that map compatible forms to specific drivers. These entries are
4111 * established by add_drv/update_drv. We use the most specific
4112 * driver binding as the nodename. This matches the eventual
4113 * ddi_driver_compatible_major() binding that will be
4114 * established by bind_node()
4116 for (dname
= NULL
, csp
= compatp
; *csp
; csp
++) {
4117 major
= ddi_name_to_major(*csp
);
4118 if ((major
== DDI_MAJOR_T_NONE
) ||
4119 (devnamesp
[major
].dn_flags
& DN_DRIVER_REMOVED
))
4121 if (dname
= ddi_major_to_name(major
))
4126 * If no nodename_aliases mapping exists then use the
4127 * driver_aliases specified driver binding as a nodename.
4132 /* return results */
4134 *nodenamep
= kmem_alloc(strlen(nname
) + 1, KM_SLEEP
);
4135 (void) strcpy(*nodenamep
, nname
);
4140 * If no nodename could be determined return a special
4141 * 'compatible' to be used for a diagnostic message. This
4142 * compatible contains all compatible forms concatenated
4143 * into a single string pointed to by the first element.
4145 for (csp
= compatp
; *(csp
+ 1); csp
++)
4146 *((*csp
) + strlen(*csp
)) = ' ';
4147 *(compatp
+ 1) = NULL
;
4153 *drivernamep
= kmem_alloc(strlen(dname
) + 1, KM_SLEEP
);
4154 (void) strcpy(*drivernamep
, dname
);
4156 *drivernamep
= NULL
;
4158 *compatiblep
= compatp
;
4159 *ncompatiblep
= ncompat
;
4163 * Free allocations associated with scsi_hba_ident_nodename_compatible_get.
4166 scsi_hba_ident_nodename_compatible_free(char *nodename
, char *drivername
,
4170 kmem_free(nodename
, strlen(nodename
) + 1);
4172 kmem_free(drivername
, strlen(drivername
) + 1);
4174 kmem_free(compatible
, (NCOMPAT
* sizeof (char *)) +
4175 (NCOMPAT
* COMPAT_LONGEST
));
4179 scsi_hba_nodename_compatible_get(struct scsi_inquiry
*inq
,
4180 char *binding_set
, int dtype_node
, char *compat0
,
4181 char **nodenamep
, char ***compatiblep
, int *ncompatiblep
)
4183 scsi_hba_ident_nodename_compatible_get(inq
,
4184 NULL
, 0, NULL
, 0, binding_set
, dtype_node
, compat0
, nodenamep
,
4185 NULL
, compatiblep
, ncompatiblep
);
4189 scsi_hba_nodename_compatible_free(char *nodename
, char **compatible
)
4191 scsi_hba_ident_nodename_compatible_free(nodename
, NULL
, compatible
);
4194 /* return the unit_address associated with a scsi_device */
4196 scsi_device_unit_address(struct scsi_device
*sd
)
4198 mdi_pathinfo_t
*pip
;
4200 ASSERT(sd
&& sd
->sd_dev
);
4201 if ((sd
== NULL
) || (sd
->sd_dev
== NULL
))
4204 pip
= (mdi_pathinfo_t
*)sd
->sd_pathinfo
;
4206 return (mdi_pi_get_addr(pip
));
4208 return (ddi_get_name_addr(sd
->sd_dev
));
4211 /* scsi_device property interfaces */
4212 #define _TYPE_DEFINED(flags) \
4213 (((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) || \
4214 ((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_DEVICE))
4216 #define _DEVICE_PIP(sd, flags) \
4217 ((((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) && \
4218 sd->sd_pathinfo) ? (mdi_pathinfo_t *)sd->sd_pathinfo : NULL)
4221 scsi_device_prop_get_int(struct scsi_device
*sd
, uint_t flags
,
4222 char *name
, int defval
)
4224 mdi_pathinfo_t
*pip
;
4229 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4230 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4231 !_TYPE_DEFINED(flags
))
4234 pip
= _DEVICE_PIP(sd
, flags
);
4236 rv
= mdi_prop_lookup_int(pip
, name
, &data
);
4237 if (rv
== DDI_PROP_SUCCESS
)
4240 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, sd
->sd_dev
,
4241 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4247 scsi_device_prop_get_int64(struct scsi_device
*sd
, uint_t flags
,
4248 char *name
, int64_t defval
)
4250 mdi_pathinfo_t
*pip
;
4255 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4256 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4257 !_TYPE_DEFINED(flags
))
4260 pip
= _DEVICE_PIP(sd
, flags
);
4262 rv
= mdi_prop_lookup_int64(pip
, name
, &data
);
4263 if (rv
== DDI_PROP_SUCCESS
)
4266 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, sd
->sd_dev
,
4267 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4272 scsi_device_prop_lookup_byte_array(struct scsi_device
*sd
, uint_t flags
,
4273 char *name
, uchar_t
**data
, uint_t
*nelements
)
4275 mdi_pathinfo_t
*pip
;
4278 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4279 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4280 !_TYPE_DEFINED(flags
))
4281 return (DDI_PROP_INVAL_ARG
);
4283 pip
= _DEVICE_PIP(sd
, flags
);
4285 rv
= mdi_prop_lookup_byte_array(pip
, name
, data
, nelements
);
4287 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4288 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4289 name
, data
, nelements
);
4294 scsi_device_prop_lookup_int_array(struct scsi_device
*sd
, uint_t flags
,
4295 char *name
, int **data
, uint_t
*nelements
)
4297 mdi_pathinfo_t
*pip
;
4300 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4301 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4302 !_TYPE_DEFINED(flags
))
4303 return (DDI_PROP_INVAL_ARG
);
4305 pip
= _DEVICE_PIP(sd
, flags
);
4307 rv
= mdi_prop_lookup_int_array(pip
, name
, data
, nelements
);
4309 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4310 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4311 name
, data
, nelements
);
4317 scsi_device_prop_lookup_string(struct scsi_device
*sd
, uint_t flags
,
4318 char *name
, char **data
)
4320 mdi_pathinfo_t
*pip
;
4323 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4324 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4325 !_TYPE_DEFINED(flags
))
4326 return (DDI_PROP_INVAL_ARG
);
4328 pip
= _DEVICE_PIP(sd
, flags
);
4330 rv
= mdi_prop_lookup_string(pip
, name
, data
);
4332 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, sd
->sd_dev
,
4333 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4339 scsi_device_prop_lookup_string_array(struct scsi_device
*sd
, uint_t flags
,
4340 char *name
, char ***data
, uint_t
*nelements
)
4342 mdi_pathinfo_t
*pip
;
4345 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4346 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4347 !_TYPE_DEFINED(flags
))
4348 return (DDI_PROP_INVAL_ARG
);
4350 pip
= _DEVICE_PIP(sd
, flags
);
4352 rv
= mdi_prop_lookup_string_array(pip
, name
, data
, nelements
);
4354 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4355 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4356 name
, data
, nelements
);
4361 scsi_device_prop_update_byte_array(struct scsi_device
*sd
, uint_t flags
,
4362 char *name
, uchar_t
*data
, uint_t nelements
)
4364 mdi_pathinfo_t
*pip
;
4367 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4368 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4369 !_TYPE_DEFINED(flags
))
4370 return (DDI_PROP_INVAL_ARG
);
4372 pip
= _DEVICE_PIP(sd
, flags
);
4374 rv
= mdi_prop_update_byte_array(pip
, name
, data
, nelements
);
4376 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4377 name
, data
, nelements
);
4382 scsi_device_prop_update_int(struct scsi_device
*sd
, uint_t flags
,
4383 char *name
, int data
)
4385 mdi_pathinfo_t
*pip
;
4388 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4389 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4390 !_TYPE_DEFINED(flags
))
4391 return (DDI_PROP_INVAL_ARG
);
4393 pip
= _DEVICE_PIP(sd
, flags
);
4395 rv
= mdi_prop_update_int(pip
, name
, data
);
4397 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, sd
->sd_dev
,
4403 scsi_device_prop_update_int64(struct scsi_device
*sd
, uint_t flags
,
4404 char *name
, int64_t data
)
4406 mdi_pathinfo_t
*pip
;
4409 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4410 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4411 !_TYPE_DEFINED(flags
))
4412 return (DDI_PROP_INVAL_ARG
);
4414 pip
= _DEVICE_PIP(sd
, flags
);
4416 rv
= mdi_prop_update_int64(pip
, name
, data
);
4418 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, sd
->sd_dev
,
4424 scsi_device_prop_update_int_array(struct scsi_device
*sd
, uint_t flags
,
4425 char *name
, int *data
, uint_t nelements
)
4427 mdi_pathinfo_t
*pip
;
4430 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4431 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4432 !_TYPE_DEFINED(flags
))
4433 return (DDI_PROP_INVAL_ARG
);
4435 pip
= _DEVICE_PIP(sd
, flags
);
4437 rv
= mdi_prop_update_int_array(pip
, name
, data
, nelements
);
4439 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4440 name
, data
, nelements
);
4445 scsi_device_prop_update_string(struct scsi_device
*sd
, uint_t flags
,
4446 char *name
, char *data
)
4448 mdi_pathinfo_t
*pip
;
4451 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4452 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4453 !_TYPE_DEFINED(flags
))
4454 return (DDI_PROP_INVAL_ARG
);
4456 pip
= _DEVICE_PIP(sd
, flags
);
4458 rv
= mdi_prop_update_string(pip
, name
, data
);
4460 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, sd
->sd_dev
,
4466 scsi_device_prop_update_string_array(struct scsi_device
*sd
, uint_t flags
,
4467 char *name
, char **data
, uint_t nelements
)
4469 mdi_pathinfo_t
*pip
;
4472 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4473 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4474 !_TYPE_DEFINED(flags
))
4475 return (DDI_PROP_INVAL_ARG
);
4477 pip
= _DEVICE_PIP(sd
, flags
);
4479 rv
= mdi_prop_update_string_array(pip
, name
, data
, nelements
);
4481 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4482 name
, data
, nelements
);
4487 scsi_device_prop_remove(struct scsi_device
*sd
, uint_t flags
, char *name
)
4489 mdi_pathinfo_t
*pip
;
4492 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4493 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4494 !_TYPE_DEFINED(flags
))
4495 return (DDI_PROP_INVAL_ARG
);
4497 pip
= _DEVICE_PIP(sd
, flags
);
4499 rv
= mdi_prop_remove(pip
, name
);
4501 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, sd
->sd_dev
, name
);
4506 scsi_device_prop_free(struct scsi_device
*sd
, uint_t flags
, void *data
)
4508 mdi_pathinfo_t
*pip
;
4510 ASSERT(sd
&& data
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4511 if ((sd
== NULL
) || (data
== NULL
) || (sd
->sd_dev
== NULL
) ||
4512 !_TYPE_DEFINED(flags
))
4515 pip
= _DEVICE_PIP(sd
, flags
);
4517 (void) mdi_prop_free(data
);
4519 ddi_prop_free(data
);
4522 /* SMP device property interfaces */
4524 smp_device_prop_get_int(struct smp_device
*smp_sd
, char *name
, int defval
)
4528 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4529 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4532 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4533 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4539 smp_device_prop_get_int64(struct smp_device
*smp_sd
, char *name
, int64_t defval
)
4543 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4544 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4547 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4548 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4553 smp_device_prop_lookup_byte_array(struct smp_device
*smp_sd
, char *name
,
4554 uchar_t
**data
, uint_t
*nelements
)
4558 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4559 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4560 return (DDI_PROP_INVAL_ARG
);
4562 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4563 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4564 name
, data
, nelements
);
4569 smp_device_prop_lookup_int_array(struct smp_device
*smp_sd
, char *name
,
4570 int **data
, uint_t
*nelements
)
4574 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4575 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4576 return (DDI_PROP_INVAL_ARG
);
4578 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4579 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4580 name
, data
, nelements
);
4586 smp_device_prop_lookup_string(struct smp_device
*smp_sd
, char *name
,
4591 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4592 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4593 return (DDI_PROP_INVAL_ARG
);
4595 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4596 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4602 smp_device_prop_lookup_string_array(struct smp_device
*smp_sd
, char *name
,
4603 char ***data
, uint_t
*nelements
)
4607 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4608 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4609 return (DDI_PROP_INVAL_ARG
);
4611 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4612 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4613 name
, data
, nelements
);
4618 smp_device_prop_update_byte_array(struct smp_device
*smp_sd
, char *name
,
4619 uchar_t
*data
, uint_t nelements
)
4623 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4624 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4625 return (DDI_PROP_INVAL_ARG
);
4627 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4628 name
, data
, nelements
);
4633 smp_device_prop_update_int(struct smp_device
*smp_sd
, char *name
, int data
)
4637 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4638 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4639 return (DDI_PROP_INVAL_ARG
);
4641 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4647 smp_device_prop_update_int64(struct smp_device
*smp_sd
, char *name
,
4652 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4653 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4654 return (DDI_PROP_INVAL_ARG
);
4656 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4662 smp_device_prop_update_int_array(struct smp_device
*smp_sd
, char *name
,
4663 int *data
, uint_t nelements
)
4667 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4668 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4669 return (DDI_PROP_INVAL_ARG
);
4671 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4672 name
, data
, nelements
);
4677 smp_device_prop_update_string(struct smp_device
*smp_sd
, char *name
, char *data
)
4681 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4682 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4683 return (DDI_PROP_INVAL_ARG
);
4685 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4691 smp_device_prop_update_string_array(struct smp_device
*smp_sd
, char *name
,
4692 char **data
, uint_t nelements
)
4696 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4697 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4698 return (DDI_PROP_INVAL_ARG
);
4700 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4701 name
, data
, nelements
);
4706 smp_device_prop_remove(struct smp_device
*smp_sd
, char *name
)
4710 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4711 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4712 return (DDI_PROP_INVAL_ARG
);
4714 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
, name
);
4719 smp_device_prop_free(struct smp_device
*smp_sd
, void *data
)
4721 ASSERT(smp_sd
&& data
&& smp_sd
->smp_sd_dev
);
4722 if ((smp_sd
== NULL
) || (data
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4725 ddi_prop_free(data
);
4729 * scsi_hba_ua_set: given "unit-address" string, set properties.
4731 * Function to set the properties on a devinfo or pathinfo node from
4732 * the "unit-address" part of a "name@unit-address" /devices path 'name'
4735 * This function works in conjunction with scsi_ua_get()/scsi_hba_ua_get()
4736 * (and possibly with an HBA driver's tran_tgt_init() implementation).
4739 scsi_hba_ua_set(char *ua
, dev_info_t
*dchild
, mdi_pathinfo_t
*pchild
)
4749 /* Caller must choose to decorate devinfo *or* pathinfo */
4750 ASSERT((dchild
!= NULL
) ^ (pchild
!= NULL
));
4751 if (dchild
&& pchild
)
4755 * generic implementation based on "tgt,lun[,sfunc]" address form.
4756 * parse hex "tgt" part of "tgt,lun[,sfunc]"
4759 tgt_port_end
= NULL
;
4760 for (tgt
= 0; *p
&& *p
!= ','; p
++) {
4761 if (*p
>= '0' && *p
<= '9')
4762 tgt
= (tgt
<< 4) + (*p
- '0');
4763 else if (*p
>= 'a' && *p
<= 'f')
4764 tgt
= (tgt
<< 4) + 10 + (*p
- 'a');
4766 tgt
= -1; /* non-numeric */
4769 * if non-numeric or our of range set tgt to -1 and
4774 for (; *p
&& *p
!= ','; p
++)
4781 /* parse hex ",lun" part of "tgt,lun[,sfunc]" */
4784 for (lun64
= 0; *p
&& *p
!= ','; p
++) {
4785 if (*p
>= '0' && *p
<= '9')
4786 lun64
= (lun64
<< 4) + (*p
- '0');
4787 else if (*p
>= 'a' && *p
<= 'f')
4788 lun64
= (lun64
<< 4) + 10 + (*p
- 'a');
4793 /* parse hex ",sfunc" part of "tgt,lun[,sfunc]" */
4796 for (sfunc
= 0; *p
; p
++) {
4797 if (*p
>= '0' && *p
<= '9')
4798 sfunc
= (sfunc
<< 4) + (*p
- '0');
4799 else if (*p
>= 'a' && *p
<= 'f')
4800 sfunc
= (sfunc
<< 4) + 10 + (*p
- 'a');
4809 * Decorate a devinfo node with unit address properties.
4810 * This adds the the addressing properties needed to
4811 * DDI_CTLOPS_UNINITCHILD the devinfo node (i.e. perform
4812 * the reverse operation - form unit address from properties).
4814 if ((tgt
!= -1) && (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4815 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4819 tgt_port_len
= tgt_port_end
- ua
+ 1;
4820 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4821 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4822 if (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
4823 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4825 kmem_free(tgt_port
, tgt_port_len
);
4828 kmem_free(tgt_port
, tgt_port_len
);
4831 /* Set the appropriate lun properties. */
4832 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4833 if (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4834 SCSI_ADDR_PROP_LUN
, (int)lun64
) != DDI_PROP_SUCCESS
)
4837 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, dchild
,
4838 SCSI_ADDR_PROP_LUN64
, lun64
) != DDI_PROP_SUCCESS
)
4841 /* Set the sfunc property */
4842 if ((sfunc
!= -1) &&
4843 (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4844 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4846 } else if (pchild
) {
4848 * Decorate a pathinfo node with unit address properties.
4850 if ((tgt
!= -1) && (mdi_prop_update_int(pchild
,
4851 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4855 tgt_port_len
= tgt_port_end
- ua
+ 1;
4856 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4857 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4858 if (mdi_prop_update_string(pchild
,
4859 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4861 kmem_free(tgt_port
, tgt_port_len
);
4864 kmem_free(tgt_port
, tgt_port_len
);
4867 /* Set the appropriate lun properties */
4868 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4869 if (mdi_prop_update_int(pchild
, SCSI_ADDR_PROP_LUN
,
4870 (int)lun64
) != DDI_PROP_SUCCESS
)
4874 if (mdi_prop_update_int64(pchild
, SCSI_ADDR_PROP_LUN64
,
4875 lun64
) != DDI_PROP_SUCCESS
)
4878 /* Set the sfunc property */
4879 if ((sfunc
!= -1) &&
4880 (mdi_prop_update_int(pchild
,
4881 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4888 * Private ndi_devi_find/mdi_pi_find implementation - find the child
4889 * dev_info/path_info of self whose phci name matches "name@caddr".
4890 * We have our own implementation because we need to search with both
4891 * forms of sibling lists (dev_info and path_info) and we need to be able
4892 * to search with a NULL name in order to find siblings already associated
4893 * with a given unit-address (same @addr). NOTE: NULL name search will never
4894 * return probe node.
4896 * If pchildp is NULL and we find a pathinfo child, we return the client
4897 * devinfo node in *dchildp.
4899 * The init flag argument should be clear when called from places where
4900 * recursion could occur (like scsi_busctl_initchild) and when the caller
4901 * has already performed a search for name@addr with init set (performance).
4903 * Future: Integrate ndi_devi_findchild_by_callback into scsi_findchild.
4906 scsi_findchild(dev_info_t
*self
, char *name
, char *addr
, int init
,
4907 dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
)
4909 dev_info_t
*dchild
; /* devinfo child */
4910 mdi_pathinfo_t
*pchild
; /* pathinfo child */
4911 int found
= CHILD_TYPE_NONE
;
4914 ASSERT(self
&& DEVI_BUSY_OWNED(self
));
4915 ASSERT(addr
&& dchildp
);
4916 if ((self
== NULL
) || (addr
== NULL
) || (dchildp
== NULL
))
4917 return (CHILD_TYPE_NONE
);
4925 /* Walk devinfo child list to find a match */
4926 for (dchild
= ddi_get_child(self
); dchild
;
4927 dchild
= ddi_get_next_sibling(dchild
)) {
4928 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
4931 daddr
= ddi_get_name_addr(dchild
);
4932 if (daddr
&& (strcmp(addr
, daddr
) == 0) &&
4934 (strcmp(name
, DEVI(dchild
)->devi_node_name
) == 0))) {
4936 * If we are asked to find "anything" at a given
4937 * unit-address (name == NULL), we don't realy want
4938 * to find the 'probe' node. The existance of
4939 * a probe node on a 'name == NULL' search should
4940 * fail. This will trigger slow-path code where
4941 * we explicity look for, and synchronize against,
4942 * a node named "probe" at the unit-address.
4944 if ((name
== NULL
) &&
4945 scsi_hba_devi_is_barrier(dchild
)) {
4946 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4947 "%s@%s 'probe' devinfo found, skip",
4948 name
? name
: "", addr
));
4952 /* We have found a match. */
4953 found
|= CHILD_TYPE_DEVINFO
;
4954 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4955 "%s@%s devinfo found", name
? name
: "", addr
));
4956 *dchildp
= dchild
; /* devinfo found */
4962 * Walk pathinfo child list to find a match.
4964 * NOTE: Unlike devinfo nodes, pathinfo nodes have a string searchable
4965 * unit-address from creation - so there is no need for an 'init'
4966 * search block of code for pathinfo nodes below.
4968 pchild
= mdi_pi_find(self
, NULL
, addr
);
4971 * NOTE: If name specified and we match a pathinfo unit
4972 * address, we don't check the client node name.
4975 *ppi
= mdi_pi_get_path_instance(pchild
);
4976 found
|= CHILD_TYPE_PATHINFO
;
4979 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
4980 "%s pathinfo found", mdi_pi_spathname(pchild
)));
4981 *pchildp
= pchild
; /* pathinfo found */
4982 } else if (*dchildp
== NULL
) {
4984 * Did not find a devinfo node, found a pathinfo node,
4985 * but caller did not ask us to return a pathinfo node:
4986 * we return the 'client' devinfo node instead (but
4987 * with CHILD_TYPE_PATHINFO 'found' return value).
4989 dchild
= mdi_pi_get_client(pchild
);
4990 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4991 "%s pathinfo found, client switch",
4992 mdi_pi_spathname(pchild
)));
4995 * A pathinfo node always has a 'client' devinfo node,
4996 * but we need to ensure that the 'client' is
4997 * initialized and has a scsi_device structure too.
5000 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
) {
5001 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5002 "%s found client, initchild",
5003 mdi_pi_spathname(pchild
)));
5004 (void) ddi_initchild(ddi_get_parent(dchild
),
5007 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
) {
5008 /* client found and initialized */
5011 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5012 "%s found client, but failed initchild",
5013 mdi_pi_spathname(pchild
)));
5018 /* Try devinfo again with initchild of uninitialized nodes */
5019 if ((found
== CHILD_TYPE_NONE
) && init
) {
5020 for (dchild
= ddi_get_child(self
); dchild
;
5021 dchild
= ddi_get_next_sibling(dchild
)) {
5022 /* skip if checked above */
5023 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
)
5025 /* attempt initchild to establish unit-address */
5026 (void) ddi_initchild(self
, dchild
);
5027 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
5029 daddr
= ddi_get_name_addr(dchild
);
5031 ((name
== NULL
) || (strcmp(name
,
5032 DEVI(dchild
)->devi_node_name
) == 0)) &&
5033 (strcmp(addr
, daddr
) == 0)) {
5034 found
|= CHILD_TYPE_DEVINFO
;
5035 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5036 "%s@%s devinfo found post initchild",
5037 name
? name
: "", addr
));
5038 *dchildp
= dchild
; /* devinfo found */
5039 break; /* node found */
5045 * We should never find devinfo and pathinfo at the same
5048 ASSERT(found
!= (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
));
5049 if (found
== (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
)) {
5050 found
= CHILD_TYPE_NONE
;
5058 * Given information about a child device (contained on probe node) construct
5059 * and return a pointer to the dynamic SID devinfo node associated with the
5060 * device. In the creation of this SID node a compatible property for the
5061 * device is formed and used to establish a nodename (via
5062 * /etc/nodename_aliases) and to bind a driver (via /etc/driver_aliases).
5064 * If this routine is called then we got a response from a device and
5065 * obtained the inquiry data from the device. Some inquiry results indicate
5066 * that the specific LUN we addressed does not exist, and we don't want to
5067 * bind a standard target driver to the node we create. Even though the
5068 * specific LUN is not usable, the framework may still want to bind a
5069 * target driver to the device for internal communication with the device -
5070 * an example would be issuing a report_lun to enumerate other LUNs under a
5071 * DPQ_NEVER LUN0. Another example would be wanting to known that the
5072 * DPQ_NEVER LUN0 device exists in BUS_CONFIG_ONE for non-existent LUN
5073 * caching optimizations. To support this we let the caller specify a
5074 * compatible property (or driver). If LUN0 inquiry data indicates that the
5075 * LUN does not exist then we establish compat0 as the highest precedence(0)
5076 * compatible form. If used, this compat0 driver will never be called on to
5077 * issue external commands to the device.
5079 * If no driver binds to the device using driver_alias we establish the driver
5080 * passed in as the node name.
5083 extern int e_devid_cache_pathinfo(mdi_pathinfo_t
*, ddi_devid_t
);
5086 scsi_device_createchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5087 struct scsi_device
*sdprobe
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
)
5097 char **compat
= NULL
;
5099 dev_info_t
*dchild
= NULL
;
5100 mdi_pathinfo_t
*pchild
= NULL
;
5101 dev_info_t
*probe
= sdprobe
->sd_dev
;
5102 struct scsi_inquiry
*inq
= sdprobe
->sd_inq
;
5103 uchar_t
*inq80
= NULL
;
5104 uchar_t
*inq83
= NULL
;
5105 uint_t inq80len
, inq83len
;
5106 char *binding_set
= NULL
;
5111 int have_cdevid
= 0;
5115 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5116 ASSERT(dchildp
&& pchildp
);
5119 * Determine the lun and whether the lun exists. We may need to create
5120 * a node for LUN0 (with compat0 driver binding) even if the lun does
5121 * not exist - so we can run report_lun to find additional LUNs.
5123 lun64
= scsi_addr_to_lun64(addr
);
5124 dtype
= inq
->inq_dtype
& DTYPE_MASK
; /* device */
5125 dpq
= inq
->inq_dtype
& DPQ_MASK
;
5126 dpq_vu
= inq
->inq_dtype
& DPQ_VUNIQ
? 1 : 0;
5128 dtype_node
= scsi_addr_to_sfunc(addr
); /* secondary function */
5129 if (dtype_node
== -1)
5130 dtype_node
= dtype
; /* node for device */
5132 lunexists
= (dtype
!= dtype_node
) || /* override */
5133 ((dpq_vu
== 0) && (dpq
== DPQ_POSSIBLE
)) || /* ANSII */
5134 (dpq_vu
&& (lun64
== 0)); /* VU LUN0 */
5135 if (dtype
== DTYPE_UNKNOWN
)
5138 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5139 "@%s dtype %x %x dpq_vu %d dpq %x: %d",
5140 addr
, dtype
, dtype_node
, dpq_vu
, dpq
, lunexists
));
5142 /* A non-existent LUN0 uses compatible_nodev. */
5144 compat0
= NULL
; /* compat0 not needed */
5145 } else if (lun64
== 0) {
5146 compat0
= compatible_nodev
;
5147 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5148 "@%s lun 0 with compat0 %s", addr
, compat0
));
5150 goto out
; /* no node created */
5152 /* Obtain identity information from probe node. */
5153 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5154 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-80",
5155 &inq80
, &inq80len
) != DDI_PROP_SUCCESS
)
5157 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5158 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-83",
5159 &inq83
, &inq83len
) != DDI_PROP_SUCCESS
)
5162 /* Get "scsi-binding-set" property (if there is one). */
5163 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
5164 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
5165 "scsi-binding-set", &binding_set
) == DDI_PROP_SUCCESS
)
5166 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
5167 "binding_set '%s'", binding_set
));
5169 /* determine the node name and compatible information */
5170 scsi_hba_ident_nodename_compatible_get(inq
,
5171 inq80
, inq80len
, inq83
, inq83len
, binding_set
, dtype_node
,
5172 compat0
, &nname
, &dname
, &compat
, &ncompat
);
5174 if (nname
== NULL
) {
5176 * We will not be able to create a node because we could not
5177 * determine a node name. Print out a NODRIVER level warning
5178 * message with the compatible forms for the device. Note that
5179 * there may be a driver.conf node that attaches to the device,
5180 * which is why we only produce this warning message for debug
5183 SCSI_HBA_LOG((_LOG(1), NULL
, self
,
5184 "no node_name for device @%s:\n compatible: %s",
5190 * FUTURE: some day we may want an accurate "compatible" on the probe
5191 * node so that vhci_is_dev_supported() in scsi_vhci could, at
5192 * least in part, determine/configure based on "compatible".
5194 * if (ndi_prop_update_string_array(DDI_DEV_T_NONE, probe,
5195 * "compatible", compat, ncompat) != DDI_PROP_SUCCESS) {
5196 * SCSI_HBA_LOG((_LOG(3), self, NULL,
5197 * "%s@%s failed probe compatible decoration",
5203 /* Encode devid from identity information. */
5204 if (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, dname
,
5205 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
5206 &devid
) == DDI_SUCCESS
) {
5209 /* Attempt to form guid from devid. */
5210 guid
= ddi_devid_to_guid(devid
);
5212 /* Produce string devid for debug. */
5213 devid_str
= ddi_devid_str_encode(devid
, NULL
);
5214 SCSI_HBA_LOG((_LOG(3), self
, probe
, "devid '%s' guid '%s'",
5215 devid_str
? devid_str
: "NULL", guid
? guid
: "NULL"));
5216 ddi_devid_str_free(devid_str
);
5221 * Determine if the device should be enumerated as under the vHCI
5222 * (client node) or under the pHCI. By convention scsi_vhci expects
5223 * the "cinfo" argument identity information to be represented as a
5224 * devinfo node with the needed information (i.e. the pHCI probe node).
5226 if ((guid
== NULL
) ||
5227 (mdi_is_dev_supported(MDI_HCI_CLASS_SCSI
, self
, sdprobe
) !=
5229 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==> devinfo"));
5232 * Enumerate under pHCI:
5234 * Create dynamic SID dchild node. No attempt is made to
5235 * transfer information (except the addressing and identity
5236 * information) from the probe node to the dynamic node since
5237 * there may be HBA specific side effects that the framework
5238 * does not known how to transfer.
5240 ndi_devi_alloc_sleep(self
, nname
,
5241 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
5244 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5247 * Decorate new node with addressing properties (via
5248 * scsi_hba_ua_set()), compatible, identity information, and
5251 if ((scsi_hba_ua_set(addr
, dchild
, NULL
) == 0) ||
5252 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, dchild
,
5253 "compatible", compat
, ncompat
) != DDI_PROP_SUCCESS
) ||
5254 (inq80
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5255 dchild
, "inquiry-page-80", inq80
, inq80len
) !=
5256 DDI_PROP_SUCCESS
)) ||
5257 (inq83
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5258 dchild
, "inquiry-page-83", inq83
, inq83len
) !=
5259 DDI_PROP_SUCCESS
)) ||
5260 (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
5261 "class", "scsi") != DDI_PROP_SUCCESS
)) {
5262 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5263 "devinfo @%s failed decoration", addr
));
5264 (void) scsi_hba_remove_node(dchild
);
5269 /* Bind the driver */
5270 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5271 /* need to bind in order to register a devid */
5272 SCSI_HBA_LOG((_LOGCFG
, NULL
, dchild
,
5273 "devinfo @%s created, no driver-> "
5274 "no devid_register", addr
));
5278 /* Register devid */
5280 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5281 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5282 "devinfo @%s created, "
5283 "devid register failed", addr
));
5285 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5286 "devinfo @%s created with devid", addr
));
5288 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5289 "devinfo @%s created, no devid", addr
));
5292 * Enumerate under vHCI:
5294 * Create a pathinfo pchild node.
5296 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==>pathinfo"));
5298 if (mdi_pi_alloc_compatible(self
, nname
, guid
, addr
, compat
,
5299 ncompat
, 0, &pchild
) != MDI_SUCCESS
) {
5300 SCSI_HBA_LOG((_LOG(2), self
, probe
,
5301 "pathinfo alloc failed"));
5306 dchild
= mdi_pi_get_client(pchild
);
5308 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5311 * Decorate new node with addressing properties via
5312 * scsi_hba_ua_set().
5314 if (scsi_hba_ua_set(addr
, NULL
, pchild
) == 0) {
5315 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5316 "pathinfo %s decoration failed",
5317 mdi_pi_spathname(pchild
)));
5318 (void) mdi_pi_free(pchild
, 0);
5323 /* Bind the driver */
5324 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5325 /* need to bind in order to register a devid */
5326 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
5327 "pathinfo %s created, no client driver-> "
5328 "no devid_register", mdi_pi_spathname(pchild
)));
5332 /* Watch out for inconsistancies in devids. */
5333 if (ddi_devid_get(dchild
, &cdevid
) == DDI_SUCCESS
)
5336 if (have_devid
&& !have_cdevid
) {
5337 /* Client does not yet have devid, register ours. */
5338 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5339 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5340 "pathinfo %s created, "
5341 "devid register failed",
5342 mdi_pi_spathname(pchild
)));
5344 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5345 "pathinfo %s created with devid",
5346 mdi_pi_spathname(pchild
)));
5347 } else if (have_devid
&& have_cdevid
) {
5349 * We have devid and client already has devid:
5350 * they must be the same.
5352 if (ddi_devid_compare(cdevid
, devid
) != 0) {
5353 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5354 "mismatched devid on path %s",
5355 mdi_pi_spathname(pchild
)));
5357 } else if (!have_devid
&& have_cdevid
) {
5359 * Client already has a devid, but we don't:
5360 * we should not have missing devids.
5362 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5363 "missing devid on path %s",
5364 mdi_pi_spathname(pchild
)));
5365 } else if (!have_cdevid
&& !have_devid
) {
5366 /* devid not supported */
5367 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5368 "pathinfo %s created, no devid",
5369 mdi_pi_spathname(pchild
)));
5373 * The above has registered devid for the device under
5374 * the client node. Now register it under the full pHCI
5375 * path to the device. We'll get an entry equivalent to
5376 * booting with mpxio disabled. This is needed for
5377 * telemetry during enumeration.
5379 if (e_devid_cache_pathinfo(pchild
, devid
) == DDI_SUCCESS
) {
5380 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5381 "pathinfo @%s created with devid", addr
));
5383 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5384 "pathinfo @%s devid cache failed", addr
));
5388 /* free the node name and compatible information */
5389 out
: if (have_devid
)
5390 ddi_devid_free(devid
);
5392 ddi_devid_free(cdevid
);
5394 ddi_devid_free_guid(guid
);
5396 scsi_hba_ident_nodename_compatible_free(nname
, dname
, compat
);
5398 ddi_prop_free(inq80
);
5400 ddi_prop_free(inq83
);
5402 ddi_prop_free(binding_set
);
5404 /* return child_type results */
5408 return (CHILD_TYPE_PATHINFO
);
5409 } else if (dchild
) {
5412 return (CHILD_TYPE_DEVINFO
);
5415 return (CHILD_TYPE_NONE
);
5419 * Call scsi_device_createchild and then initchild the new node.
5422 scsi_device_configchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5423 struct scsi_device
*sdprobe
, int *circp
, int *ppi
)
5427 mdi_pathinfo_t
*pchild
;
5431 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5435 child_type
= scsi_device_createchild(self
, addr
, se
, sdprobe
,
5439 * Prevent multiple initialized (tran_tgt_init) nodes associated with
5440 * the same @addr at the same time by calling tran_tgt_free() on the
5441 * probe node prior to promotion of the 'real' node. After the call
5442 * to scsi_hba_barrier_tran_tgt_free(), the HBA no longer has any
5443 * probe node context.
5445 scsi_hba_barrier_tran_tgt_free(sdprobe
->sd_dev
);
5447 switch (child_type
) {
5448 case CHILD_TYPE_NONE
:
5452 case CHILD_TYPE_PATHINFO
:
5454 * Online pathinfo: Hold the path and exit the pHCI while
5455 * calling mdi_pi_online() to avoid deadlock with power
5456 * management of pHCI.
5458 ASSERT(MDI_PHCI(self
));
5459 mdi_hold_path(pchild
);
5460 scsi_hba_devi_exit_phci(self
, *circp
);
5462 rval
= mdi_pi_online(pchild
, 0);
5464 scsi_hba_devi_enter_phci(self
, circp
);
5465 mdi_rele_path(pchild
);
5467 if (rval
!= MDI_SUCCESS
) {
5468 /* pathinfo form of "failed during tran_tgt_init" */
5469 scsi_enumeration_failed(NULL
, se
,
5470 mdi_pi_spathname(pchild
), "path online");
5471 (void) mdi_pi_free(pchild
, 0);
5476 * Return the path_instance of the pathinfo node.
5478 * NOTE: We assume that sd_inq is not path-specific.
5481 *ppi
= mdi_pi_get_path_instance(pchild
);
5485 * Fallthrough into CHILD_TYPE_DEVINFO code to promote
5486 * the 'client' devinfo node as a dchild.
5488 dchild
= mdi_pi_get_client(pchild
);
5489 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5490 "pathinfo online successful"));
5493 case CHILD_TYPE_DEVINFO
:
5495 * For now, we ndi_devi_online() the child because some other
5496 * parts of the IO framework, like degenerate devid code,
5497 * depend on bus_config driving nodes to DS_ATTACHED. At some
5498 * point in the future, to keep things light-weight, we would
5499 * like to change the ndi_devi_online call below to be
5501 * if (ddi_initchild(self, dchild) != DDI_SUCCESS)
5503 * This would promote the node so that framework code could
5504 * find the child with an @addr search, but does not incur
5505 * attach(9E) overhead for BUS_CONFIG_ALL cases where the
5506 * framework is not interested in attach of the node.
5508 * NOTE: If the addr specified has incorrect syntax (busconfig
5509 * one of bogus /devices path) then call below can fail.
5511 if (ndi_devi_online(dchild
, 0) != NDI_SUCCESS
) {
5512 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5513 "devinfo online failed"));
5515 /* failed online does not remove the node */
5516 (void) scsi_hba_remove_node(dchild
);
5519 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5520 "devinfo initchild successful"));
5528 scsi_hba_pkt_comp(struct scsi_pkt
*pkt
)
5530 scsi_hba_tran_t
*tran
;
5536 * Catch second call on the same packet before doing anything else.
5538 if (pkt
->pkt_flags
& FLAG_PKT_COMP_CALLED
) {
5545 "%s duplicate scsi_hba_pkt_comp(9F) on same scsi_pkt(9S)",
5546 mod_containing_pc(caller()));
5549 pkt
->pkt_flags
|= FLAG_PKT_COMP_CALLED
;
5551 if (pkt
->pkt_comp
== NULL
)
5555 * For HBA drivers that implement tran_setup_pkt(9E), if we are
5556 * completing a 'consistent' mode DMA operation then we must
5557 * perform dma_sync prior to calling pkt_comp to ensure that
5558 * the target driver sees the correct data in memory.
5560 ASSERT((pkt
->pkt_flags
& FLAG_NOINTR
) == 0);
5561 if (((pkt
->pkt_dma_flags
& DDI_DMA_CONSISTENT
) &&
5562 (pkt
->pkt_dma_flags
& DDI_DMA_READ
)) &&
5563 ((P_TO_TRAN(pkt
)->tran_setup_pkt
) != NULL
)) {
5568 * If the HBA driver is using SCSAv3 scsi_hba_tgtmap_create enumeration
5569 * then we detect the special ASC/ASCQ completion codes that indicate
5570 * that the lun configuration of a target has changed. Since we need to
5571 * be determine scsi_device given scsi_address enbedded in
5572 * scsi_pkt (via scsi_address_device(9F)), we also require use of
5573 * SCSI_HBA_ADDR_COMPLEX.
5575 tran
= pkt
->pkt_address
.a_hba_tran
;
5577 if ((tran
->tran_tgtmap
== NULL
) ||
5578 !(tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
))
5579 goto comp
; /* not using tgtmap */
5582 * Check for lun-change notification and queue the scsi_pkt for
5583 * lunchg1 processing. The 'pkt_comp' call to the target driver
5584 * is part of lunchg1 processing.
5586 if ((pkt
->pkt_reason
== CMD_CMPLT
) &&
5587 (((*pkt
->pkt_scbp
) & STATUS_MASK
) == STATUS_CHECK
) &&
5588 (pkt
->pkt_state
& STATE_ARQ_DONE
)) {
5589 sensep
= (uint8_t *)&(((struct scsi_arq_status
*)(uintptr_t)
5590 (pkt
->pkt_scbp
))->sts_sensedata
);
5591 if (((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5592 (scsi_sense_asc(sensep
) == 0x3f) &&
5593 (scsi_sense_ascq(sensep
) == 0x0e)) ||
5595 ((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5596 (scsi_sense_asc(sensep
) == 0x25) &&
5597 (scsi_sense_ascq(sensep
) == 0x00))) {
5599 * The host adaptor is done with the packet, we use
5600 * pkt_stmp stage-temporary to link the packet for
5601 * lunchg1 processing.
5603 * NOTE: pkt_ha_private is not available since its use
5604 * extends to tran_teardown_pkt.
5606 mutex_enter(&scsi_lunchg1_mutex
);
5607 pkt
->pkt_stmp
= scsi_lunchg1_list
;
5608 scsi_lunchg1_list
= pkt
;
5609 if (pkt
->pkt_stmp
== NULL
)
5610 (void) cv_signal(&scsi_lunchg1_cv
);
5611 mutex_exit(&scsi_lunchg1_mutex
);
5616 comp
: (*pkt
->pkt_comp
)(pkt
);
5620 * return 1 if the specified node is a barrier/probe node
5623 scsi_hba_devi_is_barrier(dev_info_t
*probe
)
5625 if (probe
&& (strcmp(ddi_node_name(probe
), "probe") == 0))
5631 * A host adapter driver is easier to write if we prevent multiple initialized
5632 * (tran_tgt_init) scsi_device structures to the same unit-address at the same
5633 * time. We prevent this from occurring all the time during the barrier/probe
5634 * node to real child hand-off by calling scsi_hba_barrier_tran_tgt_free
5635 * on the probe node prior to ddi_inichild of the 'real' node. As part of
5636 * this early tran_tgt_free implementation, we must also call this function
5637 * as we put a probe node on the scsi_hba_barrier_list.
5640 scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
)
5642 struct scsi_device
*sdprobe
;
5644 scsi_hba_tran_t
*tran
;
5646 ASSERT(probe
&& scsi_hba_devi_is_barrier(probe
));
5648 /* Return if we never called tran_tgt_init(9E). */
5649 if (i_ddi_node_state(probe
) < DS_INITIALIZED
)
5652 sdprobe
= ddi_get_driver_private(probe
);
5653 self
= ddi_get_parent(probe
);
5654 ASSERT(sdprobe
&& self
);
5655 tran
= ddi_get_driver_private(self
);
5658 if (tran
->tran_tgt_free
) {
5660 * To correctly support TRAN_CLONE, we need to use the same
5661 * cloned scsi_hba_tran(9S) structure for both tran_tgt_init(9E)
5662 * and tran_tgt_free(9E).
5664 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
)
5665 tran
= sdprobe
->sd_address
.a_hba_tran
;
5667 if (!sdprobe
->sd_tran_tgt_free_done
) {
5668 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5669 "tran_tgt_free EARLY"));
5670 (*tran
->tran_tgt_free
) (self
, probe
, tran
, sdprobe
);
5671 sdprobe
->sd_tran_tgt_free_done
= 1;
5673 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5674 "tran_tgt_free EARLY already done"));
5680 * Add an entry to the list of barrier nodes to be asynchronously deleted by
5681 * the scsi_hba_barrier_daemon after the specified timeout. Nodes on
5682 * the barrier list are used to implement the bus_config probe cache
5683 * of non-existent devices. The nodes are at DS_INITIALIZED, so their
5684 * @addr is established for searching. Since devi_ref of a DS_INITIALIZED
5685 * node will *not* prevent demotion, demotion is prevented by setting
5686 * sd_uninit_prevent. Devinfo snapshots attempt to attach probe cache
5687 * nodes, and on failure attempt to demote the node (without the participation
5688 * of bus_unconfig) to DS_BOUND - this demotion is prevented via
5689 * sd_uninit_prevent causing any attempted DDI_CTLOPS_UNINITCHILD to fail.
5690 * Probe nodes are bound to nulldriver. The list is sorted by
5693 * NOTE: If we drove a probe node to DS_ATTACHED, we could use ndi_hold_devi()
5694 * to prevent demotion (instead of sd_uninit_prevent).
5697 scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
)
5699 struct scsi_hba_barrier
*nb
;
5700 struct scsi_hba_barrier
*b
;
5701 struct scsi_hba_barrier
**bp
;
5704 ASSERT(scsi_hba_devi_is_barrier(probe
));
5706 /* HBA is no longer responsible for nodes on the barrier list. */
5707 scsi_hba_barrier_tran_tgt_free(probe
);
5708 nb
= kmem_alloc(sizeof (struct scsi_hba_barrier
), KM_SLEEP
);
5709 mutex_enter(&scsi_hba_barrier_mutex
);
5710 endtime
= ddi_get_lbolt() + drv_usectohz(seconds
* MICROSEC
);
5711 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
;
5712 bp
= &b
->barrier_next
)
5713 if (b
->barrier_endtime
> endtime
)
5715 nb
->barrier_next
= *bp
;
5716 nb
->barrier_endtime
= endtime
;
5717 nb
->barrier_probe
= probe
;
5719 if (bp
== &scsi_hba_barrier_list
)
5720 (void) cv_signal(&scsi_hba_barrier_cv
);
5721 mutex_exit(&scsi_hba_barrier_mutex
);
5725 * Attempt to remove devinfo node node, return 1 if removed. We
5726 * don't try to remove barrier nodes that have sd_uninit_prevent set
5727 * (even though they should fail device_uninitchild).
5730 scsi_hba_remove_node(dev_info_t
*child
)
5732 dev_info_t
*self
= ddi_get_parent(child
);
5733 struct scsi_device
*sd
;
5737 char na
[SCSI_MAXNAMELEN
];
5739 scsi_hba_devi_enter(self
, &circ
);
5741 /* Honor sd_uninit_prevent on barrier nodes */
5742 if (scsi_hba_devi_is_barrier(child
)) {
5743 sd
= ddi_get_driver_private(child
);
5744 if (sd
&& sd
->sd_uninit_prevent
)
5749 (void) ddi_deviname(child
, na
);
5750 if (ddi_remove_child(child
, 0) != DDI_SUCCESS
) {
5751 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
5752 "remove_node failed"));
5754 child
= NULL
; /* child is gone */
5755 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5756 "remove_node removed %s", *na
? &na
[1] : na
));
5760 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "remove_node prevented"));
5762 scsi_hba_devi_exit(self
, circ
);
5767 * The asynchronous barrier deletion daemon. Waits for a barrier timeout
5768 * to expire, then deletes the barrier (removes it as a child).
5772 scsi_hba_barrier_daemon(void *arg
)
5774 struct scsi_hba_barrier
*b
;
5776 callb_cpr_t cprinfo
;
5780 CALLB_CPR_INIT(&cprinfo
, &scsi_hba_barrier_mutex
,
5781 callb_generic_cpr
, "scsi_hba_barrier_daemon");
5782 again
: mutex_enter(&scsi_hba_barrier_mutex
);
5784 b
= scsi_hba_barrier_list
;
5786 /* all barriers expired, wait for barrier_add */
5787 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5788 (void) cv_wait(&scsi_hba_barrier_cv
,
5789 &scsi_hba_barrier_mutex
);
5790 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_hba_barrier_mutex
);
5792 if (ddi_get_lbolt() >= b
->barrier_endtime
) {
5794 * Drop and retry if ordering issue. Do this
5795 * before calling scsi_hba_remove_node() and
5798 probe
= b
->barrier_probe
;
5799 self
= ddi_get_parent(probe
);
5800 if (scsi_hba_devi_tryenter(self
, &circ
) == 0) {
5801 delay
: mutex_exit(&scsi_hba_barrier_mutex
);
5806 /* process expired barrier */
5807 if (!scsi_hba_remove_node(probe
)) {
5808 /* remove failed, delay and retry */
5809 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5811 scsi_hba_devi_exit(self
, circ
);
5814 scsi_hba_barrier_list
= b
->barrier_next
;
5815 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5816 scsi_hba_devi_exit(self
, circ
);
5818 /* establish timeout for next barrier expire */
5819 (void) cv_timedwait(&scsi_hba_barrier_cv
,
5820 &scsi_hba_barrier_mutex
,
5821 b
->barrier_endtime
);
5828 * Remove all barriers associated with the specified HBA. This is called
5829 * from from the bus_unconfig implementation to remove probe nodes associated
5830 * with the specified HBA (self) so that probe nodes that have not expired
5831 * will not prevent DR of the HBA.
5834 scsi_hba_barrier_purge(dev_info_t
*self
)
5836 struct scsi_hba_barrier
**bp
;
5837 struct scsi_hba_barrier
*b
;
5839 mutex_enter(&scsi_hba_barrier_mutex
);
5840 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
; ) {
5841 if (ddi_get_parent(b
->barrier_probe
) == self
) {
5842 if (scsi_hba_remove_node(b
->barrier_probe
)) {
5843 *bp
= b
->barrier_next
;
5844 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5846 SCSI_HBA_LOG((_LOG(4), NULL
, b
->barrier_probe
,
5850 bp
= &b
->barrier_next
;
5853 mutex_exit(&scsi_hba_barrier_mutex
);
5857 * LUN-change processing daemons: processing occurs in two stages:
5859 * Stage 1: Daemon waits for a lunchg1 queued scsi_pkt, dequeues the pkt,
5860 * forms the path, completes the scsi_pkt (pkt_comp), and
5861 * queues the path for stage 2 processing. The use of stage 1
5862 * avoids issues related to memory allocation in interrupt context
5863 * (scsi_hba_pkt_comp()). We delay the pkt_comp completion until
5864 * after lunchg1 processing forms the path for stage 2 - this is
5865 * done to prevent the target driver from detaching until the
5866 * path formation is complete (driver with outstanding commands
5867 * should not detach).
5869 * Stage 2: Daemon waits for a lunchg2 queued request, dequeues the
5870 * request, and opens the path using ldi_open_by_name(). The
5871 * path opened uses a special "@taddr,*" unit address that will
5872 * trigger lun enumeration in scsi_hba_bus_configone(). We
5873 * trigger lun enumeration in stage 2 to avoid problems when
5874 * initial ASC/ASCQ trigger occurs during discovery.
5878 scsi_lunchg1_daemon(void *arg
)
5880 callb_cpr_t cprinfo
;
5881 struct scsi_pkt
*pkt
;
5882 scsi_hba_tran_t
*tran
;
5884 struct scsi_device
*sd
;
5886 char taddr
[SCSI_MAXNAMELEN
];
5887 char path
[MAXPATHLEN
];
5888 struct scsi_lunchg2
*lunchg2
;
5890 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg1_mutex
,
5891 callb_generic_cpr
, "scsi_lunchg1_daemon");
5892 mutex_enter(&scsi_lunchg1_mutex
);
5894 pkt
= scsi_lunchg1_list
;
5896 /* All lunchg1 processing requests serviced, wait. */
5897 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5898 (void) cv_wait(&scsi_lunchg1_cv
,
5899 &scsi_lunchg1_mutex
);
5900 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg1_mutex
);
5904 /* Unlink and perform lunchg1 processing on pkt. */
5905 scsi_lunchg1_list
= pkt
->pkt_stmp
;
5907 /* Determine initiator port (self) from the pkt_address. */
5908 tran
= pkt
->pkt_address
.a_hba_tran
;
5909 ASSERT(tran
&& tran
->tran_tgtmap
&& tran
->tran_iport_dip
);
5910 self
= tran
->tran_iport_dip
;
5913 * Determine scsi_devie from pkt_address (depends on
5914 * SCSI_HBA_ADDR_COMPLEX).
5916 sd
= scsi_address_device(&(pkt
->pkt_address
));
5919 (*pkt
->pkt_comp
)(pkt
);
5923 /* Determine unit-address from scsi_device. */
5924 ua
= scsi_device_unit_address(sd
);
5926 /* Extract taddr from the unit-address. */
5927 for (p
= taddr
; (*ua
!= ',') && (*ua
!= '\0'); )
5929 *p
= '\0'; /* NULL terminate taddr */
5932 * Form path using special "@taddr,*" notation to trigger
5935 (void) ddi_pathname(self
, path
);
5936 (void) strcat(path
, "/luns@");
5937 (void) strcat(path
, taddr
);
5938 (void) strcat(path
, ",*");
5941 * Now that we have the path, complete the pkt that
5942 * triggered lunchg1 processing.
5944 (*pkt
->pkt_comp
)(pkt
);
5946 /* Allocate element for stage2 processing queue. */
5947 lunchg2
= kmem_alloc(sizeof (*lunchg2
), KM_SLEEP
);
5948 lunchg2
->lunchg2_path
= strdup(path
);
5950 /* Queue and dispatch to stage 2. */
5951 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5952 "lunchg stage1: queue %s", lunchg2
->lunchg2_path
));
5953 mutex_enter(&scsi_lunchg2_mutex
);
5954 lunchg2
->lunchg2_next
= scsi_lunchg2_list
;
5955 scsi_lunchg2_list
= lunchg2
;
5956 if (lunchg2
->lunchg2_next
== NULL
)
5957 (void) cv_signal(&scsi_lunchg2_cv
);
5958 mutex_exit(&scsi_lunchg2_mutex
);
5964 scsi_lunchg2_daemon(void *arg
)
5966 callb_cpr_t cprinfo
;
5967 struct scsi_lunchg2
*lunchg2
;
5971 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg2_mutex
,
5972 callb_generic_cpr
, "scsi_lunchg2_daemon");
5974 li
= ldi_ident_from_anon();
5975 mutex_enter(&scsi_lunchg2_mutex
);
5977 lunchg2
= scsi_lunchg2_list
;
5978 if (lunchg2
== NULL
) {
5979 /* All lunchg2 processing requests serviced, wait. */
5980 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5981 (void) cv_wait(&scsi_lunchg2_cv
,
5982 &scsi_lunchg2_mutex
);
5983 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg2_mutex
);
5987 /* Unlink and perform lunchg2 processing on pkt. */
5988 scsi_lunchg2_list
= lunchg2
->lunchg2_next
;
5991 * Open and close the path to trigger lun enumeration. We
5992 * don't expect the open to succeed, but we do expect code in
5993 * scsi_hba_bus_configone() to trigger lun enumeration.
5995 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
5996 "lunchg stage2: open %s", lunchg2
->lunchg2_path
));
5997 if (ldi_open_by_name(lunchg2
->lunchg2_path
,
5998 FREAD
, kcred
, &lh
, li
) == 0)
5999 (void) ldi_close(lh
, FREAD
, kcred
);
6001 /* Free path and linked element. */
6002 strfree(lunchg2
->lunchg2_path
);
6003 kmem_free(lunchg2
, sizeof (*lunchg2
));
6008 * Enumerate a child at the specified @addr. If a device exists @addr then
6009 * ensure that we have the appropriately named devinfo node for it. Name is
6010 * NULL in the bus_config_all case. This routine has no knowledge of the
6011 * format of an @addr string or associated addressing properties.
6013 * The caller must guarantee that there is an open scsi_hba_devi_enter on the
6014 * parent. We return the scsi_device structure for the child device. This
6015 * scsi_device structure is valid until the caller scsi_hba_devi_exit the
6016 * parent. The caller can add do ndi_hold_devi of the child prior to the
6017 * scsi_hba_devi_exit to extend the validity of the child.
6019 * In some cases the returned scsi_device structure may be used to drive
6020 * additional SCMD_REPORT_LUNS operations by bus_config_all callers.
6022 * The first operation performed is to see if there is a dynamic SID nodes
6023 * already attached at the specified "name@addr". This is the fastpath
6024 * case for resolving a reference to a node that has already been created.
6025 * All other references are serialized for a given @addr prior to probing
6026 * to determine the type of device, if any, at the specified @addr.
6027 * If no device is present then NDI_FAILURE is returned. The fact that a
6028 * device does not exist may be determined via the barrier/probe cache,
6029 * minimizing the probes of non-existent devices.
6031 * When there is a device present the dynamic SID node is created based on
6032 * the device found. If a driver.conf node exists for the same @addr it
6033 * will either merge into the dynamic SID node (if the SID node bound to
6034 * that driver), or exist independently. To prevent the actions of one driver
6035 * causing side effects in another, code prevents multiple SID nodes from
6036 * binding to the same "@addr" at the same time. There is autodetach code
6037 * to allow one device to be replaced with another at the same @addr for
6038 * slot addressed SCSI bus implementations (SPI). For compatibility with
6039 * legacy driver.conf behavior, the code does not prevent multiple driver.conf
6040 * nodes from attaching to the same @addr at the same time.
6042 * This routine may have the side effect of creating nodes for devices other
6043 * than the one being sought. It is possible that there is a different type of
6044 * target device at that target/lun address than we were asking for. In that
6045 * It is the caller's responsibility to determine whether the device we found,
6046 * if any, at the specified address, is the one it really wanted.
6048 static struct scsi_device
*
6049 scsi_device_config(dev_info_t
*self
, char *name
, char *addr
, scsi_enum_t se
,
6050 int *circp
, int *ppi
)
6052 dev_info_t
*child
= NULL
;
6053 dev_info_t
*probe
= NULL
;
6054 struct scsi_device
*sdchild
;
6055 struct scsi_device
*sdprobe
;
6056 dev_info_t
*dsearch
;
6057 mdi_pathinfo_t
*psearch
;
6061 int wait_msg
= scsi_hba_wait_msg
;
6064 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6066 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s wanted",
6067 name
? name
: "", addr
));
6069 /* playing with "probe" node name is dangerous */
6070 if (name
&& (strcmp(name
, "probe") == 0))
6074 * NOTE: use 'goto done;' or 'goto fail;'. There should only be one
6075 * 'return' statement from here to the end of the function - the one
6076 * on the last line of the function.
6080 * Fastpath: search to see if we are requesting a named SID node that
6081 * already exists (we already created) - probe node does not count.
6082 * scsi_findchild() does not hold the returned devinfo node, but
6083 * this is OK since the caller has a scsi_hba_devi_enter on the
6084 * attached parent HBA (self). The caller is responsible for attaching
6085 * and placing a hold on the child (directly via ndi_hold_devi or
6086 * indirectly via ndi_busop_bus_config) before doing an
6087 * scsi_hba_devi_exit on the parent.
6089 * NOTE: This fastpath prevents detecting a driver binding change
6090 * (autodetach) if the same nodename is used for old and new binding.
6092 /* first call is with init set */
6093 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6094 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
) &&
6095 !scsi_hba_devi_is_barrier(dsearch
)) {
6096 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6097 "%s@%s devinfo fastpath", name
? name
: "", addr
));
6103 * Create a barrier devinfo node used to "probe" the device with. We
6104 * need to drive this node to DS_INITIALIZED so that the
6105 * DDI_CTLOPS_INITCHILD has occurred, bringing the SCSA transport to
6106 * a state useable state for issuing our "probe" commands. We establish
6107 * this barrier node with a node name of "probe" and compatible
6108 * property of "scsiprobe". The compatible property must be associated
6109 * in /etc/driver_aliases with a scsi target driver available in the
6110 * root file system (sd).
6112 * The "probe" that we perform on the barrier node, after it is
6113 * DS_INITIALIZED, is used to find the information needed to create a
6114 * dynamic devinfo (SID) node. This "probe" is separate from the
6115 * probe(9E) call associated with the transition of a node from
6116 * DS_INITIALIZED to DS_PROBED. The probe(9E) call that eventually
6117 * occurs against the created SID node should find ddi_dev_is_sid and
6118 * just return DDI_PROBE_DONTCARE.
6120 * Trying to avoid the use of a barrier node is not a good idea
6121 * because we may have an HBA driver that uses generic bus_config
6122 * (this code) but implements its own DDI_CTLOPS_INITCHILD with side
6123 * effects that we can't duplicate (such as the ATA nexus driver).
6125 * The probe/barrier node plays an integral part of the locking scheme.
6126 * The objective is to single thread probes of the same device (same
6127 * @addr) while allowing parallelism for probes of different devices
6128 * with the same parent. At this point we are serialized on our self.
6129 * For parallelism we will need to release our self. Prior to release
6130 * we construct a barrier for probes of the same device to serialize
6131 * against. The "probe@addr" node acts as this barrier. An entering
6132 * thread must wait until the probe node does not exist - it can then
6133 * create and link the probe node - dropping the HBA (self) lock after
6134 * the node is linked and visible (after ddi_initchild). A side effect
6135 * of this is that transports should not "go over the wire" (i.e. do
6136 * things that incur significant delays) until after tran_target_init.
6137 * This means that the first "over the wire" operation should occur
6138 * at tran_target_probe time - when things are running in parallel
6141 * If the probe node exists then another probe with the same @addr is
6142 * in progress, we must wait until there is no probe in progress
6143 * before proceeding, and when we proceed we must continue to hold the
6144 * HBA (self) until we have linked a new probe node as a barrier.
6146 * When a device is found to *not* exist, its probe/barrier node may be
6147 * marked with DEVICE_REMOVED with node deletion scheduled for some
6148 * future time (seconds). This asynchronous deletion allows the
6149 * framework to detect repeated requests to the same non-existent
6150 * device and avoid overhead associated with contacting a non-existent
6151 * device again and again.
6155 * Search for probe node - they should only exist as devinfo
6158 (void) scsi_findchild(self
, "probe", addr
,
6159 0, &probe
, &psearch
, NULL
);
6160 if (probe
== NULL
) {
6162 SCSI_HBA_LOG((_LOG(2), self
,
6163 mdi_pi_get_client(psearch
),
6164 "???? @%s 'probe' search found "
6165 "pathinfo: %p", addr
, (void *)psearch
));
6170 * The barrier node may cache the non-existence of a device
6171 * by leaving the barrier node in place (with
6172 * DEVI_DEVICE_REMOVED flag set ) for some amount of time after
6173 * the failure of a probe. This flag is used to fail
6174 * additional probes until the barrier probe node is deleted,
6175 * which will occur from a timeout some time after a failed
6176 * probe. The failed probe will use DEVI_SET_DEVICE_REMOVED
6177 * and schedule probe node deletion from a timeout. The callers
6178 * scsi_hba_devi_exit on the way out of the first failure will
6179 * do the cv_broadcast associated with the cv_wait below - this
6180 * handles threads that wait prior to DEVI_DEVICE_REMOVED being
6183 if (DEVI_IS_DEVICE_REMOVED(probe
)) {
6184 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6185 "detected probe DEVICE_REMOVED"));
6186 probe
= NULL
; /* deletion already scheduled */
6191 * Drop the lock on the HBA (self) and wait until the probe in
6192 * progress has completed. A changes in the sibling list from
6193 * removing the probe node will cause cv_wait to return
6194 * (scsi_hba_devi_exit does the cv_broadcast).
6198 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6199 "exists, probe already in progress: %s", wait_msg
?
6200 "waiting..." : "last msg, but still waiting..."));
6204 * NOTE: we could avoid rare case of one second delay by
6205 * implementing scsi_hba_devi_exit_and_wait based on
6206 * ndi/mdi_devi_exit_and_wait (and consider switching devcfg.c
6207 * code to use these ndi/mdi interfaces too).
6209 scsi_hba_devi_exit(self
, *circp
);
6210 mutex_enter(&DEVI(self
)->devi_lock
);
6211 (void) cv_timedwait(&DEVI(self
)->devi_cv
,
6212 &DEVI(self
)->devi_lock
,
6213 ddi_get_lbolt() + drv_usectohz(MICROSEC
));
6214 mutex_exit(&DEVI(self
)->devi_lock
);
6215 scsi_hba_devi_enter(self
, circp
);
6217 ASSERT(probe
== NULL
);
6220 * Search to see if we are requesting a SID node that already exists.
6221 * We hold the HBA (self) and there is not another probe in progress at
6222 * the same @addr. scsi_findchild() does not hold the returned
6223 * devinfo node but this is OK since we hold the HBA (self).
6226 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6227 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
)) {
6228 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6229 "%s@%s probe devinfo fastpath",
6230 name
? name
: "", addr
));
6237 * We are looking for a SID node that does not exist or a driver.conf
6240 * To avoid probe side effects, before we probe the device at the
6241 * specified address we need to check to see if there is already an
6242 * initialized child "@addr".
6244 * o If we find an initialized SID child and name is NULL or matches
6245 * the name or the name of the attached driver then we return the
6248 * o If we find a non-matching SID node, we will attempt to autodetach
6249 * and remove the node in preference to our new node.
6251 * o If SID node found does not match and can't be autodetached, we
6252 * fail: we only allow one SID node at an address.
6254 * NOTE: This code depends on SID nodes showing up prior to
6255 * driver.conf nodes in the sibling list.
6258 /* first NULL name call is with init set */
6259 (void) scsi_findchild(self
, NULL
, addr
, 1, &dsearch
, NULL
, &pi
);
6260 if (dsearch
== NULL
)
6262 ASSERT(!scsi_hba_devi_is_barrier(dsearch
));
6265 * To detect changes in driver binding that should attempt
6266 * autodetach we determine the major number of the driver
6267 * that should currently be associated with the device based
6268 * on the compatible property.
6270 major
= DDI_MAJOR_T_NONE
;
6271 if (scsi_hba_dev_is_sid(dsearch
))
6272 major
= ddi_compatible_driver_major(dsearch
, NULL
);
6273 if ((major
== DDI_MAJOR_T_NONE
) && (name
== NULL
))
6274 major
= ddi_driver_major(dsearch
);
6276 if ((scsi_hba_dev_is_sid(dsearch
) ||
6277 (i_ddi_node_state(dsearch
) >= DS_INITIALIZED
)) &&
6279 (strcmp(ddi_node_name(dsearch
), name
) == 0) ||
6280 (strcmp(ddi_driver_name(dsearch
), name
) == 0)) &&
6281 (major
== ddi_driver_major(dsearch
))) {
6282 SCSI_HBA_LOG((_LOG(3), NULL
, dsearch
,
6283 "already attached @addr"));
6288 if (!scsi_hba_dev_is_sid(dsearch
))
6289 break; /* driver.conf node */
6292 * Implement autodetach of SID node for situations like a
6293 * previously "scsinodev" LUN0 coming into existence (or a
6294 * disk/tape on an SPI transport at same addr but never both
6295 * powered on at the same time). Try to autodetach the existing
6296 * SID node @addr. If that works, search again - otherwise fail.
6298 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6299 "looking for %s@%s: SID @addr exists, autodetach",
6300 name
? name
: "", addr
));
6301 if (!scsi_hba_remove_node(dsearch
)) {
6302 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6303 "autodetach @%s failed: fail %s@%s",
6304 addr
, name
? name
: "", addr
));
6307 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "autodetach @%s OK", addr
));
6311 * We will be creating a new SID node, allocate probe node
6312 * used to find out information about the device located @addr.
6313 * The probe node also acts as a barrier against additional
6314 * configuration at the same address, and in the case of non-existent
6315 * devices it will (for some amount of time) avoid re-learning that
6316 * the device does not exist on every reference. Once the probe
6317 * node is DS_LINKED we can drop the HBA (self).
6319 * The probe node is allocated as a hidden node so that it does not
6320 * show up in devinfo snapshots.
6322 ndi_devi_alloc_sleep(self
, "probe",
6323 (se
== SE_HP
) ? DEVI_SID_HP_HIDDEN_NODEID
: DEVI_SID_HIDDEN_NODEID
,
6326 ndi_flavor_set(probe
, SCSA_FLAVOR_SCSI_DEVICE
);
6329 * Decorate the probe node with the property representation of @addr
6330 * unit-address string prior to initchild so that initchild can
6331 * construct the name of the node from properties and tran_tgt_init
6332 * implementation can determine what LUN is being referenced.
6334 * If the addr specified has incorrect syntax (busconfig one of bogus
6335 * /devices path) then scsi_hba_ua_set can fail. If the address
6336 * is not understood by the SCSA HBA driver then this operation will
6337 * work, but tran_tgt_init may still fail (for example the HBA
6338 * driver may not support secondary functions).
6340 if (scsi_hba_ua_set(addr
, probe
, NULL
) == 0) {
6341 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6342 "@%s failed scsi_hba_ua_set", addr
));
6347 * Set the class property to "scsi". This is sufficient to distinguish
6348 * the node for HBAs that have multiple classes of children (like uata
6349 * - which has "dada" class for ATA children and "scsi" class for
6350 * ATAPI children) and may not use our scsi_busctl_initchild()
6351 * implementation. We also add a "compatible" property of "scsiprobe"
6352 * to select the probe driver.
6354 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, probe
,
6355 "class", "scsi") != DDI_PROP_SUCCESS
) ||
6356 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, probe
,
6357 "compatible", &compatible_probe
, 1) != DDI_PROP_SUCCESS
)) {
6358 SCSI_HBA_LOG((_LOG(1), NULL
, probe
,
6359 "@%s failed node decoration", addr
));
6364 * Promote probe node to DS_INITIALIZED so that transport can be used
6365 * for scsi_probe. After this the node is linked and visible as a
6366 * barrier for serialization of other @addr operations.
6368 * NOTE: If we attached the probe node, we could get rid of
6371 if (ddi_initchild(self
, probe
) != DDI_SUCCESS
) {
6372 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6373 "@%s failed initchild", addr
));
6375 /* probe node will be removed in fail exit path */
6379 /* get the scsi_device structure of the probe node */
6380 sdprobe
= ddi_get_driver_private(probe
);
6384 * Do scsi_probe. The probe node is linked and visible as a barrier.
6385 * We prevent uninitialization of the probe node and drop our HBA (self)
6386 * while we run scsi_probe() of this "@addr". This allows the framework
6387 * to support multiple scsi_probes for different devices attached to
6388 * the same HBA (self) in parallel. We prevent node demotion of the
6389 * probe node from DS_INITIALIZED by setting sd_uninit_prevent. The
6390 * probe node can not be successfully demoted below DS_INITIALIZED
6391 * (scsi_busctl_uninitchild will fail) until we zero sd_uninit_prevent
6392 * as we are freeing the node via scsi_hba_remove_node(probe).
6394 sdprobe
->sd_uninit_prevent
++;
6395 scsi_hba_devi_exit(self
, *circp
);
6396 sp
= scsi_probe(sdprobe
, SLEEP_FUNC
);
6398 /* Introduce a small delay here to increase parallelism. */
6401 if (sp
== SCSIPROBE_EXISTS
) {
6403 * For a device that exists, while still running in parallel,
6404 * also get identity information from device. This is done
6405 * separate from scsi_probe/tran_tgt_probe/scsi_hba_probe
6406 * since the probe code path may still be used for HBAs
6407 * that don't use common bus_config services (we don't want
6408 * to expose that code path to a behavior change). This
6409 * operation is called 'identity' to avoid confusion with
6410 * deprecated identify(9E).
6412 * Future: We may eventually want to allow HBA customization via
6413 * scsi_identity/tran_tgt_identity/scsi_device_identity, but for
6414 * now we just scsi_device_identity.
6416 * The identity operation will establish additional properties
6417 * on the probe node related to device identity:
6419 * "inquiry-page-80" byte array of SCSI page 80
6420 * "inquiry-page-83" byte array of SCSI page 83
6422 * These properties will be used to generate a devid
6423 * (ddi_devid_scsi_encode) and guid - and to register
6424 * (ddi_devid_register) a devid for the device.
6426 * If identify fails (non-zero return), the we had allocation
6427 * problems or the device returned inconsistent results then
6428 * we pretend that device does not exist.
6430 if (scsi_device_identity(sdprobe
, SLEEP_FUNC
)) {
6431 scsi_enumeration_failed(probe
, -1, NULL
, "identify");
6432 sp
= SCSIPROBE_FAILURE
;
6436 * Future: Is there anything more we can do here to help avoid
6437 * serialization on iport parent during scsi_device attach(9E)?
6440 scsi_hba_devi_enter(self
, circp
);
6441 sdprobe
->sd_uninit_prevent
--;
6443 if (sp
!= SCSIPROBE_EXISTS
) {
6444 scsi_enumeration_failed(probe
, -1, NULL
, "probe");
6446 if ((se
!= SE_HP
) && scsi_hba_barrier_timeout
) {
6448 * Target does not exist. Mark the barrier probe node
6449 * as DEVICE_REMOVED and schedule an asynchronous
6450 * deletion of the node in scsi_hba_barrier_timeout
6451 * seconds. We keep our hold on the probe node
6452 * until we are ready perform the asynchronous node
6455 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6456 "set probe DEVICE_REMOVED"));
6457 mutex_enter(&DEVI(probe
)->devi_lock
);
6458 DEVI_SET_DEVICE_REMOVED(probe
);
6459 mutex_exit(&DEVI(probe
)->devi_lock
);
6461 scsi_hba_barrier_add(probe
, scsi_hba_barrier_timeout
);
6467 /* Create the child node from the inquiry data in the probe node. */
6468 if ((child
= scsi_device_configchild(self
, addr
, se
, sdprobe
,
6469 circp
, &pi
)) == NULL
) {
6471 * This may fail because there was no driver binding identified
6472 * via driver_alias. We may still have a conf node.
6475 (void) scsi_findchild(self
, name
, addr
,
6476 0, &child
, NULL
, &pi
);
6478 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6479 "using driver.conf driver binding"));
6481 if (child
== NULL
) {
6482 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6483 "device not configured"));
6489 * Transfer the inquiry data from the probe node to the child
6490 * SID node to avoid an extra scsi_probe. Callers depend on
6491 * established inquiry data for the returned scsi_device.
6493 sdchild
= ddi_get_driver_private(child
);
6494 if (sdchild
&& (sdchild
->sd_inq
== NULL
)) {
6495 sdchild
->sd_inq
= sdprobe
->sd_inq
;
6496 sdprobe
->sd_inq
= NULL
;
6500 * If we are doing a bus_configone and the node we created has the
6501 * wrong node and driver name then switch the return result to a
6502 * driver.conf node with the correct name - if such a node exists.
6504 if (name
&& (strcmp(ddi_node_name(child
), name
) != 0) &&
6505 (strcmp(ddi_driver_name(child
), name
) != 0)) {
6506 (void) scsi_findchild(self
, name
, addr
,
6507 0, &dsearch
, NULL
, &pi
);
6508 if (dsearch
== NULL
) {
6509 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6510 "wrong device configured %s@%s", name
, addr
));
6512 * We can't remove when modrootloaded == 0 in case
6513 * boot-device a uses generic name and
6514 * scsi_hba_nodename_compatible_get() returned a
6515 * legacy binding-set driver oriented name.
6517 if (modrootloaded
) {
6518 (void) scsi_hba_remove_node(child
);
6523 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6524 "device configured, but switching to driver.conf"));
6529 /* get the scsi_device structure from the node */
6530 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "device configured"));
6533 done
: ASSERT(child
);
6534 sdchild
= ddi_get_driver_private(child
);
6538 * We may have ended up here after promotion of a previously
6539 * demoted node, where demotion deleted sd_inq data in
6540 * scsi_busctl_uninitchild. We redo the scsi_probe() to
6541 * reestablish sd_inq. We also want to redo the scsi_probe
6542 * for devices are currently device_isremove in order to
6543 * detect new device_insert.
6545 if ((sdchild
->sd_inq
== NULL
) ||
6546 ((pi
== 0) && ndi_devi_device_isremoved(child
))) {
6548 /* hotplug_node can only be revived via hotplug. */
6549 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
6550 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6551 "scsi_probe() demoted devinfo"));
6553 sp
= scsi_probe(sdchild
, SLEEP_FUNC
);
6555 if (sp
== SCSIPROBE_EXISTS
) {
6556 ASSERT(sdchild
->sd_inq
);
6559 * Devinfo child exists and we are
6560 * talking to the device, report
6561 * reinsert and note if this was a
6564 chg
= ndi_devi_device_insert(child
);
6565 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6566 "devinfo %s@%s device_reinsert%s",
6567 name
? name
: "", addr
,
6568 chg
? "" : "ed already"));
6570 scsi_enumeration_failed(child
, se
,
6573 chg
= ndi_devi_device_remove(child
);
6574 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6575 "%s device_remove%s",
6576 (sp
> (sizeof (scsi_probe_ascii
) /
6577 sizeof (scsi_probe_ascii
[0]))) ?
6578 "UNKNOWN" : scsi_probe_ascii
[sp
],
6579 chg
? "" : "ed already"));
6585 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6593 fail
: ASSERT(child
== NULL
);
6598 * Clean up probe node, destroying node if uninit_prevent
6599 * it is going to zero. Destroying the probe node (deleting
6600 * from the sibling list) will wake up any people waiting on
6601 * the probe node barrier.
6603 SCSI_HBA_LOG((_LOG(4), NULL
, probe
, "remove probe"));
6604 if (!scsi_hba_remove_node(probe
)) {
6606 * Probe node removal should not fail, but if it
6607 * does we hand that responsibility over to the
6608 * async barrier deletion thread - other references
6609 * to the same unit-address can hang until the
6610 * probe node delete completes.
6612 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
6613 "remove probe failed, go async"));
6614 scsi_hba_barrier_add(probe
, 1);
6620 * If we successfully resolved via a pathinfo node, we need to find
6621 * the pathinfo node and ensure that it is online (if possible). This
6622 * is done for the case where the device was open when
6623 * scsi_device_unconfig occurred, so mdi_pi_free did not occur. If the
6624 * device has now been reinserted, we want the path back online.
6625 * NOTE: This needs to occur after destruction of the probe node to
6626 * avoid ASSERT related to two nodes at the same unit-address.
6628 if (sdchild
&& pi
&& (probe
== NULL
)) {
6629 ASSERT(MDI_PHCI(self
));
6631 (void) scsi_findchild(self
, NULL
, addr
,
6632 0, &dsearch
, &psearch
, NULL
);
6633 ASSERT((psearch
== NULL
) ||
6634 (mdi_pi_get_client(psearch
) == child
));
6636 if (psearch
&& mdi_pi_device_isremoved(psearch
)) {
6638 * Verify that we can talk to the device, and if
6639 * so note if this is a new device_insert.
6641 * NOTE: We depend on mdi_path_select(), when given
6642 * a specific path_instance, to select that path
6643 * even if the path is offline.
6645 * NOTE: A Client node is not ndi_dev_is_hotplug_node().
6648 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6649 "%s scsi_probe() demoted pathinfo",
6650 mdi_pi_spathname(psearch
)));
6652 sp
= scsi_hba_probe_pi(sdchild
, SLEEP_FUNC
, pi
);
6654 if (sp
== SCSIPROBE_EXISTS
) {
6656 * Pathinfo child exists and we are
6657 * talking to the device, report
6658 * reinsert and note if this
6659 * was a new reinsert.
6661 chg
= mdi_pi_device_insert(psearch
);
6662 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
6663 "pathinfo %s device_reinsert%s",
6664 mdi_pi_spathname(psearch
),
6665 chg
? "" : "ed already"));
6668 (void) mdi_pi_online(psearch
,
6672 * Report client reinsert and note if
6673 * this was a new reinsert.
6675 chg
= ndi_devi_device_insert(child
);
6676 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6677 "client devinfo %s@%s "
6678 "device_reinsert%s",
6679 name
? name
: "", addr
,
6680 chg
? "" : "ed already"));
6682 scsi_enumeration_failed(child
, se
,
6683 mdi_pi_spathname(psearch
),
6690 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6692 mdi_pi_spathname(psearch
)));
6700 /* If asked for path_instance, return it. */
6708 scsi_device_unconfig(dev_info_t
*self
, char *name
, char *addr
, int *circp
)
6710 dev_info_t
*child
= NULL
;
6711 mdi_pathinfo_t
*path
= NULL
;
6715 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6718 * We have a catch-22. We may have a demoted node that we need to find
6719 * and offline/remove. To find the node if it isn't demoted, we
6720 * use scsi_findchild. If it's demoted, we then use
6721 * ndi_devi_findchild_by_callback.
6723 (void) scsi_findchild(self
, name
, addr
, 0, &child
, &path
, NULL
);
6725 if ((child
== NULL
) && (path
== NULL
)) {
6726 child
= ndi_devi_findchild_by_callback(self
, name
, addr
,
6729 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6730 "devinfo %s@%s found by callback",
6731 name
? name
: "", addr
));
6732 ASSERT(ndi_flavor_get(child
) ==
6733 SCSA_FLAVOR_SCSI_DEVICE
);
6734 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
) {
6735 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6736 "devinfo %s@%s not SCSI_DEVICE flavored",
6737 name
? name
: "", addr
));
6744 ASSERT(child
&& (path
== NULL
));
6746 /* Don't unconfig probe nodes. */
6747 if (scsi_hba_devi_is_barrier(child
)) {
6748 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6749 "devinfo %s@%s is_barrier, skip",
6750 name
? name
: "", addr
));
6754 /* Attempt to offline/remove the devinfo node */
6755 if (ndi_devi_offline(child
,
6756 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
6757 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6758 "devinfo %s@%s offlined and removed",
6759 name
? name
: "", addr
));
6760 } else if (ndi_devi_device_remove(child
)) {
6761 /* Offline/remove failed, note new device_remove */
6762 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6763 "devinfo %s@%s offline failed, device_remove",
6764 name
? name
: "", addr
));
6767 ASSERT(path
&& (child
== NULL
));
6770 * Attempt to offline/remove the pathinfo node.
6772 * NOTE: mdi_pi_offline of last path will fail if the
6773 * device is open (i.e. the client can't be offlined).
6775 * NOTE: For mdi there is no REMOVE flag for mdi_pi_offline().
6776 * When mdi_pi_offline returns MDI_SUCCESS, we are responsible
6777 * for remove via mdi_pi_free().
6779 mdi_hold_path(path
);
6780 spathname
= mdi_pi_spathname(path
); /* valid after free */
6781 scsi_hba_devi_exit_phci(self
, *circp
);
6782 rval
= mdi_pi_offline(path
, 0);
6783 scsi_hba_devi_enter_phci(self
, circp
);
6785 /* Note new device_remove */
6786 if (mdi_pi_device_remove(path
))
6787 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6788 "pathinfo %s note device_remove", spathname
));
6790 mdi_rele_path(path
);
6791 if (rval
== MDI_SUCCESS
) {
6792 (void) mdi_pi_free(path
, 0);
6793 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6794 "pathinfo %s offlined, then freed", spathname
));
6797 ASSERT((path
== NULL
) && (child
== NULL
));
6799 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6800 "%s@%s not found", name
? name
: "", addr
));
6805 * configure the device at the specified "@addr" address.
6807 static struct scsi_device
*
6808 scsi_hba_bus_configone_addr(dev_info_t
*self
, char *addr
, scsi_enum_t se
)
6811 struct scsi_device
*sd
;
6813 scsi_hba_devi_enter(self
, &circ
);
6814 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, NULL
);
6815 scsi_hba_devi_exit(self
, circ
);
6820 * unconfigure the device at the specified "@addr" address.
6823 scsi_hba_bus_unconfigone_addr(dev_info_t
*self
, char *addr
)
6827 scsi_hba_devi_enter(self
, &circ
);
6828 (void) scsi_device_unconfig(self
, NULL
, addr
, &circ
);
6829 scsi_hba_devi_exit(self
, circ
);
6833 * The bus_config_all operations are multi-threaded for performance. A
6834 * separate thread per target and per LUN is used. The config handle is used
6835 * to coordinate all the threads at a given level and the config thread data
6836 * contains the required information for a specific thread to identify what it
6837 * is processing and the handle under which this is being processed.
6840 /* multi-threaded config handle */
6841 struct scsi_hba_mte_h
{
6842 dev_info_t
*h_self
; /* initiator port */
6848 /* target of 'self' config thread data */
6849 struct scsi_hba_mte_td
{
6850 struct scsi_hba_mte_h
*td_h
;
6851 char *td_taddr
; /* target port */
6856 /* Invoke callback on a vector of taddrs from multiple threads */
6858 scsi_hba_thread_taddrs(dev_info_t
*self
, char **taddrs
, int mt
,
6859 scsi_enum_t se
, void (*callback
)(void *arg
))
6861 struct scsi_hba_mte_h
*h
; /* HBA header */
6862 struct scsi_hba_mte_td
*td
; /* target data */
6865 /* allocate and initialize the handle */
6866 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
6867 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
6868 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
6871 /* loop over all the targets */
6872 for (taddr
= taddrs
; *taddr
; taddr
++) {
6873 /* allocate a thread data structure for target */
6874 td
= kmem_alloc(sizeof (*td
), KM_SLEEP
);
6876 td
->td_taddr
= *taddr
;
6880 /* process the target */
6881 mutex_enter(&h
->h_lock
);
6883 mutex_exit(&h
->h_lock
);
6885 if (mt
& SCSI_ENUMERATION_MT_TARGET_DISABLE
)
6886 callback((void *)td
);
6888 (void) thread_create(NULL
, 0, callback
, (void *)td
,
6889 0, &p0
, TS_RUN
, minclsyspri
);
6892 /* wait for all the target threads to complete */
6893 mutex_enter(&h
->h_lock
);
6894 while (h
->h_thr_count
> 0)
6895 cv_wait(&h
->h_cv
, &h
->h_lock
);
6896 mutex_exit(&h
->h_lock
);
6898 /* free the handle */
6899 cv_destroy(&h
->h_cv
);
6900 mutex_destroy(&h
->h_lock
);
6901 kmem_free(h
, sizeof (*h
));
6905 /* lun/secondary function of lun0 config thread data */
6906 struct scsi_hba_mte_ld
{
6907 struct scsi_hba_mte_h
*ld_h
;
6908 char *ld_taddr
; /* target port */
6909 scsi_lun64_t ld_lun64
; /* lun */
6910 int ld_sfunc
; /* secondary function */
6915 * Enumerate the LUNs and secondary functions of the specified target. The
6916 * target portion of the "@addr" is already represented as a string in the
6917 * thread data, we add a ",lun" representation to this and perform a
6918 * bus_configone byte of enumeration on that "@addr".
6921 scsi_hba_enum_lsf_of_tgt_thr(void *arg
)
6923 struct scsi_hba_mte_ld
*ld
= (struct scsi_hba_mte_ld
*)arg
;
6924 struct scsi_hba_mte_h
*h
= ld
->ld_h
;
6925 dev_info_t
*self
= h
->h_self
;
6926 char addr
[SCSI_MAXNAMELEN
];
6928 /* make string form of "@taddr,lun[,sfunc]" and see if it exists */
6929 if (ld
->ld_sfunc
== -1)
6930 (void) snprintf(addr
, sizeof (addr
),
6931 "%s,%" PRIx64
, ld
->ld_taddr
, ld
->ld_lun64
);
6933 (void) snprintf(addr
, sizeof (addr
),
6934 "%s,%" PRIx64
",%x",
6935 ld
->ld_taddr
, ld
->ld_lun64
, ld
->ld_sfunc
);
6937 /* configure device at that unit-address address */
6938 (void) scsi_hba_bus_configone_addr(self
, addr
, ld
->ld_se
);
6940 /* signal completion of this LUN thread to the target */
6941 mutex_enter(&h
->h_lock
);
6942 if (--h
->h_thr_count
== 0)
6943 cv_broadcast(&h
->h_cv
);
6944 mutex_exit(&h
->h_lock
);
6946 /* free config thread data */
6947 kmem_free(ld
, sizeof (*ld
));
6950 /* Format of SCSI REPORT_LUNS report */
6951 typedef struct scsi_lunrpt
{
6952 uchar_t lunrpt_len_msb
; /* # LUNs being reported */
6953 uchar_t lunrpt_len_mmsb
;
6954 uchar_t lunrpt_len_mlsb
;
6955 uchar_t lunrpt_len_lsb
;
6956 uchar_t lunrpt_reserved
[4];
6957 scsi_lun_t lunrpt_luns
[1]; /* LUNs, variable size */
6961 * scsi_device_reportluns()
6963 * Callers of this routine should ensure that the 'sd0' scsi_device structure
6964 * and 'pi' path_instance specified are associated with a responding LUN0.
6965 * This should not be called for SCSI-1 devices.
6967 * To get a LUN report, we must allocate a buffer. To know how big to make the
6968 * buffer, we must know the number of LUNs. To know the number of LUNs, we must
6969 * get a LUN report. We first issue a SCMD_REPORT_LUNS command using a
6970 * reasonably sized buffer that's big enough to report all LUNs for most
6971 * typical devices. If it turns out that we needed a bigger buffer, we attempt
6972 * to allocate a buffer of sufficient size, and reissue the command. If the
6973 * first command succeeds, but the second fails, we return whatever we were
6974 * able to get the first time. We return enough information for the caller to
6975 * tell whether they got all the LUNs or only a subset.
6977 * If successful, we allocate an array of scsi_lun_t to hold the results. The
6978 * caller must kmem_free(*lunarrayp, *sizep) when finished with it. Upon
6979 * successful return return value is NDI_SUCCESS and:
6981 * *lunarrayp points to the allocated array,
6982 * *nlunsp is the number of valid LUN entries in the array,
6983 * *tlunsp is the total number of LUNs in the target,
6984 * *sizep is the size of the lunarrayp array, which must be freed.
6986 * If the *nlunsp is less than *tlunsp, then we were only able to retrieve a
6987 * subset of the total set of LUNs in the target.
6990 scsi_device_reportluns(struct scsi_device
*sd0
, char *taddr
, int pi
,
6991 scsi_lun_t
**lunarrayp
, uint32_t *nlunsp
, uint32_t *tlunsp
, size_t *sizep
)
6993 struct buf
*lunrpt_bp
;
6994 struct scsi_pkt
*lunrpt_pkt
;
6995 scsi_lunrpt_t
*lunrpt
;
6997 uint32_t tluns
, nluns
;
6998 int default_maxluns
= scsi_lunrpt_default_max
;
7001 ASSERT(sd0
&& lunarrayp
&& nlunsp
&& tlunsp
&& sizep
);
7004 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7005 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7006 * of a child of the 'self' pHCI we are enumerating.
7008 child
= sd0
->sd_dev
;
7010 /* first try, look for up to scsi_lunrpt_default_max LUNs */
7011 nluns
= default_maxluns
;
7013 again
: bsize
= sizeof (struct scsi_lunrpt
) +
7014 ((nluns
- 1) * sizeof (struct scsi_lun
));
7016 lunrpt_bp
= scsi_alloc_consistent_buf(&sd0
->sd_address
,
7017 NULL
, bsize
, B_READ
, SLEEP_FUNC
, NULL
);
7018 if (lunrpt_bp
== NULL
) {
7019 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed alloc"));
7023 lunrpt_pkt
= scsi_init_pkt(&sd0
->sd_address
,
7024 NULL
, lunrpt_bp
, CDB_GROUP5
,
7025 sizeof (struct scsi_arq_status
), 0, PKT_CONSISTENT
,
7027 if (lunrpt_pkt
== NULL
) {
7028 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed init"));
7029 scsi_free_consistent_buf(lunrpt_bp
);
7033 (void) scsi_setup_cdb((union scsi_cdb
*)lunrpt_pkt
->pkt_cdbp
,
7034 SCMD_REPORT_LUNS
, 0, bsize
, 0);
7036 lunrpt_pkt
->pkt_time
= scsi_lunrpt_timeout
;
7039 * When sd0 is a vHCI scsi device, we need reportlun to be issued
7040 * against a specific LUN0 path_instance that we are enumerating.
7042 lunrpt_pkt
->pkt_path_instance
= pi
;
7043 lunrpt_pkt
->pkt_flags
|= FLAG_PKT_PATH_INSTANCE
;
7046 * NOTE: scsi_poll may not allow HBA specific recovery from TRAN_BUSY.
7048 if (scsi_poll(lunrpt_pkt
) < 0) {
7049 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "reportlun not supported"));
7050 scsi_destroy_pkt(lunrpt_pkt
);
7051 scsi_free_consistent_buf(lunrpt_bp
);
7052 return (NDI_FAILURE
);
7055 scsi_destroy_pkt(lunrpt_pkt
);
7057 lunrpt
= (scsi_lunrpt_t
*)lunrpt_bp
->b_un
.b_addr
;
7059 /* Compute the total number of LUNs in the target */
7060 tluns
= (((uint_t
)lunrpt
->lunrpt_len_msb
<< 24) |
7061 ((uint_t
)lunrpt
->lunrpt_len_mmsb
<< 16) |
7062 ((uint_t
)lunrpt
->lunrpt_len_mlsb
<< 8) |
7063 ((uint_t
)lunrpt
->lunrpt_len_lsb
)) >> 3;
7066 /* Illegal response -- this target is broken */
7067 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "illegal tluns of zero"));
7068 scsi_free_consistent_buf(lunrpt_bp
);
7069 return (DDI_NOT_WELL_FORMED
);
7072 if (tluns
> nluns
) {
7073 /* have more than we allocated space for */
7074 if (nluns
== default_maxluns
) {
7075 /* first time around, reallocate larger */
7076 scsi_free_consistent_buf(lunrpt_bp
);
7081 /* uh oh, we got a different tluns the second time! */
7082 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
7083 "tluns changed from %d to %d", nluns
, tluns
));
7089 * lunrpt_bp is the buffer we're using;
7090 * tluns is the total number of LUNs the target says it has;
7091 * nluns is the number of LUNs we were able to get into the buffer.
7093 * Copy the data out of scarce iopb memory into regular kmem.
7094 * The caller must kmem_free(*lunarrayp, *sizep) when finished with it.
7096 *lunarrayp
= (scsi_lun_t
*)kmem_alloc(
7097 nluns
* sizeof (scsi_lun_t
), KM_SLEEP
);
7098 if (*lunarrayp
== NULL
) {
7099 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "NULL lunarray"));
7100 scsi_free_consistent_buf(lunrpt_bp
);
7104 *sizep
= nluns
* sizeof (scsi_lun_t
);
7107 bcopy((void *)&lunrpt
->lunrpt_luns
, (void *)*lunarrayp
, *sizep
);
7108 scsi_free_consistent_buf(lunrpt_bp
);
7109 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
7110 "@%s,0 path %d: %d/%d luns", taddr
, pi
, nluns
, tluns
));
7111 return (NDI_SUCCESS
);
7115 * Enumerate all the LUNs and secondary functions of the specified 'taddr'
7116 * target port as accessed via 'self' pHCI. Note that sd0 may be associated
7117 * with a child of the vHCI instead of 'self' - in this case the 'pi'
7118 * path_instance is used to ensure that the SCMD_REPORT_LUNS command is issued
7119 * through the 'self' pHCI path.
7121 * We multi-thread across all the LUNs and secondary functions and enumerate
7122 * them. Which LUNs exist is based on SCMD_REPORT_LUNS data.
7124 * The scsi_device we are called with should be for LUN0 and has been probed.
7126 * This function is structured so that an HBA that has a different target
7127 * addressing structure can still use this function to enumerate the its
7128 * LUNs if it uses "taddr,lun" for its LUN space.
7130 * We make assumptions about other LUNs associated with the target:
7132 * For SCSI-2 and SCSI-3 target we will issue the SCSI report_luns
7133 * command. If this fails or we have a SCSI-1 then the number of
7134 * LUNs is determined based on SCSI_OPTIONS_NLUNS. For a SCSI-1
7135 * target we never probe above LUN 8, even if SCSI_OPTIONS_NLUNS
7136 * indicates we should.
7138 * HBA drivers wanting a different set of assumptions should implement their
7139 * own LUN enumeration code.
7142 scsi_hba_enum_lsf_of_t(struct scsi_device
*sd0
,
7143 dev_info_t
*self
, char *taddr
, int pi
, int mt
, scsi_enum_t se
)
7146 scsi_hba_tran_t
*tran
;
7147 impl_scsi_tgtmap_t
*tgtmap
;
7150 damap_t
*lundam
= NULL
;
7151 struct scsi_hba_mte_h
*h
;
7152 struct scsi_hba_mte_ld
*ld
;
7154 scsi_lun_t
*lunp
= NULL
;
7163 * If LUN0 failed then we have no other LUNs.
7165 * NOTE: We need sd_inq to be valid to check ansi version. Since
7166 * scsi_unprobe is now a noop (sd_inq freeded in
7167 * scsi_busctl_uninitchild) sd_inq remains valid even if a target
7168 * driver detach(9E) occurs, resulting in a scsi_unprobe call
7169 * (sd_uninit_prevent keeps sd_inq valid by failing any
7170 * device_uninitchild attempts).
7172 ASSERT(sd0
&& sd0
->sd_uninit_prevent
&& sd0
->sd_dev
&& sd0
->sd_inq
);
7173 if ((sd0
== NULL
) || (sd0
->sd_dev
== NULL
) || (sd0
->sd_inq
== NULL
)) {
7174 SCSI_HBA_LOG((_LOG(1), NULL
, sd0
? sd0
->sd_dev
: NULL
,
7175 "not setup correctly:%s%s%s",
7176 (sd0
== NULL
) ? " device" : "",
7177 (sd0
&& (sd0
->sd_dev
== NULL
)) ? " dip" : "",
7178 (sd0
&& (sd0
->sd_inq
== NULL
)) ? " inq" : ""));
7179 return (DDI_FAILURE
);
7183 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7184 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7185 * of a child of the 'self' pHCI we are enumerating.
7187 child
= sd0
->sd_dev
;
7189 /* Determine if we are reporting lun observations into lunmap. */
7190 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7191 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7193 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
7194 tgtid
= damap_lookup(tgtdam
, taddr
);
7195 if (tgtid
!= NODAM
) {
7196 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
7197 damap_id_rele(tgtdam
, tgtid
);
7203 /* If using lunmap, start the observation */
7204 scsi_lunmap_set_begin(self
, lundam
);
7206 /* allocate and initialize the LUN handle */
7207 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
7208 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
7209 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
7213 /* See if SCMD_REPORT_LUNS works for SCSI-2 and beyond */
7214 aver
= sd0
->sd_inq
->inq_ansi
;
7215 if ((aver
>= SCSI_VERSION_2
) && (scsi_device_reportluns(sd0
,
7216 taddr
, pi
, &lunp
, &nluns
, &tluns
, &size
) == NDI_SUCCESS
)) {
7218 ASSERT(lunp
&& (size
> 0) && (nluns
> 0) && (tluns
> 0));
7220 /* loop over the reported LUNs */
7221 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7222 "@%s,0 path %d: enumerating %d reported lun%s", taddr
, pi
,
7223 nluns
, nluns
> 1 ? "s" : ""));
7225 for (lun
= 0; lun
< nluns
; lun
++) {
7226 lun64
= scsi_lun_to_lun64(lunp
[lun
]);
7229 if (scsi_lunmap_set_add(self
, lundam
,
7230 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7231 SCSI_HBA_LOG((_LOG_NF(WARN
),
7232 "@%s,%" PRIx64
" failed to create",
7239 /* allocate a thread data structure for LUN */
7240 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7242 ld
->ld_taddr
= taddr
;
7243 ld
->ld_lun64
= lun64
;
7247 /* process the LUN */
7248 mutex_enter(&h
->h_lock
);
7250 mutex_exit(&h
->h_lock
);
7252 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7253 scsi_hba_enum_lsf_of_tgt_thr(
7256 (void) thread_create(NULL
, 0,
7257 scsi_hba_enum_lsf_of_tgt_thr
,
7258 (void *)ld
, 0, &p0
, TS_RUN
,
7263 /* free the LUN array allocated by scsi_device_reportluns */
7264 kmem_free(lunp
, size
);
7266 /* Determine the number of LUNs to enumerate. */
7267 maxluns
= scsi_get_scsi_maxluns(sd0
);
7269 /* Couldn't get SCMD_REPORT_LUNS data */
7270 if (aver
>= SCSI_VERSION_3
) {
7271 scsi_enumeration_failed(child
, se
, taddr
, "report_lun");
7274 * Based on calling context tunable, only enumerate one
7275 * lun (lun0) if scsi_device_reportluns() fails on a
7276 * SCSI_VERSION_3 or greater device.
7278 if (scsi_lunrpt_failed_do1lun
& (1 << se
))
7282 /* loop over possible LUNs, skipping LUN0 */
7284 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7285 "@%s,0 path %d: enumerating luns 1-%d", taddr
, pi
,
7288 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7289 "@%s,0 path %d: enumerating just lun0", taddr
, pi
));
7291 for (lun64
= 0; lun64
< maxluns
; lun64
++) {
7293 if (scsi_lunmap_set_add(self
, lundam
,
7294 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7295 SCSI_HBA_LOG((_LOG_NF(WARN
),
7296 "@%s,%" PRIx64
" failed to create",
7303 /* allocate a thread data structure for LUN */
7304 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7306 ld
->ld_taddr
= taddr
;
7307 ld
->ld_lun64
= lun64
;
7311 /* process the LUN */
7312 mutex_enter(&h
->h_lock
);
7314 mutex_exit(&h
->h_lock
);
7315 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7316 scsi_hba_enum_lsf_of_tgt_thr(
7319 (void) thread_create(NULL
, 0,
7320 scsi_hba_enum_lsf_of_tgt_thr
,
7321 (void *)ld
, 0, &p0
, TS_RUN
,
7328 * If we have an embedded service as a secondary function on LUN0 and
7329 * the primary LUN0 function is different than the secondary function
7330 * then enumerate the secondary function. The sfunc value is the dtype
7331 * associated with the embedded service.
7333 * inq_encserv: enclosure service and our dtype is not DTYPE_ESI
7334 * or DTYPE_UNKNOWN then create a separate DTYPE_ESI node for
7335 * enclosure service access.
7337 ASSERT(sd0
->sd_inq
);
7338 if (sd0
->sd_inq
->inq_encserv
&&
7339 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_UNKNOWN
) &&
7340 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_ESI
) &&
7341 ((sd0
->sd_inq
->inq_ansi
>= SCSI_VERSION_3
))) {
7343 if (scsi_lunmap_set_add(self
, lundam
,
7344 taddr
, 0, DTYPE_ESI
) != DDI_SUCCESS
) {
7345 SCSI_HBA_LOG((_LOG_NF(WARN
),
7346 "@%s,0,%x failed to create",
7350 /* allocate a thread data structure for sfunc */
7351 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7353 ld
->ld_taddr
= taddr
;
7355 ld
->ld_sfunc
= DTYPE_ESI
;
7358 /* process the LUN */
7359 mutex_enter(&h
->h_lock
);
7361 mutex_exit(&h
->h_lock
);
7362 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7363 scsi_hba_enum_lsf_of_tgt_thr((void *)ld
);
7365 (void) thread_create(NULL
, 0,
7366 scsi_hba_enum_lsf_of_tgt_thr
, (void *)ld
,
7367 0, &p0
, TS_RUN
, minclsyspri
);
7372 * Future: Add secondary function support for:
7373 * inq_mchngr (DTYPE_CHANGER)
7374 * inq_sccs (DTYPE_ARRAY_CTRL)
7378 /* If using lunmap, end the observation */
7379 scsi_lunmap_set_end(self
, lundam
);
7381 /* wait for all the LUN threads of this target to complete */
7382 mutex_enter(&h
->h_lock
);
7383 while (h
->h_thr_count
> 0)
7384 cv_wait(&h
->h_cv
, &h
->h_lock
);
7385 mutex_exit(&h
->h_lock
);
7387 /* free the target handle */
7388 cv_destroy(&h
->h_cv
);
7389 mutex_destroy(&h
->h_lock
);
7390 kmem_free(h
, sizeof (*h
));
7393 return (DDI_SUCCESS
);
7397 * Enumerate LUN0 and all other LUNs and secondary functions associated with
7398 * the specified target address.
7400 * Return NDI_SUCCESS if we might have created a new node.
7401 * Return NDI_FAILURE if we definitely did not create a new node.
7404 scsi_hba_bus_config_taddr(dev_info_t
*self
, char *taddr
, int mt
, scsi_enum_t se
)
7406 char addr
[SCSI_MAXNAMELEN
];
7407 struct scsi_device
*sd
;
7412 /* See if LUN0 of the specified target exists. */
7413 (void) snprintf(addr
, sizeof (addr
), "%s,0", taddr
);
7415 scsi_hba_devi_enter(self
, &circ
);
7416 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, &pi
);
7420 * LUN0 exists, enumerate all the other LUNs.
7422 * With vHCI enumeration, when 'self' is a pHCI the sd
7423 * scsi_device may be associated with the vHCI 'client'.
7424 * In this case 'pi' is the path_instance needed to
7425 * continue enumeration communication LUN0 via 'self'
7426 * pHCI and specific 'taddr' target address.
7428 * We prevent the removal of LUN0 until we are done with
7429 * prevent/allow because we must exit the parent for
7430 * multi-threaded scsi_hba_enum_lsf_of_t().
7432 * NOTE: scsi_unprobe is a noop, sd->sd_inq is valid until
7433 * device_uninitchild - so sd_uninit_prevent keeps sd_inq valid
7434 * by failing any device_uninitchild attempts.
7437 sd
->sd_uninit_prevent
++;
7438 scsi_hba_devi_exit(self
, circ
);
7440 (void) scsi_hba_enum_lsf_of_t(sd
, self
, taddr
, pi
, mt
, se
);
7442 scsi_hba_devi_enter(self
, &circ
);
7443 sd
->sd_uninit_prevent
--;
7446 scsi_hba_devi_exit(self
, circ
);
7450 /* Config callout from scsi_hba_thread_taddrs */
7452 scsi_hba_taddr_config_thr(void *arg
)
7454 struct scsi_hba_mte_td
*td
= (struct scsi_hba_mte_td
*)arg
;
7455 struct scsi_hba_mte_h
*h
= td
->td_h
;
7457 (void) scsi_hba_bus_config_taddr(h
->h_self
, td
->td_taddr
,
7458 td
->td_mt
, td
->td_se
);
7460 /* signal completion of this target thread to the HBA */
7461 mutex_enter(&h
->h_lock
);
7462 if (--h
->h_thr_count
== 0)
7463 cv_broadcast(&h
->h_cv
);
7464 mutex_exit(&h
->h_lock
);
7466 /* free config thread data */
7467 kmem_free(td
, sizeof (*td
));
7471 * Enumerate all the children of the specified SCSI parallel interface (spi).
7472 * An HBA associated with a non-parallel scsi bus should be using another bus
7473 * level enumeration implementation (possibly their own) and calling
7474 * scsi_hba_bus_config_taddr to do enumeration of devices associated with a
7475 * particular target address.
7477 * On an spi bus the targets are sequentially enumerated based on the
7478 * width of the bus. We also take care to try to skip the HBAs own initiator
7479 * id. See scsi_hba_enum_lsf_of_t() for LUN and secondary function enumeration.
7481 * Return NDI_SUCCESS if we might have created a new node.
7482 * Return NDI_FAILURE if we definitely did not create a new node.
7484 * Note: At some point we may want to expose this interface in transport.h
7485 * if we find an hba that implements bus_config but still uses spi-like target
7489 scsi_hba_bus_configall_spi(dev_info_t
*self
, int mt
)
7500 * Find the number of targets supported on the bus. Look at the per
7501 * bus scsi-options property on the HBA node and check its
7502 * SCSI_OPTIONS_WIDE setting.
7504 options
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7505 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-options", -1);
7506 if ((options
!= -1) && ((options
& SCSI_OPTIONS_WIDE
) == 0))
7507 ntargets
= NTARGETS
; /* 8 */
7509 ntargets
= NTARGETS_WIDE
; /* 16 */
7512 * Find the initiator-id for the HBA so we can skip that. We get the
7513 * cached value on the HBA node, established in scsi_hba_attach_setup.
7514 * If we were unable to determine the id then we rely on the HBA to
7515 * fail gracefully when asked to enumerate itself.
7517 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7518 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-initiator-id", -1);
7519 if (id
> ntargets
) {
7520 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
7521 "'scsi-initiator-id' bogus for %d target bus: %d",
7525 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7526 "enumerating targets 0-%d skip %d", ntargets
, id
));
7528 /* form vector of target addresses */
7529 taddrs
= kmem_zalloc(sizeof (char *) * (ntargets
+ 1), KM_SLEEP
);
7530 for (tgt
= 0, taddr
= taddrs
; tgt
< ntargets
; tgt
++) {
7531 /* skip initiator */
7535 /* convert to string and enumerate the target address */
7536 tbuf
= kmem_alloc(((tgt
/16) + 1) + 1, KM_SLEEP
);
7537 (void) sprintf(tbuf
, "%x", tgt
);
7538 ASSERT(strlen(tbuf
) == ((tgt
/16) + 1));
7542 /* null terminate vector of target addresses */
7545 /* configure vector of target addresses */
7546 scsi_hba_thread_taddrs(self
, taddrs
, mt
, SE_BUSCONFIG
,
7547 scsi_hba_taddr_config_thr
);
7549 /* free vector of target addresses */
7550 for (taddr
= taddrs
; *taddr
; taddr
++)
7551 kmem_free(*taddr
, strlen(*taddr
) + 1);
7552 kmem_free(taddrs
, sizeof (char *) * (ntargets
+ 1));
7553 return (NDI_SUCCESS
);
7557 * Transport independent bus_configone BUS_CONFIG_ONE implementation. Takes
7558 * same arguments, minus op, as scsi_hba_bus_config(), tran_bus_config(),
7559 * and scsi_hba_bus_config_spi().
7562 scsi_hba_bus_configone(dev_info_t
*self
, uint_t flags
, char *arg
,
7563 dev_info_t
**childp
)
7570 char nameaddr
[SCSI_MAXNAMELEN
];
7571 extern int i_ndi_make_spec_children(dev_info_t
*, uint_t
);
7572 struct scsi_device
*sd0
, *sd
;
7576 /* parse_name modifies arg1, we must duplicate "name@addr" */
7577 (void) strcpy(nameaddr
, arg
);
7578 i_ddi_parse_name(nameaddr
, &name
, &addr
, NULL
);
7580 /* verify the form of the node - we need an @addr */
7581 if ((name
== NULL
) || (addr
== NULL
) ||
7582 (*name
== '\0') || (*addr
== '\0')) {
7584 * OBP may create ill formed template/stub/wild-card
7585 * nodes (no @addr) for legacy driver loading methods -
7588 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "%s ill formed", arg
));
7589 return (NDI_FAILURE
);
7593 * Check to see if this is a non-scsi flavor configuration operation.
7595 if (strcmp(name
, "smp") == 0) {
7597 * Configure the child, and if we're successful return with
7600 return (smp_hba_bus_config(self
, addr
, childp
));
7604 * The framework does not ensure the creation of driver.conf
7605 * nodes prior to calling a nexus bus_config. For legacy
7606 * support of driver.conf file nodes we want to create our
7607 * driver.conf file children now so that we can detect if we
7608 * are being asked to bus_configone one of these nodes.
7610 * Needing driver.conf file nodes prior to bus config is unique
7611 * to scsi_enumeration mixed mode (legacy driver.conf and
7612 * dynamic SID node) support. There is no general need for the
7613 * framework to make driver.conf children prior to bus_config.
7615 * We enter our HBA (self) prior to scsi_device_config, and
7616 * pass it our circ. The scsi_device_config may exit the
7617 * HBA around scsi_probe() operations to allow for parallelism.
7618 * This is done after the probe node "@addr" is available as a
7619 * barrier to prevent parallel probes of the same device. The
7620 * probe node is also configured in a way that it can't be
7621 * removed by the framework until we are done with it.
7623 * NOTE: The framework is currently preventing many parallel
7624 * sibling operations (such as attaches), so the parallelism
7625 * we are providing is of marginal use until that is improved.
7626 * The most logical way to solve this would be to have separate
7627 * target and lun nodes. This would be a large change in the
7628 * format of /devices paths and is not being pursued at this
7629 * time. The need for parallelism will become more of an issue
7630 * with top-down attach for mpxio/vhci and for iSCSI support.
7631 * We may want to eventually want a dual mode implementation,
7632 * where the HBA determines if we should construct separate
7633 * target and lun devinfo nodes.
7635 scsi_hba_devi_enter(self
, &circ
);
7636 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s config_one", name
, addr
));
7637 (void) i_ndi_make_spec_children(self
, flags
);
7640 * For bus_configone, we make sure that we can find LUN0
7641 * first. This allows the delayed probe/barrier deletion for a
7642 * non-existent LUN0 (if enabled in scsi_device_config) to
7643 * cover all LUNs on the target. This is done to minimize the
7644 * number of independent target selection timeouts that occur
7645 * when a target with many LUNs is no longer accessible
7646 * (powered off). This removes the need for target driver
7647 * probe cache implementations.
7649 * This optimization may not be desirable in a pure bridge
7650 * environment where targets on the other side of the bridge
7651 * show up as LUNs to the host. If we ever need to support
7652 * such a configuration then we should consider implementing a
7653 * SCSI_OPTIONS_ILUN0 bit.
7655 * NOTE: we are *not* applying any target limitation filtering
7656 * to bus_configone, which means that we are relying on the
7657 * HBA tran_tgt_init entry point invoked by scsi_busctl_initchild
7660 sd0
= (struct scsi_device
*)-1;
7661 lcp
= strchr(addr
, ','); /* "addr,lun[,sfunc]" */
7664 * With "tgt,lun[,sfunc]" addressing, multiple addressing levels
7665 * have been compressed into single devinfo node unit-address.
7666 * This presents a mismatch - there is no bus_config to discover
7667 * LUNs below a specific target, the only choice is to
7668 * BUS_CONFIG_ALL the HBA. To support BUS_CONFIG_ALL_LUNS below
7669 * a specific target, a bus_configone with lun address of "*"
7670 * triggers lun discovery below a target.
7672 if (*(lcp
+ 1) == '*') {
7673 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7674 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7675 "scsi-enumeration", scsi_enumeration
);
7676 mt
|= scsi_hba_log_mt_disable
;
7678 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7679 "%s@%s lun enumeration triggered", name
, addr
));
7680 *lcp
= '\0'; /* turn ',' into '\0' */
7681 scsi_hba_devi_exit(self
, circ
);
7682 (void) scsi_hba_bus_config_taddr(self
, addr
,
7684 return (NDI_FAILURE
);
7687 /* convert hex lun number from ascii */
7688 lun64
= scsi_addr_to_lun64(lcp
+ 1);
7690 if ((lun64
!= 0) && (lun64
!= SCSI_LUN64_ILLEGAL
)) {
7692 * configure ",0" lun first, saving off
7693 * original lun characters.
7699 sd0
= scsi_device_config(self
,
7700 NULL
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7702 /* restore original lun */
7707 * Apply maxlun filtering.
7709 * Future: We still have the kludged
7710 * scsi_check_ss2_LUN_limit() filtering off
7711 * scsi_probe() to catch bogus driver.conf
7714 if (sd0
&& (lun64
< SCSI_32LUNS_PER_TARGET
) &&
7715 (lun64
>= scsi_get_scsi_maxluns(sd0
))) {
7717 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7718 "%s@%s filtered", name
, addr
));
7720 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7721 "%s@%s lun 0 %s", name
, addr
,
7722 sd0
? "worked" : "failed"));
7727 * configure the requested device if LUN0 exists or we were
7728 * unable to determine the lun format to determine if LUN0
7732 sd
= scsi_device_config(self
,
7733 name
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7736 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7737 "%s@%s no lun 0 or filtered lun", name
, addr
));
7741 * We know what we found, to reduce overhead we finish BUS_CONFIG_ONE
7742 * processing without calling back to the frameworks
7743 * ndi_busop_bus_config (unless we goto framework below).
7745 * If the reference is to a driver name and we created a generic name
7746 * (bound to that driver) we will still succeed. This is important
7747 * for correctly resolving old drivername references to device that now
7748 * uses a generic names across the transition to generic naming. This
7749 * is effectively an internal implementation of the NDI_DRIVERNAME flag.
7751 * We also need to special case the resolve_pathname OBP boot-device
7752 * case (modrootloaded == 0) where reference is to a generic name but
7753 * we created a legacy driver name node by returning just returning
7756 if (sd
&& sd
->sd_dev
&&
7757 ((strcmp(ddi_node_name(sd
->sd_dev
), name
) == 0) ||
7758 (strcmp(ddi_driver_name(sd
->sd_dev
), name
) == 0) ||
7759 (modrootloaded
== 0)) &&
7760 (ndi_devi_online(sd
->sd_dev
,
7761 flags
& NDI_NO_EVENT
) == NDI_SUCCESS
)) {
7763 /* device attached, return devinfo node with hold */
7765 *childp
= sd
->sd_dev
;
7766 ndi_hold_devi(sd
->sd_dev
);
7769 * In the process of failing we may have added nodes to the HBA
7770 * (self), clearing DEVI_MADE_CHILDREN. To reduce the overhead
7771 * associated with the frameworks reaction to this we clear the
7774 mutex_enter(&DEVI(self
)->devi_lock
);
7775 DEVI(self
)->devi_flags
&= ~DEVI_MADE_CHILDREN
;
7776 mutex_exit(&DEVI(self
)->devi_lock
);
7780 * The framework may still be able to succeed with
7781 * with its GENERIC_PROP code.
7783 scsi_hba_devi_exit(self
, circ
);
7784 if (flags
& NDI_DRV_CONF_REPROBE
)
7785 flags
|= NDI_CONFIG_REPROBE
;
7786 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7787 return (ndi_busop_bus_config(self
, flags
, BUS_CONFIG_ONE
,
7788 (void *)arg
, childp
, 0));
7791 scsi_hba_devi_exit(self
, circ
);
7796 * Perform SCSI Parallel Interconnect bus_config
7799 scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
7800 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7806 * Enumerate scsi target devices: See if we are doing generic dynamic
7807 * enumeration: if driver.conf has not specified the 'scsi-enumeration'
7808 * knob then use the global scsi_enumeration knob.
7810 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7811 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7812 "scsi-enumeration", scsi_enumeration
);
7813 mt
|= scsi_hba_log_mt_disable
;
7815 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0) {
7817 * Static driver.conf file enumeration:
7819 * Force reprobe for BUS_CONFIG_ONE or when manually
7820 * reconfiguring via devfsadm(1m) to emulate deferred attach.
7821 * Reprobe only discovers driver.conf enumerated nodes, more
7822 * dynamic implementations probably require their own
7825 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
7826 flags
|= NDI_CONFIG_REPROBE
;
7827 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7828 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
7831 if (scsi_hba_bus_config_debug
)
7832 flags
|= NDI_DEVI_DEBUG
;
7835 * Generic spi dynamic bus config enumeration to discover and enumerate
7836 * the target device nodes we are looking for.
7839 case BUS_CONFIG_ONE
: /* enumerate the named child */
7840 ret
= scsi_hba_bus_configone(self
, flags
, (char *)arg
, childp
);
7843 case BUS_CONFIG_ALL
: /* enumerate all children on the bus */
7844 case BUS_CONFIG_DRIVER
: /* enumerate all children that bind to driver */
7845 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7846 "BUS_CONFIG_%s mt %x",
7847 (op
== BUS_CONFIG_ALL
) ? "ALL" : "DRIVER", mt
));
7850 * Enumerate targets on SCSI parallel interconnect and let the
7851 * framework finish the operation (attach the nodes).
7853 if ((ret
= scsi_hba_bus_configall_spi(self
, mt
)) == NDI_SUCCESS
)
7854 ret
= ndi_busop_bus_config(self
, flags
, op
,
7866 * Perform SCSI Parallel Interconnect bus_unconfig
7869 scsi_hba_bus_unconfig_spi(dev_info_t
*self
, uint_t flags
,
7870 ddi_bus_config_op_t op
, void *arg
)
7877 * See if we are doing generic dynamic enumeration: if driver.conf has
7878 * not specified the 'scsi-enumeration' knob then use the global
7879 * scsi_enumeration knob.
7881 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7882 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7883 "scsi-enumeration", scsi_enumeration
);
7884 mt
|= scsi_hba_log_mt_disable
;
7886 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0)
7887 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
7889 if (scsi_hba_bus_config_debug
)
7890 flags
|= NDI_DEVI_DEBUG
;
7892 scsi_hba_devi_enter(self
, &circ
);
7894 case BUS_UNCONFIG_ONE
:
7895 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7896 "unconfig one: %s", (char *)arg
));
7900 case BUS_UNCONFIG_ALL
:
7901 case BUS_UNCONFIG_DRIVER
:
7910 /* Perform the generic default bus unconfig */
7911 if (ret
== NDI_SUCCESS
)
7912 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
7914 scsi_hba_devi_exit(self
, circ
);
7920 scsi_hba_bus_config_tgtmap(dev_info_t
*self
, uint_t flags
,
7921 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7923 scsi_hba_tran_t
*tran
;
7924 impl_scsi_tgtmap_t
*tgtmap
;
7925 uint64_t tsa
= 0; /* clock64_t */
7929 int ret
= NDI_FAILURE
;
7931 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
7932 (op
!= BUS_CONFIG_DRIVER
))
7935 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7936 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7940 * MPXIO is never a sure thing (and we have mixed children), so
7941 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
7942 * search for both devinfo and pathinfo children.
7944 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
7945 * devinfo/pathinfo children in parallel (instead of old way of
7946 * looking for one form of child and then doing "fallback" to
7947 * look for other form of child).
7949 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7952 * If bus_config occurred within the map create-to-hotplug_sync window,
7953 * we need the framework to wait for children that are physicaly
7954 * present at map create time to show up (via tgtmap hotplug config).
7956 * The duration of this window is specified by the HBA driver at
7957 * scsi_hba_tgtmap_create(9F) time (during attach(9E)). Its
7958 * 'csync_usec' value is selected based on how long it takes the HBA
7959 * driver to get from map creation to initial observation for something
7960 * already plugged in. Estimate high, a low estimate can result in
7961 * devices not showing up correctly on first reference. The call to
7962 * ndi_busop_bus_config needs a timeout value large enough so that
7963 * the map sync call further down is not a noop (i.e. done against
7964 * an empty map when something is infact plugged in). With
7965 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
7966 * soon as the desired device is enumerated via hotplug - so we are
7967 * not committed to waiting the entire time.
7969 * We are typically outside the window, so timeout is 0.
7971 sync_usec
= tgtmap
->tgtmap_create_csync_usec
;
7972 if (tgtmap
->tgtmap_create_window
) {
7973 tsa
= ddi_get_lbolt64() - tgtmap
->tgtmap_create_time
;
7974 if (tsa
< drv_usectohz(sync_usec
)) {
7975 tsa
= drv_usectohz(sync_usec
) - tsa
;
7976 ret
= ndi_busop_bus_config(self
,
7977 flags
, op
, arg
, childp
, (clock_t)tsa
);
7979 tsa
= 0; /* passed window */
7981 /* First one out closes the window. */
7982 tgtmap
->tgtmap_create_window
= 0;
7983 } else if (op
== BUS_CONFIG_ONE
)
7984 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
7986 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
7987 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
7988 goto out
; /* performance path */
7991 * We sync if we were in the window, on the first bus_config_one, and
7992 * every bus_config_all (or bus_config_driver).
7994 if (tsa
|| (tgtmap
->tgtmap_sync_cnt
== 0) ||
7995 (op
!= BUS_CONFIG_ONE
)) {
7997 * Sync current observations in the map and look again. We
7998 * place an upper bound on the amount of time we will wait for
7999 * sync to complete to avoid a bad device causing this
8000 * busconfig operation to hang.
8002 * We are typically stable, so damap_sync returns immediately.
8004 * Max time to wait for sync is settle_usec per possible device.
8006 tgtmap
->tgtmap_sync_cnt
++;
8007 maxdev
= damap_size(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8008 maxdev
= (maxdev
> scsi_hba_map_settle_f
) ? maxdev
:
8009 scsi_hba_map_settle_f
;
8010 sync_usec
= maxdev
* tgtmap
->tgtmap_settle_usec
;
8011 synced
= scsi_tgtmap_sync((scsi_hba_tgtmap_t
*)tgtmap
,
8014 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8015 "tgtmap_sync timeout"));
8019 if (op
== BUS_CONFIG_ONE
)
8020 ret
= scsi_hba_bus_configone(self
, flags
, arg
, childp
);
8022 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8026 if (ret
!= NDI_SUCCESS
) {
8027 if (scsi_hba_bus_config_failure_msg
||
8028 scsi_hba_bus_config_failure_dbg
) {
8029 scsi_hba_bus_config_failure_msg
--;
8030 printf("%s%d: bus_config_tgtmap %p failure on %s: "
8032 ddi_driver_name(self
), ddi_get_instance(self
),
8034 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8037 if (scsi_hba_bus_config_failure_dbg
) {
8038 scsi_hba_bus_config_failure_dbg
--;
8039 debug_enter("config_tgtmap failure");
8041 } else if (scsi_hba_bus_config_success_msg
||
8042 scsi_hba_bus_config_success_dbg
) {
8043 scsi_hba_bus_config_success_msg
--;
8044 printf("%s%d: bus_config_tgtmap %p success on %s: %d %d\n",
8045 ddi_driver_name(self
), ddi_get_instance(self
),
8047 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8049 if (scsi_hba_bus_config_success_dbg
) {
8050 scsi_hba_bus_config_success_dbg
--;
8051 debug_enter("config_tgtmap success");
8059 scsi_hba_bus_unconfig_tgtmap(dev_info_t
*self
, uint_t flags
,
8060 ddi_bus_config_op_t op
, void *arg
)
8062 int ret
= NDI_FAILURE
;
8065 case BUS_UNCONFIG_ONE
:
8066 case BUS_UNCONFIG_DRIVER
:
8067 case BUS_UNCONFIG_ALL
:
8074 if (ret
== NDI_SUCCESS
) {
8075 flags
&= ~NDI_DEVI_REMOVE
;
8076 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8082 scsi_hba_bus_config_iportmap(dev_info_t
*self
, uint_t flags
,
8083 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8085 scsi_hba_tran_t
*tran
;
8086 impl_scsi_iportmap_t
*iportmap
;
8089 uint64_t tsa
= 0; /* clock64_t */
8092 int ret
= NDI_FAILURE
;
8094 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
8095 (op
!= BUS_CONFIG_DRIVER
))
8098 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8099 iportmap
= (impl_scsi_iportmap_t
*)tran
->tran_iportmap
;
8103 * MPXIO is never a sure thing (and we have mixed children), so
8104 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
8105 * search for both devinfo and pathinfo children.
8107 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
8108 * devinfo/pathinfo children in parallel (instead of old way of
8109 * looking for one form of child and then doing "fallback" to
8110 * look for other form of child).
8112 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
8115 * If bus_config occurred within the map create-to-hotplug_sync window,
8116 * we need the framework to wait for children that are physicaly
8117 * present at map create time to show up (via iportmap hotplug config).
8119 * The duration of this window is specified by the HBA driver at
8120 * scsi_hba_iportmap_create(9F) time (during attach(9E)). Its
8121 * 'csync_usec' value is selected based on how long it takes the HBA
8122 * driver to get from map creation to initial observation for something
8123 * already plugged in. Estimate high, a low estimate can result in
8124 * devices not showing up correctly on first reference. The call to
8125 * ndi_busop_bus_config needs a timeout value large enough so that
8126 * the map sync call further down is not a noop (i.e. done against
8127 * an empty map when something is infact plugged in). With
8128 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
8129 * soon as the desired device is enumerated via hotplug - so we are
8130 * not committed to waiting the entire time.
8132 * We are typically outside the window, so timeout is 0.
8134 sync_usec
= iportmap
->iportmap_create_csync_usec
;
8135 if (iportmap
->iportmap_create_window
) {
8136 tsa
= ddi_get_lbolt64() - iportmap
->iportmap_create_time
;
8137 if (tsa
< drv_usectohz(sync_usec
)) {
8138 tsa
= drv_usectohz(sync_usec
) - tsa
;
8139 ret
= ndi_busop_bus_config(self
,
8140 flags
, op
, arg
, childp
, (clock_t)tsa
);
8142 tsa
= 0; /* passed window */
8144 /* First one out closes the window. */
8145 iportmap
->iportmap_create_window
= 0;
8146 } else if (op
== BUS_CONFIG_ONE
)
8147 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8149 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
8150 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
8151 goto out
; /* performance path */
8154 * We sync if we were in the window, on the first bus_config_one, and
8155 * every bus_config_all (or bus_config_driver).
8157 if (tsa
|| (iportmap
->iportmap_sync_cnt
== 0) ||
8158 (op
!= BUS_CONFIG_ONE
)) {
8160 * Sync current observations in the map and look again. We
8161 * place an upper bound on the amount of time we will wait for
8162 * sync to complete to avoid a bad device causing this
8163 * busconfig operation to hang.
8165 * We are typically stable, so damap_sync returns immediately.
8167 * Max time to wait for sync is settle_usec times settle factor.
8169 iportmap
->iportmap_sync_cnt
++;
8170 synced
= damap_sync(iportmap
->iportmap_dam
, sync_usec
);
8172 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8173 "iportmap_sync timeout"));
8177 if (op
== BUS_CONFIG_ONE
) {
8178 /* create the iport node child */
8179 scsi_hba_devi_enter(self
, &circ
);
8180 if ((child
= scsi_hba_bus_config_port(self
, (char *)arg
,
8181 SE_BUSCONFIG
)) != NULL
) {
8183 ndi_hold_devi(child
);
8188 scsi_hba_devi_exit(self
, circ
);
8190 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8194 if (ret
!= NDI_SUCCESS
) {
8195 if (scsi_hba_bus_config_failure_msg
||
8196 scsi_hba_bus_config_failure_dbg
) {
8197 scsi_hba_bus_config_failure_msg
--;
8198 printf("%s%d: bus_config_iportmap %p failure on %s: "
8200 ddi_driver_name(self
), ddi_get_instance(self
),
8202 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8205 if (scsi_hba_bus_config_failure_dbg
) {
8206 scsi_hba_bus_config_failure_dbg
--;
8207 debug_enter("config_iportmap failure");
8209 } else if (scsi_hba_bus_config_success_msg
||
8210 scsi_hba_bus_config_success_dbg
) {
8211 scsi_hba_bus_config_success_msg
--;
8212 printf("%s%d: bus_config_iportmap %p success on %s: %d %d\n",
8213 ddi_driver_name(self
), ddi_get_instance(self
),
8215 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8217 if (scsi_hba_bus_config_success_dbg
) {
8218 scsi_hba_bus_config_success_dbg
--;
8219 debug_enter("config_iportmap success");
8227 scsi_hba_bus_unconfig_iportmap(dev_info_t
*self
, uint_t flags
,
8228 ddi_bus_config_op_t op
, void *arg
)
8230 flags
&= ~NDI_DEVI_REMOVE
;
8231 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8235 * SCSI HBA bus config enumeration entry point. Called via the bus_ops
8236 * bus_config entry point for all SCSA HBA drivers.
8238 * o If an HBA implements its own bus_config via tran_bus_config then we
8239 * invoke it. An HBA that implements its own tran_bus_config entry point
8240 * may still call back into common SCSA code bus_config code for:
8242 * o SPI bus_config (scsi_hba_bus_spi)
8243 * o LUN and secondary function enumeration (scsi_hba_enum_lsf_of_t()).
8244 * o configuration of a specific device (scsi_device_config).
8245 * o determining 1275 SCSI nodename and compatible property
8246 * (scsi_hba_nodename_compatible_get/_free).
8248 * o Otherwise we implement a SCSI parallel interface (spi) bus config.
8250 * Return NDI_SUCCESS if we might have created a new node.
8251 * Return NDI_FAILURE if we definitely did not create a new node.
8254 scsi_hba_bus_config(dev_info_t
*self
, uint_t flags
,
8255 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8257 scsi_hba_tran_t
*tran
;
8260 /* make sure that we will not disappear */
8261 ASSERT(DEVI(self
)->devi_ref
);
8263 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8265 /* NULL tran driver.conf config (used by cmdk). */
8266 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
8267 flags
|= NDI_CONFIG_REPROBE
;
8268 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
8271 /* Check if self is HBA-only node. */
8272 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8273 /* The bus_config request is to configure iports below HBA. */
8277 * Sparc's 'boot-device' OBP property value lacks an /iport@X/
8278 * component. Prior to the mount of root, we drive a disk@
8279 * BUS_CONFIG_ONE operatino down a level to resolve an
8280 * OBP 'boot-device' path.
8282 * Future: Add (modrootloaded == 0) below, and insure that
8283 * all attempts bus_conf of 'bo_name' (in OBP form) occur
8284 * prior to 'modrootloaded = 1;' assignment in vfs_mountroot.
8286 if ((op
== BUS_CONFIG_ONE
) &&
8287 (strncmp((char *)arg
, "disk@", strlen("disk@")) == 0)) {
8288 return (scsi_hba_bus_config_prom_node(self
,
8289 flags
, arg
, childp
));
8293 if (tran
->tran_iportmap
) {
8294 /* config based on scsi_hba_iportmap API */
8295 ret
= scsi_hba_bus_config_iportmap(self
,
8296 flags
, op
, arg
, childp
);
8298 /* config based on 'iport_register' API */
8299 ret
= scsi_hba_bus_config_iports(self
,
8300 flags
, op
, arg
, childp
);
8305 /* Check to see how the iport/HBA does target/lun bus config. */
8306 if (tran
->tran_bus_config
) {
8307 /* HBA config based on Sun-private/legacy tran_bus_config */
8308 ret
= tran
->tran_bus_config(self
, flags
, op
, arg
, childp
);
8309 } else if (tran
->tran_tgtmap
) {
8310 /* SCSAv3 config based on scsi_hba_tgtmap_*() API */
8311 ret
= scsi_hba_bus_config_tgtmap(self
, flags
, op
, arg
, childp
);
8313 /* SCSA config based on SCSI Parallel Interconnect */
8314 ret
= scsi_hba_bus_config_spi(self
, flags
, op
, arg
, childp
);
8320 * Called via the bus_ops bus_unconfig entry point for SCSI HBA drivers.
8323 scsi_hba_bus_unconfig(dev_info_t
*self
, uint_t flags
,
8324 ddi_bus_config_op_t op
, void *arg
)
8327 scsi_hba_tran_t
*tran
;
8330 tran
= ddi_get_driver_private(self
);
8332 /* NULL tran driver.conf unconfig (used by cmdk). */
8333 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8337 * Purge barrier/probe node children. We do this prior to
8338 * tran_bus_unconfig in case the unconfig implementation calls back
8339 * into the common code at a different enumeration level, such a
8340 * scsi_device_config, which still creates barrier/probe nodes.
8342 scsi_hba_devi_enter(self
, &circ
);
8343 scsi_hba_barrier_purge(self
);
8344 scsi_hba_devi_exit(self
, circ
);
8346 /* DEBUG: for testing, allow bus_unconfig do drive removal. */
8347 if (scsi_hba_bus_unconfig_remove
)
8348 flags
|= NDI_DEVI_REMOVE
;
8350 /* Check if self is HBA-only node. */
8351 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8352 /* The bus_config request is to unconfigure iports below HBA. */
8353 if (tran
->tran_iportmap
) {
8354 /* SCSAv3 unconfig based on scsi_hba_iportmap API */
8355 ret
= scsi_hba_bus_unconfig_iportmap(self
,
8357 } else if (tran
->tran_bus_unconfig
) {
8358 /* HBA unconfig based on Sun-private/legacy API */
8359 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8361 /* Standard framework unconfig. */
8362 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8367 /* Check to see how the iport/HBA does target/lun bus unconfig. */
8368 if (tran
->tran_bus_unconfig
) {
8369 /* HBA unconfig based on Sun-private/legacy tran_bus_unconfig */
8370 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8371 } else if (tran
->tran_tgtmap
) {
8372 /* SCSAv3 unconfig based on scsi_hba_tgtmap_*() API */
8373 ret
= scsi_hba_bus_unconfig_tgtmap(self
, flags
, op
, arg
);
8375 /* SCSA unconfig based on SCSI Parallel Interconnect */
8376 ret
= scsi_hba_bus_unconfig_spi(self
, flags
, op
, arg
);
8382 scsi_tgtmap_scsi_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8384 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8385 dev_info_t
*self
= tran
->tran_iport_dip
;
8386 impl_scsi_tgtmap_t
*tgtmap
;
8390 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8391 tgtaddr
= damap_id2addr(mapp
, tgtid
);
8393 if (scsi_lunmap_create(self
, tgtmap
, tgtaddr
) != DDI_SUCCESS
) {
8394 SCSI_HBA_LOG((_LOG_NF(WARN
),
8395 "failed to create lunmap for %s", tgtaddr
));
8398 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8399 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8401 mt
|= scsi_hba_log_mt_disable
;
8403 cfg_status
= scsi_hba_bus_config_taddr(self
, tgtaddr
, mt
, SE_HP
);
8404 if (cfg_status
!= NDI_SUCCESS
) {
8405 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s config status %d",
8406 damap_name(mapp
), tgtaddr
, cfg_status
));
8407 scsi_lunmap_destroy(self
, tgtmap
, tgtaddr
);
8408 return (DAM_FAILURE
);
8411 return (DAM_SUCCESS
);
8416 scsi_tgtmap_scsi_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8418 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8419 dev_info_t
*self
= tran
->tran_iport_dip
;
8420 impl_scsi_tgtmap_t
*tgtmap
;
8423 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8424 tgt_addr
= damap_id2addr(mapp
, tgtid
);
8426 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
),
8428 scsi_lunmap_destroy(self
, tgtmap
, tgt_addr
);
8429 return (DAM_SUCCESS
);
8433 scsi_tgtmap_smp_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8435 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8436 dev_info_t
*self
= tran
->tran_iport_dip
;
8439 addr
= damap_id2addr(mapp
, tgtid
);
8440 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8442 return ((smp_hba_bus_config_taddr(self
, addr
) == NDI_SUCCESS
) ?
8443 DAM_SUCCESS
: DAM_FAILURE
);
8447 scsi_tgtmap_smp_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8449 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8450 dev_info_t
*self
= tran
->tran_iport_dip
;
8453 char nameaddr
[SCSI_MAXNAMELEN
];
8456 addr
= damap_id2addr(mapp
, tgtid
);
8457 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8459 (void) snprintf(nameaddr
, sizeof (nameaddr
), "smp@%s", addr
);
8460 scsi_hba_devi_enter(self
, &circ
);
8461 if ((child
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
8462 scsi_hba_devi_exit(self
, circ
);
8463 return (DAM_SUCCESS
);
8466 if (ndi_devi_offline(child
,
8467 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
8468 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8469 "devinfo smp@%s offlined and removed", addr
));
8470 } else if (ndi_devi_device_remove(child
)) {
8471 /* Offline/remove failed, note new device_remove */
8472 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8473 "devinfo smp@%s offline failed, device_remove",
8476 scsi_hba_devi_exit(self
, circ
);
8477 return (DAM_SUCCESS
);
8482 scsi_tgtmap_smp_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8485 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8486 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8488 if (tgtmap
->tgtmap_activate_cb
) {
8489 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8490 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8493 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8494 tgt_addr
, SCSI_TGT_SMP_DEVICE
, tgt_privp
);
8500 scsi_tgtmap_smp_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8501 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8503 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8504 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8505 boolean_t tgtmap_rereport
;
8506 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8508 if (tgtmap
->tgtmap_deactivate_cb
) {
8509 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8510 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8511 tgt_addr
, damap_rsn
));
8513 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8514 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8515 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8516 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8517 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8518 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8520 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8521 "%s @%s deactivated with unknown rsn",
8522 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8527 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8528 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8529 SCSI_TGT_SMP_DEVICE
, tgt_privp
, tgtmap_rsn
);
8531 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8532 (tgtmap_rereport
== B_FALSE
)) {
8533 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8534 "%s enumeration failed, no more retries until "
8535 "config change occurs", tgt_addr
));
8542 scsi_tgtmap_scsi_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8545 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8546 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8548 if (tgtmap
->tgtmap_activate_cb
) {
8549 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8550 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8553 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8554 tgt_addr
, SCSI_TGT_SCSI_DEVICE
, tgt_privp
);
8560 scsi_tgtmap_scsi_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8561 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8563 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8564 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8565 boolean_t tgtmap_rereport
;
8566 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8568 if (tgtmap
->tgtmap_deactivate_cb
) {
8569 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8570 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8571 tgt_addr
, damap_rsn
));
8573 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8574 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8575 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8576 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8577 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8578 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8580 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8581 "%s @%s deactivated with unknown rsn", damap_name(
8582 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8587 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8588 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8589 SCSI_TGT_SCSI_DEVICE
, tgt_privp
, tgtmap_rsn
);
8591 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8592 (tgtmap_rereport
== B_FALSE
)) {
8593 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8594 "%s enumeration failed, no more retries until "
8595 "config change occurs", tgt_addr
));
8602 scsi_hba_tgtmap_create(dev_info_t
*self
, scsi_tgtmap_mode_t mode
,
8603 int csync_usec
, int settle_usec
, void *tgtmap_priv
,
8604 scsi_tgt_activate_cb_t activate_cb
, scsi_tgt_deactivate_cb_t deactivate_cb
,
8605 scsi_hba_tgtmap_t
**handle
)
8607 scsi_hba_tran_t
*tran
;
8610 impl_scsi_tgtmap_t
*tgtmap
;
8611 damap_rptmode_t rpt_style
;
8612 char *scsi_binding_set
;
8615 if (self
== NULL
|| csync_usec
== 0 ||
8616 settle_usec
== 0 || handle
== NULL
)
8617 return (DDI_FAILURE
);
8621 if (scsi_hba_iport_unit_address(self
) == NULL
)
8622 return (DDI_FAILURE
);
8625 case SCSI_TM_FULLSET
:
8626 rpt_style
= DAMAP_REPORT_FULLSET
;
8628 case SCSI_TM_PERADDR
:
8629 rpt_style
= DAMAP_REPORT_PERADDR
;
8632 return (DDI_FAILURE
);
8635 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
8638 return (DDI_FAILURE
);
8640 tgtmap
= kmem_zalloc(sizeof (*tgtmap
), KM_SLEEP
);
8641 tgtmap
->tgtmap_tran
= tran
;
8642 tgtmap
->tgtmap_activate_cb
= activate_cb
;
8643 tgtmap
->tgtmap_deactivate_cb
= deactivate_cb
;
8644 tgtmap
->tgtmap_mappriv
= tgtmap_priv
;
8646 tgtmap
->tgtmap_create_window
= 1; /* start with window */
8647 tgtmap
->tgtmap_create_time
= ddi_get_lbolt64();
8648 tgtmap
->tgtmap_create_csync_usec
= csync_usec
;
8649 tgtmap
->tgtmap_settle_usec
= settle_usec
;
8650 tgtmap
->tgtmap_sync_cnt
= 0;
8652 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8653 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8654 scsi_enumeration
) & SCSI_ENUMERATION_MT_TARGET_DISABLE
) ?
8655 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
8657 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.scsi",
8658 ddi_driver_name(self
), ddi_get_instance(self
));
8659 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8660 if (damap_create(context
, rpt_style
, optflags
, settle_usec
,
8661 tgtmap
, scsi_tgtmap_scsi_activate
, scsi_tgtmap_scsi_deactivate
,
8662 tran
, scsi_tgtmap_scsi_config
, scsi_tgtmap_scsi_unconfig
,
8663 &mapp
) != DAM_SUCCESS
) {
8664 kmem_free(tgtmap
, sizeof (*tgtmap
));
8665 return (DDI_FAILURE
);
8667 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
] = mapp
;
8669 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.smp",
8670 ddi_driver_name(self
), ddi_get_instance(self
));
8671 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8672 if (damap_create(context
, rpt_style
, optflags
,
8673 settle_usec
, tgtmap
, scsi_tgtmap_smp_activate
,
8674 scsi_tgtmap_smp_deactivate
,
8675 tran
, scsi_tgtmap_smp_config
, scsi_tgtmap_smp_unconfig
,
8676 &mapp
) != DAM_SUCCESS
) {
8677 damap_destroy(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8678 kmem_free(tgtmap
, sizeof (*tgtmap
));
8679 return (DDI_FAILURE
);
8681 tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
] = mapp
;
8683 tran
->tran_tgtmap
= (scsi_hba_tgtmap_t
*)tgtmap
;
8684 *handle
= (scsi_hba_tgtmap_t
*)tgtmap
;
8687 * We have now set tran_tgtmap, marking the tran as using tgtmap
8688 * enumeration services. To prevent the generation of legacy spi
8689 * 'binding-set' compatible forms, remove the 'scsi-binding-set'
8692 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
8693 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
8694 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
8695 if (strcmp(scsi_binding_set
, scsi_binding_set_spi
) == 0)
8696 (void) ndi_prop_remove(DDI_DEV_T_NONE
, self
,
8697 "scsi-binding-set");
8698 ddi_prop_free(scsi_binding_set
);
8700 return (DDI_SUCCESS
);
8704 scsi_hba_tgtmap_destroy(scsi_hba_tgtmap_t
*handle
)
8706 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8707 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8710 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8711 if (tgtmap
->tgtmap_dam
[i
]) {
8712 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8713 "%s", damap_name(tgtmap
->tgtmap_dam
[i
])));
8714 damap_destroy(tgtmap
->tgtmap_dam
[i
]);
8717 kmem_free(tgtmap
, sizeof (*tgtmap
));
8720 /* return 1 if all maps ended up syned */
8722 scsi_tgtmap_sync(scsi_hba_tgtmap_t
*handle
, int sync_usec
)
8724 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8725 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8730 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8731 if (tgtmap
->tgtmap_dam
[i
]) {
8732 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync begin",
8733 damap_name(tgtmap
->tgtmap_dam
[i
])));
8734 synced
= damap_sync(tgtmap
->tgtmap_dam
[i
], sync_usec
);
8735 all_synced
&= synced
;
8736 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync end %d",
8737 damap_name(tgtmap
->tgtmap_dam
[i
]), synced
));
8741 return (all_synced
);
8744 /* return 1 if all maps ended up empty */
8746 scsi_tgtmap_is_empty(scsi_hba_tgtmap_t
*handle
)
8748 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8749 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8754 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8755 if (tgtmap
->tgtmap_dam
[i
]) {
8756 empty
= damap_is_empty(tgtmap
->tgtmap_dam
[i
]);
8758 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s is_empty %d",
8759 damap_name(tgtmap
->tgtmap_dam
[i
]), empty
));
8767 scsi_tgtmap_beginf(scsi_hba_tgtmap_t
*handle
, boolean_t do_begin
)
8769 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8770 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8772 int rv
= DAM_SUCCESS
;
8775 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8776 if (tgtmap
->tgtmap_dam
[i
] == NULL
) {
8780 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8781 if (do_begin
== B_TRUE
) {
8782 if (i
== SCSI_TGT_SCSI_DEVICE
) {
8784 * In scsi_device context, so we have the
8785 * 'context' string, diagnose the case where
8786 * the tgtmap caller is failing to make
8787 * forward progress, i.e. the caller is never
8788 * completing an observation by calling
8789 * scsi_hbg_tgtmap_set_end. If this occurs,
8790 * the solaris target/lun state may be out
8791 * of sync with hardware.
8793 if (tgtmap
->tgtmap_reports
++ >=
8794 scsi_hba_tgtmap_reports_max
) {
8795 tgtmap
->tgtmap_noisy
++;
8796 if (tgtmap
->tgtmap_noisy
== 1) {
8797 SCSI_HBA_LOG((_LOG(WARN
),
8799 "%s: failing tgtmap begin",
8805 rv
= damap_addrset_begin(tgtmap
->tgtmap_dam
[i
]);
8807 rv
= damap_addrset_flush(tgtmap
->tgtmap_dam
[i
]);
8810 if (rv
!= DAM_SUCCESS
) {
8811 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8813 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8817 return ((rv
== DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8822 scsi_hba_tgtmap_set_begin(scsi_hba_tgtmap_t
*handle
)
8824 return (scsi_tgtmap_beginf(handle
, B_TRUE
));
8828 scsi_hba_tgtmap_set_flush(scsi_hba_tgtmap_t
*handle
)
8830 return (scsi_tgtmap_beginf(handle
, B_FALSE
));
8834 scsi_hba_tgtmap_set_add(scsi_hba_tgtmap_t
*handle
,
8835 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8837 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8838 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8840 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8841 return (DDI_FAILURE
);
8843 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8844 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8846 return ((damap_addrset_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
,
8847 NULL
, NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8852 scsi_hba_tgtmap_set_end(scsi_hba_tgtmap_t
*handle
, uint_t flags
)
8854 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8855 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8857 int rv
= DDI_SUCCESS
;
8860 tgtmap
->tgtmap_reports
= tgtmap
->tgtmap_noisy
= 0;
8862 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8863 if (tgtmap
->tgtmap_dam
[i
] == NULL
)
8865 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8866 if (damap_addrset_end(
8867 tgtmap
->tgtmap_dam
[i
], 0) != DAM_SUCCESS
) {
8868 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8873 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8879 scsi_hba_tgtmap_tgt_add(scsi_hba_tgtmap_t
*handle
,
8880 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8882 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8883 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8885 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8886 return (DDI_FAILURE
);
8888 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8889 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8891 return ((damap_addr_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
, NULL
,
8892 NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8896 scsi_hba_tgtmap_tgt_remove(scsi_hba_tgtmap_t
*handle
,
8897 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
)
8899 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8900 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8902 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8903 return (DDI_FAILURE
);
8905 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8906 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8908 return ((damap_addr_del(tgtmap
->tgtmap_dam
[tgt_type
],
8909 tgt_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8913 scsi_hba_tgtmap_lookup(scsi_hba_tgtmap_t
*handle
,
8914 char *tgt_addr
, scsi_tgtmap_tgt_type_t
*r_type
)
8916 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8917 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8921 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8922 tgtid
= damap_lookup(tgtmap
->tgtmap_dam
[i
], tgt_addr
);
8923 if (tgtid
!= NODAM
) {
8925 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8926 "%s @%s found: type %d",
8927 damap_name(tgtmap
->tgtmap_dam
[i
]), tgt_addr
, i
));
8928 damap_id_rele(tgtmap
->tgtmap_dam
[i
], tgtid
);
8929 return (DDI_SUCCESS
);
8933 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8934 "%s%d.tgtmap @%s not found",
8935 ddi_driver_name(self
), ddi_get_instance(self
), tgt_addr
));
8936 return (DDI_FAILURE
);
8940 * Return the unit-address of an 'iport' node, or NULL for non-iport node.
8943 scsi_hba_iport_unit_address(dev_info_t
*self
)
8946 * NOTE: Since 'self' could be a SCSA iport node or a SCSA HBA node,
8947 * we can't use SCSA flavors: the flavor of a SCSA HBA node is not
8948 * established/owned by SCSA, it is established by the nexus that
8949 * created the SCSA HBA node (PCI) as a child.
8951 * NOTE: If we want to support a node_name other than "iport" for
8952 * an iport node then we can add support for a "scsa-iport-node-name"
8953 * property on the SCSA HBA node. A SCSA HBA driver would set this
8954 * property on the SCSA HBA node prior to using the iport API.
8956 if (strcmp(ddi_node_name(self
), "iport") == 0)
8957 return (ddi_get_name_addr(self
));
8963 * Define a SCSI initiator port (bus/channel) for an HBA card that needs to
8964 * support multiple SCSI ports, but only has a single HBA devinfo node. This
8965 * function should be called from the HBA's attach(9E) implementation (when
8966 * processing the HBA devinfo node attach) after the number of SCSI ports on
8967 * the card is known or when the HBA driver DR handler detects a new port.
8968 * The function returns 0 on failure and 1 on success.
8970 * The implementation will add the port value into the "scsi-iports" property
8971 * value maintained on the HBA node as. These properties are used by the generic
8972 * scsi bus_config implementation to dynamicaly enumerate the specified iport
8973 * children. The enumeration code will, on demand, create the appropriate
8974 * iport children with a SCSI_ADDR_PROP_IPORTUA unit address. This node will
8975 * bind to the same driver as the HBA node itself. This means that an HBA
8976 * driver that uses iports should expect probe(9E), attach(9E), and detach(9E)
8977 * calls on the iport children of the HBA. If configuration for all ports was
8978 * already done during HBA node attach, the driver should just return
8979 * DDI_SUCCESS when confronted with an iport node.
8981 * A maximum of 32 iport ports are supported per HBA devinfo node.
8983 * A NULL "port" can be used to indicate that the framework should enumerate
8984 * target children on the HBA node itself, in addition to enumerating target
8985 * children on any iport nodes declared. There are two reasons that an HBA may
8986 * wish to have target children enumerated on both the HBA node and iport
8989 * o If, in the past, HBA hardware had only a single physical port but now
8990 * supports multiple physical ports, the updated driver that supports
8991 * multiple physical ports may want to avoid /devices path upgrade issues
8992 * by enumerating the first physical port under the HBA instead of as a
8995 * o Some hardware RAID HBA controllers (mlx, chs, etc) support multiple
8996 * SCSI physical ports configured so that various physical devices on
8997 * the physical ports are amalgamated into virtual devices on a virtual
8998 * port. Amalgamated physical devices no longer appear to the host OS
8999 * on the physical ports, but other non-amalgamated devices may still be
9000 * visible on the physical ports. These drivers use a model where the
9001 * physical ports are iport nodes and the HBA node is the virtual port to
9002 * the configured virtual devices.
9005 scsi_hba_iport_register(dev_info_t
*self
, char *port
)
9007 unsigned int ports
= 0;
9009 char **iports
, **newiports
;
9013 return (DDI_FAILURE
);
9015 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9016 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9019 if (ports
>= SCSI_HBA_MAX_IPORTS
) {
9020 ddi_prop_free(iports
);
9021 return (DDI_FAILURE
);
9024 if (rval
== DDI_PROP_SUCCESS
) {
9025 for (i
= 0; i
< ports
; i
++) {
9026 if (strcmp(port
, iports
[i
]) == 0) {
9027 /* iport already registered */
9028 ddi_prop_free(iports
);
9029 return (DDI_SUCCESS
);
9034 newiports
= kmem_alloc((sizeof (char *) * (ports
+ 1)), KM_SLEEP
);
9036 for (i
= 0; i
< ports
; i
++) {
9037 newiports
[i
] = strdup(iports
[i
]);
9039 newiports
[ports
] = strdup(port
);
9042 if (ddi_prop_update_string_array(DDI_DEV_T_NONE
, self
,
9043 "scsi-iports", newiports
, ports
) != DDI_PROP_SUCCESS
) {
9044 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
9045 "failed to establish %s %s",
9046 SCSI_ADDR_PROP_IPORTUA
, port
));
9052 /* If there is iport exist, free property */
9054 ddi_prop_free(iports
);
9055 for (i
= 0; i
< ports
; i
++) {
9056 strfree(newiports
[i
]);
9058 kmem_free(newiports
, (sizeof (char *)) * ports
);
9064 * Check if the HBA has any scsi_hba_iport_register()ed children.
9067 scsi_hba_iport_exist(dev_info_t
*self
)
9069 unsigned int ports
= 0;
9073 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9074 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9077 if (rval
!= DDI_PROP_SUCCESS
)
9080 /* If there is now at least 1 iport, then iports is valid */
9085 ddi_prop_free(iports
);
9091 scsi_hba_iport_find(dev_info_t
*self
, char *portnm
)
9095 unsigned int num_iports
= 0;
9096 int rval
= DDI_FAILURE
;
9098 dev_info_t
*child
= NULL
;
9100 /* check to see if this is an HBA that defined scsi iports */
9101 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9102 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9105 if (rval
!= DDI_SUCCESS
) {
9108 ASSERT(num_iports
> 0);
9110 /* check to see if this port was registered */
9111 for (i
= 0; i
< num_iports
; i
++) {
9112 if (strcmp(iports
[i
], portnm
) == 0)
9116 if (i
== num_iports
) {
9121 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9122 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s", portnm
);
9123 rval
= ndi_devi_config_one(self
, addr
, &child
, NDI_NO_EVENT
);
9124 kmem_free(addr
, SCSI_MAXNAMELEN
);
9126 if (rval
!= DDI_SUCCESS
) {
9130 ddi_prop_free(iports
);
9135 * Search/create the specified iport node
9138 scsi_hba_bus_config_port(dev_info_t
*self
, char *nameaddr
, scsi_enum_t se
)
9140 dev_info_t
*child
; /* iport child of HBA node */
9141 scsi_hba_tran_t
*tran
;
9146 * See if the iport node already exists.
9148 addr
= nameaddr
+ strlen("iport@");
9149 if (child
= ndi_devi_findchild(self
, nameaddr
)) {
9150 if (ndi_devi_device_isremoved(child
)) {
9151 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
9152 if (ndi_devi_device_insert(child
))
9153 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
9154 "devinfo iport@%s device_reinsert",
9164 * If config based on scsi_hba_iportmap API, only allow create
9167 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
9169 if (tran
->tran_iportmap
&& (se
!= SE_HP
))
9172 /* allocate and initialize a new "iport" node */
9173 ndi_devi_alloc_sleep(self
, "iport",
9174 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
9178 * Set the flavor of the child to be IPORT flavored
9180 ndi_flavor_set(child
, SCSA_FLAVOR_IPORT
);
9183 * Add the SCSI_ADDR_PROP_IPORTUA addressing property for this child.
9184 * This property is used to identify a iport node, and to represent the
9185 * nodes @addr form via node properties.
9187 * Add "compatible" property to the "scsi-iport" node to cause it bind
9188 * to the same driver as the HBA driver. Use the "driver" name
9189 * instead of the "binding name" to distinguish from hw node.
9191 * Give the HBA a chance, via tran_set_name_prop, to set additional
9192 * iport node properties or to change the "compatible" binding
9193 * prior to init_child.
9195 * NOTE: the order of these operations is important so that
9196 * scsi_hba_iport works when called.
9198 compat
= (char *)ddi_driver_name(self
);
9199 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
9200 SCSI_ADDR_PROP_IPORTUA
, addr
) != DDI_PROP_SUCCESS
) ||
9201 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, child
,
9202 "compatible", &compat
, 1) != DDI_PROP_SUCCESS
) ||
9203 ddi_pathname_obp_set(child
, NULL
) != DDI_SUCCESS
) {
9204 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s failed dynamic decoration",
9206 (void) ddi_remove_child(child
, 0);
9210 * Online/attach in order to get events so devfsadm will
9211 * create public names.
9213 ndi_hold_devi(child
);
9214 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
9215 ndi_rele_devi(child
);
9216 ndi_prop_remove_all(child
);
9217 (void) ndi_devi_free(child
);
9220 ndi_rele_devi(child
);
9228 * Future: When iportmap boot support is added, consider rewriting this to
9229 * perform a scsi_hba_bus_config(BUS_CONFIG_ALL) on self (HBA) followed by
9230 * a scsi_hba_bus_config(BUS_CONFIG_ONE) on each child of self (each iport).
9234 scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
9235 void *arg
, dev_info_t
**childp
)
9239 int ret
= NDI_FAILURE
;
9240 unsigned int num_iports
= 0;
9241 dev_info_t
*pdip
= NULL
;
9244 /* check to see if this is an HBA that defined scsi iports */
9245 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9246 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9249 if (ret
!= DDI_SUCCESS
) {
9253 ASSERT(num_iports
> 0);
9255 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9259 scsi_hba_devi_enter(self
, &circ
);
9261 /* create iport nodes for each scsi port/bus */
9262 for (i
= 0; i
< num_iports
; i
++) {
9263 bzero(addr
, SCSI_MAXNAMELEN
);
9264 /* Prepend the iport name */
9265 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9267 if (pdip
= scsi_hba_bus_config_port(self
, addr
, SE_BUSCONFIG
)) {
9268 if (ndi_busop_bus_config(self
, NDI_NO_EVENT
,
9269 BUS_CONFIG_ONE
, addr
, &pdip
, 0) !=
9274 * Try to configure child under iport see wehter
9275 * request node is the child of the iport node
9277 if (ndi_devi_config_one(pdip
, arg
, childp
,
9278 NDI_NO_EVENT
) == NDI_SUCCESS
) {
9285 scsi_hba_devi_exit(self
, circ
);
9287 kmem_free(addr
, SCSI_MAXNAMELEN
);
9289 ddi_prop_free(iports
);
9296 * Perform iport port/bus bus_config.
9299 scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
9300 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
9302 char *nameaddr
, *addr
;
9305 int ret
= NDI_FAILURE
;
9306 unsigned int num_iports
= 0;
9308 /* check to see if this is an HBA that defined scsi iports */
9309 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9310 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9313 if (ret
!= DDI_SUCCESS
) {
9317 ASSERT(num_iports
> 0);
9319 scsi_hba_devi_enter(self
, &circ
);
9322 case BUS_CONFIG_ONE
:
9323 /* return if this operation is not against an iport node */
9324 nameaddr
= (char *)arg
;
9325 if ((nameaddr
== NULL
) ||
9326 (strncmp(nameaddr
, "iport@", strlen("iport@")) != 0)) {
9328 scsi_hba_devi_exit(self
, circ
);
9329 ddi_prop_free(iports
);
9333 /* parse the port number from "iport@%s" */
9334 addr
= nameaddr
+ strlen("iport@");
9336 /* check to see if this port was registered */
9337 for (i
= 0; i
< num_iports
; i
++) {
9338 if (strcmp((iports
[i
]), addr
) == 0)
9342 if (i
== num_iports
) {
9347 /* create the iport node child */
9348 if (scsi_hba_bus_config_port(self
, nameaddr
, SE_BUSCONFIG
)) {
9353 case BUS_CONFIG_ALL
:
9354 case BUS_CONFIG_DRIVER
:
9355 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9356 /* create iport nodes for each scsi port/bus */
9357 for (i
= 0; i
< num_iports
; i
++) {
9358 bzero(addr
, SCSI_MAXNAMELEN
);
9359 /* Prepend the iport name */
9360 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9362 (void) scsi_hba_bus_config_port(self
, addr
,
9366 kmem_free(addr
, SCSI_MAXNAMELEN
);
9370 if (ret
== NDI_SUCCESS
) {
9373 * Mask NDI_PROMNAME since PROM doesn't have iport
9376 flags
&= (~NDI_PROMNAME
);
9378 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
9379 ret
= ndi_busop_bus_config(self
, flags
, op
,
9382 scsi_hba_devi_exit(self
, circ
);
9384 ddi_prop_free(iports
);
9390 scsi_iportmap_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9392 dev_info_t
*self
= (dev_info_t
*)arg
;
9394 char nameaddr
[SCSI_MAXNAMELEN
];
9398 scsi_hba_devi_enter(self
, &circ
);
9400 iport_addr
= damap_id2addr(mapp
, tgtid
);
9401 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9402 "%s @%s", damap_name(mapp
), iport_addr
));
9404 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", iport_addr
);
9405 childp
= scsi_hba_bus_config_port(self
, nameaddr
, SE_HP
);
9406 scsi_hba_devi_exit(self
, circ
);
9407 return (childp
!= NULL
? DAM_SUCCESS
: DAM_FAILURE
);
9411 scsi_iportmap_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9413 dev_info_t
*self
= arg
;
9414 dev_info_t
*childp
; /* iport child of HBA node */
9417 char nameaddr
[SCSI_MAXNAMELEN
];
9418 scsi_hba_tran_t
*tran
;
9420 addr
= damap_id2addr(mapp
, tgtid
);
9421 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
9423 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", addr
);
9424 scsi_hba_devi_enter(self
, &circ
);
9425 if ((childp
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
9426 scsi_hba_devi_exit(self
, circ
);
9427 return (DAM_FAILURE
);
9430 tran
= ddi_get_driver_private(childp
);
9433 ndi_hold_devi(childp
);
9434 scsi_hba_devi_exit(self
, circ
);
9437 * A begin/end (clear) against the iport's
9438 * tgtmap will trigger unconfigure of all
9439 * targets on the iport.
9441 * Future: This bit of code only works if the
9442 * target map reporting style is are full
9443 * reports and not per-address. Maybe we
9444 * should plan on handling this by
9445 * auto-unconfiguration when destroying the
9448 (void) scsi_hba_tgtmap_set_begin(tran
->tran_tgtmap
);
9449 (void) scsi_hba_tgtmap_set_end(tran
->tran_tgtmap
, 0);
9451 /* wait for unconfigure */
9452 (void) scsi_tgtmap_sync(tran
->tran_tgtmap
, 0);
9453 empty
= scsi_tgtmap_is_empty(tran
->tran_tgtmap
);
9455 scsi_hba_devi_enter(self
, &circ
);
9456 ndi_rele_devi(childp
);
9458 /* If begin/end/sync ends in empty map, offline/remove. */
9460 if (ndi_devi_offline(childp
,
9461 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
9462 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9463 "devinfo iport@%s offlined and removed",
9465 } else if (ndi_devi_device_remove(childp
)) {
9466 /* Offline/rem failed, note new device_remove */
9467 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9468 "devinfo iport@%s offline failed, "
9469 "device_remove", addr
));
9472 scsi_hba_devi_exit(self
, circ
);
9473 return (empty
? DAM_SUCCESS
: DAM_FAILURE
);
9478 scsi_hba_iportmap_create(dev_info_t
*self
, int csync_usec
, int settle_usec
,
9479 scsi_hba_iportmap_t
**handle
)
9481 scsi_hba_tran_t
*tran
;
9484 impl_scsi_iportmap_t
*iportmap
;
9486 if (self
== NULL
|| csync_usec
== 0 ||
9487 settle_usec
== 0 || handle
== NULL
)
9488 return (DDI_FAILURE
);
9492 if (scsi_hba_iport_unit_address(self
) != NULL
)
9493 return (DDI_FAILURE
);
9495 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
9498 return (DDI_FAILURE
);
9500 (void) snprintf(context
, sizeof (context
), "%s%d.iportmap",
9501 ddi_driver_name(self
), ddi_get_instance(self
));
9503 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
9504 settle_usec
, NULL
, NULL
, NULL
, self
,
9505 scsi_iportmap_config
, scsi_iportmap_unconfig
, &mapp
) !=
9507 return (DDI_FAILURE
);
9509 iportmap
= kmem_zalloc(sizeof (*iportmap
), KM_SLEEP
);
9510 iportmap
->iportmap_hba_dip
= self
;
9511 iportmap
->iportmap_dam
= mapp
;
9513 iportmap
->iportmap_create_window
= 1; /* start with window */
9514 iportmap
->iportmap_create_time
= ddi_get_lbolt64();
9515 iportmap
->iportmap_create_csync_usec
= csync_usec
;
9516 iportmap
->iportmap_settle_usec
= settle_usec
;
9517 iportmap
->iportmap_sync_cnt
= 0;
9519 tran
->tran_iportmap
= (scsi_hba_iportmap_t
*)iportmap
;
9520 *handle
= (scsi_hba_iportmap_t
*)iportmap
;
9522 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s", damap_name(mapp
)));
9523 return (DDI_SUCCESS
);
9527 scsi_hba_iportmap_destroy(scsi_hba_iportmap_t
*handle
)
9529 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9530 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9532 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9533 "%s", damap_name(iportmap
->iportmap_dam
)));
9535 damap_destroy(iportmap
->iportmap_dam
);
9536 kmem_free(iportmap
, sizeof (*iportmap
));
9540 scsi_hba_iportmap_iport_add(scsi_hba_iportmap_t
*handle
,
9541 char *iport_addr
, void *iport_priv
)
9543 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9544 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9546 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9547 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9549 return ((damap_addr_add(iportmap
->iportmap_dam
, iport_addr
, NULL
,
9550 NULL
, iport_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9554 scsi_hba_iportmap_iport_remove(scsi_hba_iportmap_t
*handle
,
9557 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9558 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9560 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9561 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9563 return ((damap_addr_del(iportmap
->iportmap_dam
,
9564 iport_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9568 scsi_hba_iportmap_lookup(scsi_hba_iportmap_t
*handle
,
9571 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9572 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9575 iportid
= damap_lookup(iportmap
->iportmap_dam
, iport_addr
);
9576 if (iportid
!= NODAM
) {
9577 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9579 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9580 damap_id_rele(iportmap
->iportmap_dam
, iportid
);
9581 return (DDI_SUCCESS
);
9584 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9586 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9587 return (DDI_FAILURE
);
9592 scsi_lunmap_config(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9594 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9595 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9596 dev_info_t
*self
= tran
->tran_iport_dip
;
9599 addr
= damap_id2addr(lundam
, lunid
);
9600 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9601 "%s @%s", damap_name(lundam
), addr
));
9602 if (scsi_hba_bus_configone_addr(self
, addr
, SE_HP
) != NULL
)
9603 return (DAM_SUCCESS
);
9605 return (DAM_FAILURE
);
9609 scsi_lunmap_unconfig(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9611 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9612 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9613 dev_info_t
*self
= tran
->tran_iport_dip
;
9616 addr
= damap_id2addr(lundam
, lunid
);
9617 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
),
9620 scsi_hba_bus_unconfigone_addr(self
, addr
);
9621 return (DAM_SUCCESS
);
9625 scsi_lunmap_create(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9633 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9634 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9636 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9637 tgtid
= damap_lookup(tgtdam
, taddr
);
9638 if (tgtid
== NODAM
) {
9639 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9640 "target %s not found", context
));
9641 return (DDI_FAILURE
);
9644 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
9646 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9647 "lunmap %s already created", context
));
9648 damap_id_rele(tgtdam
, tgtid
);
9649 return (DDI_FAILURE
);
9652 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
9653 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
9654 scsi_enumeration
) & SCSI_ENUMERATION_MT_LUN_DISABLE
) ?
9655 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
9657 /* NOTE: expected ref at tgtid/taddr: 2: caller + lookup. */
9658 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 2);
9659 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s creat, id %d ref %d",
9660 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9663 if (damap_create(context
, DAMAP_REPORT_FULLSET
, optflags
, 1,
9664 NULL
, NULL
, NULL
, tgtmap
, scsi_lunmap_config
, scsi_lunmap_unconfig
,
9665 &lundam
) != DAM_SUCCESS
) {
9666 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9667 "%s create failed, id %d ref %d",
9668 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9669 damap_id_rele(tgtdam
, tgtid
);
9670 return (DDI_FAILURE
);
9674 * Return with damap_id_hold at tgtid/taddr from damap_lookup to
9675 * account for damap_id_prv_set below.
9677 damap_id_priv_set(tgtdam
, tgtid
, lundam
);
9678 return (DDI_SUCCESS
);
9682 scsi_lunmap_destroy(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9689 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9690 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9692 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9693 tgtid
= damap_lookup(tgtdam
, taddr
);
9694 if (tgtid
== NODAM
) {
9695 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9696 "target %s not found", context
));
9700 lundam
= (damap_t
*)damap_id_priv_get(tgtdam
, tgtid
);
9701 if (lundam
== NULL
) {
9702 damap_id_rele(tgtdam
, tgtid
); /* from damap_lookup */
9703 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9704 "lunmap %s already destroyed", context
));
9708 /* NOTE: expected ref at tgtid/taddr: 3: priv_set + caller + lookup. */
9709 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 3);
9710 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s, id %d ref %d",
9711 damap_name(lundam
), tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9714 * A begin/end (clear) against a target's lunmap will trigger
9715 * unconfigure of all LUNs on the target.
9717 scsi_lunmap_set_begin(self
, lundam
);
9718 scsi_lunmap_set_end(self
, lundam
);
9720 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9721 "%s sync begin", damap_name(lundam
)));
9723 (void) damap_sync(lundam
, 0); /* wait for unconfigure */
9725 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9726 "%s sync end", damap_name(lundam
)));
9728 damap_id_priv_set(tgtdam
, tgtid
, NULL
);
9730 /* release hold established by damap_lookup above */
9731 damap_id_rele(tgtdam
, tgtid
);
9733 /* release hold established since scsi_lunmap_create() */
9734 damap_id_rele(tgtdam
, tgtid
);
9736 damap_destroy(lundam
);
9740 scsi_lunmap_set_begin(dev_info_t
*self
, damap_t
*lundam
)
9742 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9744 (void) damap_addrset_begin(lundam
);
9748 scsi_lunmap_set_add(dev_info_t
*self
, damap_t
*lundam
,
9749 char *taddr
, scsi_lun64_t lun64
, int sfunc
)
9751 char ua
[SCSI_MAXNAMELEN
];
9753 /* make unit address string form of "@taddr,lun[,sfunc]" */
9755 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
, taddr
, lun64
);
9757 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
",%x",
9758 taddr
, lun64
, sfunc
);
9760 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
), ua
));
9762 return ((damap_addrset_add(lundam
, ua
, NULL
, NULL
,
9763 NULL
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9767 scsi_lunmap_set_end(dev_info_t
*self
, damap_t
*lundam
)
9769 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9771 (void) damap_addrset_end(lundam
, 0);
9775 scsi_lunmap_lookup(dev_info_t
*self
, damap_t
*lundam
, char *addr
)
9779 if ((lunid
= damap_lookup(lundam
, addr
)) != NODAM
) {
9780 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9781 "%s @%s found", damap_name(lundam
), addr
));
9782 damap_id_rele(lundam
, lunid
);
9783 return (DDI_SUCCESS
);
9786 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9787 "%s @%s not found", damap_name(lundam
), addr
));
9788 return (DDI_FAILURE
);
9792 * phymap implementation
9794 * We manage the timed aggregation of phys into a phy map * by creating a
9795 * SAS port construct (based upon 'name' of "local,remote" SAS addresses)
9796 * upon the first link up. As time goes on additional phys may join that port.
9797 * After an appropriate amount of settle time, we trigger the activation
9798 * callback which will then take the resultant bit mask of phys (phymask) in
9799 * the SAS port and use that to call back to the callback function
9800 * provided by the additional caller.
9802 * We cross check to make sure that phys only exist in one SAS port at a
9803 * time by having soft state for each phy point back to the created
9806 * NOTE: Make SAS_PHY_UA_LEN max(SAS_PHY_PHYMASK_LEN, SAS_PHY_NAME_LEN)
9807 * so we have enough space if sas_phymap_bitset2phymaskua phymask address
9808 * is already in use, and we end up using port name as unit address.
9810 #define SAS_PHY_NAME_FMT "%" PRIx64 ",%" PRIx64
9811 #define SAS_PHY_NAME_LEN (16 + 1 + 16 + 1)
9812 #define SAS_PHY_NPHY (SAS2_PHYNUM_MAX + 1)
9813 #define SAS_PHY_PHYMASK_LEN ((roundup(SAS_PHY_NPHY, 4)) / 4)
9814 #if (SAS_PHY_PHYMASK_LEN > SAS_PHY_NAME_LEN)
9815 #define SAS_PHY_UA_LEN SAS_PHY_PHYMASK_LEN
9817 #define SAS_PHY_UA_LEN SAS_PHY_NAME_LEN
9819 typedef struct impl_sas_physet
{ /* needed for name2phys destroy */
9820 struct impl_sas_physet
*physet_next
;
9822 bitset_t
*physet_phys
;
9823 } impl_sas_physet_t
;
9824 typedef struct impl_sas_phymap
{
9825 dev_info_t
*phymap_self
;
9827 kmutex_t phymap_lock
;
9828 damap_t
*phymap_dam
;
9829 void *phymap_phy2name
;
9830 ddi_soft_state_bystr
*phymap_name2phys
; /* bitset */
9831 ddi_soft_state_bystr
*phymap_name2ua
;
9832 ddi_soft_state_bystr
*phymap_ua2name
;
9834 /* Noisy phy information - ensure forward progress for noisy phys */
9835 int phymap_phy_max
; /* max phy# */
9836 int phymap_reports
; /* per period */
9837 int phymap_reports_max
; /* scales */
9838 int phymap_phys_noisy
; /* detected */
9840 /* These are for callbacks to the consumer. */
9841 sas_phymap_activate_cb_t phymap_acp
;
9842 sas_phymap_deactivate_cb_t phymap_dcp
;
9843 void *phymap_private
;
9845 struct impl_sas_physet
*phymap_physets
;
9846 } impl_sas_phymap_t
;
9848 /* Detect noisy phy: max changes per stabilization period per phy. */
9849 static int sas_phymap_phy_max_factor
= 16;
9852 * Convert bitset into a unit-address string. The maximum string length would
9853 * be the maximum number of phys, rounded up by 4 and divided by 4.
9856 sas_phymap_bitset2phymaskua(bitset_t
*phys
, char *buf
)
9863 bit
= roundup(SAS_PHY_NPHY
, 4);
9870 if (bitset_in_set(phys
, bit
)) {
9875 if (cur
|| ptr
!= buf
) {
9876 *ptr
++ = "0123456789abcdef"[cur
];
9889 sas_phymap_config(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
9891 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
9892 char *context
= damap_name(phymap
->phymap_dam
);
9901 mutex_enter(&phymap
->phymap_lock
);
9902 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
9904 /* Get the name ("local,remote" address string) from damap. */
9905 damn
= damap_id2addr(phydam
, phyid
);
9907 /* Get the bitset of phys currently forming the port. */
9908 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, damn
);
9910 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: no phys",
9912 mutex_exit(&phymap
->phymap_lock
);
9913 return (DAM_FAILURE
);
9916 /* allocate, get, and initialize name index of name2ua map */
9917 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2ua
, damn
) !=
9919 SCSI_HBA_LOG((_LOG_NF(WARN
),
9920 "%s: %s: failed name2ua alloc", context
, damn
));
9921 mutex_exit(&phymap
->phymap_lock
);
9922 return (DAM_FAILURE
);
9924 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
9925 SCSI_HBA_LOG((_LOG_NF(WARN
),
9926 "%s: %s: no name2ua", context
, damn
));
9927 mutex_exit(&phymap
->phymap_lock
);
9928 return (DAM_FAILURE
);
9930 sas_phymap_bitset2phymaskua(phys
, ua
); /* set ua */
9932 /* see if phymask ua index already allocated in ua2name map */
9933 if (name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
)) {
9935 * The 'phymask' sas_phymap_bitset2phymaskua ua is
9936 * already in use. This means that original phys have
9937 * formed into a new port, and that the original port
9938 * still exists (it has migrated to some completely
9939 * different set of phys). In this corner-case we use
9940 * "local,remote" name as a 'temporary' unit address.
9941 * Reset ua in name2ua map.
9943 (void) strlcpy(ua
, damn
, SAS_PHY_NAME_LEN
);
9944 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9946 /* The "local,remote" ua should be new... */
9947 SCSI_HBA_LOG((_LOG_NF(WARN
),
9948 "%s: %s ua already configured",
9950 mutex_exit(&phymap
->phymap_lock
);
9951 return (DAM_SUCCESS
);
9955 /* allocate, get, and init ua index of ua2name map */
9956 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_ua2name
, ua
) !=
9958 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9959 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: failed ua2name alloc",
9961 mutex_exit(&phymap
->phymap_lock
);
9962 return (DAM_FAILURE
);
9964 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9966 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9967 SCSI_HBA_LOG((_LOG_NF(WARN
),
9968 "%s: %s: no ua2name", context
, ua
));
9969 mutex_exit(&phymap
->phymap_lock
);
9970 return (DAM_FAILURE
);
9973 /* set name in ua2name map */
9974 (void) strlcpy(name
, damn
, SAS_PHY_NAME_LEN
);
9976 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
9977 "%s: %s: ua %s: activate", context
, damn
, ua
));
9979 if (phymap
->phymap_acp
) {
9981 * drop our lock and invoke the activation callback
9983 mutex_exit(&phymap
->phymap_lock
);
9985 (phymap
->phymap_acp
)(phymap
->phymap_private
, ua
, &ua_priv
);
9986 mutex_enter(&phymap
->phymap_lock
);
9987 damap_id_priv_set(phydam
, phyid
, ua_priv
);
9989 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
9990 "%s: %s: ua %s: activate complete", context
, damn
, ua
));
9991 mutex_exit(&phymap
->phymap_lock
);
9992 return (DAM_SUCCESS
);
9997 sas_phymap_unconfig(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
9999 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
10000 char *context
= damap_name(phymap
->phymap_dam
);
10007 mutex_enter(&phymap
->phymap_lock
);
10008 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
10010 /* Get the name ("local,remote" address string) from damap. */
10011 damn
= damap_id2addr(phydam
, phyid
);
10013 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
10014 SCSI_HBA_LOG((_LOG_NF(WARN
),
10015 "%s: %s: no name2ua", context
, damn
));
10016 mutex_exit(&phymap
->phymap_lock
);
10017 return (DAM_FAILURE
);
10020 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10021 "%s: %s: ua %s: deactivate", context
, damn
, ua
));
10022 if (phymap
->phymap_dcp
) {
10023 ua_priv
= damap_id_priv_get(phydam
, phyid
);
10024 mutex_exit(&phymap
->phymap_lock
);
10025 (phymap
->phymap_dcp
)(phymap
->phymap_private
, ua
, ua_priv
);
10026 mutex_enter(&phymap
->phymap_lock
);
10028 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10029 "%s: %s: ua %s: deactivate complete", context
, damn
, ua
));
10031 /* delete ua<->name mappings */
10032 ddi_soft_state_bystr_free(phymap
->phymap_ua2name
, ua
);
10033 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
10034 mutex_exit(&phymap
->phymap_lock
);
10035 return (DAM_SUCCESS
);
10039 sas_phymap_create(dev_info_t
*self
, int settle_usec
,
10040 sas_phymap_mode_t mode
, void *mode_argument
, void *phymap_priv
,
10041 sas_phymap_activate_cb_t activate_cb
,
10042 sas_phymap_deactivate_cb_t deactivate_cb
,
10043 sas_phymap_t
**handlep
)
10045 _NOTE(ARGUNUSED(mode_argument
));
10047 impl_sas_phymap_t
*phymap
;
10049 if (self
== NULL
|| settle_usec
== 0 || handlep
== NULL
)
10050 return (DDI_FAILURE
);
10052 if (mode
!= PHYMAP_MODE_SIMPLE
)
10053 return (DDI_FAILURE
);
10055 phymap
= kmem_zalloc(sizeof (*phymap
), KM_SLEEP
);
10056 phymap
->phymap_self
= self
;
10057 phymap
->phymap_reports_max
= 1 * sas_phymap_phy_max_factor
;
10058 phymap
->phymap_acp
= activate_cb
;
10059 phymap
->phymap_dcp
= deactivate_cb
;
10060 phymap
->phymap_private
= phymap_priv
;
10061 mutex_init(&phymap
->phymap_lock
, NULL
, MUTEX_DRIVER
, NULL
);
10063 (void) snprintf(context
, sizeof (context
), "%s%d.phymap",
10064 ddi_driver_name(self
), ddi_get_instance(self
));
10065 SCSI_HBA_LOG((_LOGPHY
, self
, NULL
, "%s", context
));
10067 if (ddi_soft_state_init(&phymap
->phymap_phy2name
,
10068 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10070 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2phys
,
10071 sizeof (bitset_t
), SAS_PHY_NPHY
) != 0)
10074 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2ua
,
10075 SAS_PHY_UA_LEN
, SAS_PHY_NPHY
) != 0)
10077 if (ddi_soft_state_bystr_init(&phymap
->phymap_ua2name
,
10078 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10081 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
10082 settle_usec
, NULL
, NULL
, NULL
,
10083 phymap
, sas_phymap_config
, sas_phymap_unconfig
,
10084 &phymap
->phymap_dam
) != DAM_SUCCESS
)
10088 *handlep
= (sas_phymap_t
*)phymap
;
10089 return (DDI_SUCCESS
);
10091 fail
: sas_phymap_destroy((sas_phymap_t
*)phymap
);
10093 return (DDI_FAILURE
);
10097 sas_phymap_destroy(sas_phymap_t
*handle
)
10099 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10101 struct impl_sas_physet
*physet
, *nphyset
;
10105 context
= phymap
->phymap_dam
?
10106 damap_name(phymap
->phymap_dam
) : "unknown";
10107 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s", context
));
10109 if (phymap
->phymap_dam
)
10110 damap_destroy(phymap
->phymap_dam
);
10112 /* free the bitsets of allocated physets */
10113 for (physet
= phymap
->phymap_physets
; physet
; physet
= nphyset
) {
10114 nphyset
= physet
->physet_next
;
10115 phys
= physet
->physet_phys
;
10116 name
= physet
->physet_name
;
10121 ddi_soft_state_bystr_free(
10122 phymap
->phymap_name2phys
, name
);
10125 kmem_free(physet
, sizeof (*physet
));
10128 /* free the maps */
10129 if (phymap
->phymap_ua2name
)
10130 ddi_soft_state_bystr_fini(&phymap
->phymap_ua2name
);
10131 if (phymap
->phymap_name2ua
)
10132 ddi_soft_state_bystr_fini(&phymap
->phymap_name2ua
);
10134 if (phymap
->phymap_name2phys
)
10135 ddi_soft_state_bystr_fini(&phymap
->phymap_name2phys
);
10136 if (phymap
->phymap_phy2name
)
10137 ddi_soft_state_fini(&phymap
->phymap_phy2name
);
10139 mutex_destroy(&phymap
->phymap_lock
);
10140 kmem_free(phymap
, sizeof (*phymap
));
10145 sas_phymap_phy_add(sas_phymap_t
*handle
,
10146 int phy
, uint64_t local
, uint64_t remote
)
10148 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10149 char *context
= damap_name(phymap
->phymap_dam
);
10150 char port
[SAS_PHY_NAME_LEN
];
10152 int phy2name_allocated
= 0;
10154 struct impl_sas_physet
*physet
;
10157 /* Create the SAS port name from the local and remote addresses. */
10158 (void) snprintf(port
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10161 mutex_enter(&phymap
->phymap_lock
);
10162 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: add phy %d",
10163 context
, port
, phy
));
10165 /* Check for conflict in phy2name map */
10166 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10168 if (strcmp(name
, port
) != 0)
10169 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10170 "already in %s", context
, port
, phy
, name
));
10172 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10173 "duplicate add", context
, port
, phy
));
10174 mutex_exit(&phymap
->phymap_lock
);
10175 return (DDI_FAILURE
);
10178 /* allocate, get, and initialize phy index of phy2name map */
10179 if (ddi_soft_state_zalloc(
10180 phymap
->phymap_phy2name
, phy
) != DDI_SUCCESS
) {
10181 SCSI_HBA_LOG((_LOG_NF(WARN
),
10182 "%s: %s: failed phy2name alloc", context
, port
));
10185 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10186 if (name
== NULL
) {
10187 SCSI_HBA_LOG((_LOG_NF(WARN
),
10188 "%s: %s: no phy2name", context
, port
));
10191 phy2name_allocated
= 1;
10192 (void) strlcpy(name
, port
, SAS_PHY_NAME_LEN
); /* set name */
10194 /* Find/alloc, initialize name index of name2phys map */
10195 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10196 if (phys
== NULL
) {
10197 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2phys
,
10198 name
) != DDI_SUCCESS
) {
10199 SCSI_HBA_LOG((_LOG_NF(WARN
),
10200 "%s: %s: failed name2phys alloc", context
, name
));
10203 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10204 if (phys
== NULL
) {
10205 SCSI_HBA_LOG((_LOG_NF(WARN
),
10206 "%s: %s: no name2phys", context
, name
));
10210 /* Initialize bitset of phys. */
10212 bitset_resize(phys
, SAS_PHY_NPHY
);
10214 /* Keep a list of information for destroy. */
10215 physet
= kmem_zalloc(sizeof (*physet
), KM_SLEEP
);
10216 physet
->physet_name
= strdup(name
);
10217 physet
->physet_phys
= phys
;
10218 physet
->physet_next
= phymap
->phymap_physets
;
10219 phymap
->phymap_physets
= physet
;
10223 /* Reflect 'add' in phys bitset. */
10224 if (bitset_atomic_test_and_add(phys
, phy
) < 0) {
10225 /* It is an error if the phy was already recorded. */
10226 SCSI_HBA_LOG((_LOG_NF(WARN
),
10227 "%s: %s: phy bit %d already in port", context
, name
, phy
));
10232 * Check to see if we have a new phy_max for this map, and if so
10233 * scale phymap_reports_max to the new number of phys.
10235 if (phy
> phymap
->phymap_phy_max
) {
10236 phymap
->phymap_phy_max
= phy
+ 1;
10237 phymap
->phymap_reports_max
= phymap
->phymap_phy_max
*
10238 sas_phymap_phy_max_factor
;
10242 * If we have not reached phymap_reports_max, start/restart the
10243 * activate timer. Otherwise, if phymap->phymap_reports add/rem reports
10244 * ever exceeds phymap_reports_max due to noisy phys, then report the
10245 * noise and force stabilization by stopping reports into the damap.
10247 * The first config/unconfig callout out of the damap will reset
10248 * phymap->phymap_reports.
10251 if (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
) {
10252 if (damap_addr_add(phymap
->phymap_dam
, name
,
10253 NULL
, NULL
, NULL
) == DAM_SUCCESS
) {
10254 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10255 "%s: %s: damap_addr_add", context
, name
));
10257 SCSI_HBA_LOG((_LOG_NF(WARN
),
10258 "%s: %s: damap_addr_add failed", context
, name
));
10262 phymap
->phymap_phys_noisy
++;
10263 if (phymap
->phymap_phys_noisy
== 1)
10264 SCSI_HBA_LOG((_LOG_NF(WARN
),
10265 "%s: %s: noisy phys", context
, name
));
10267 mutex_exit(&phymap
->phymap_lock
);
10270 fail
: if (phy2name_allocated
)
10271 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
);
10272 mutex_exit(&phymap
->phymap_lock
);
10273 return (DDI_FAILURE
);
10277 sas_phymap_phy_rem(sas_phymap_t
*handle
, int phy
)
10279 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10280 char *context
= damap_name(phymap
->phymap_dam
);
10283 int rv
= DDI_FAILURE
;
10287 mutex_enter(&phymap
->phymap_lock
);
10288 phymap
->phymap_reports
++;
10290 /* Find and free phy index of phy2name map */
10291 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10292 if (name
== NULL
) {
10293 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: rem phy %d: never added",
10297 /* NOTE: always free phy index of phy2name map before return... */
10299 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: rem phy %d",
10300 context
, name
, phy
));
10302 /* Get bitset of phys currently associated with named port. */
10303 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10304 if (phys
== NULL
) {
10305 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: name2phys failed",
10310 /* Reflect 'rem' in phys bitset. */
10311 if (bitset_atomic_test_and_del(phys
, phy
) < 0) {
10312 /* It is an error if the phy wasn't one of the port's phys. */
10313 SCSI_HBA_LOG((_LOG_NF(WARN
),
10314 "%s: %s: phy bit %d not in port", context
, name
, phy
));
10318 /* If this was the last phy in the port, start the deactivate timer. */
10319 if (bitset_is_null(phys
) &&
10320 (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
)) {
10321 if (damap_addr_del(phymap
->phymap_dam
, name
) == DAM_SUCCESS
) {
10322 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10323 "%s: %s: damap_addr_del", context
, name
));
10325 SCSI_HBA_LOG((_LOG_NF(WARN
),
10326 "%s: %s: damap_addr_del failure", context
, name
));
10332 /* free phy index of phy2name map */
10334 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
); /* free */
10335 mutex_exit(&phymap
->phymap_lock
);
10340 sas_phymap_lookup_ua(sas_phymap_t
*handle
, uint64_t local
, uint64_t remote
)
10342 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10343 char *context
= damap_name(phymap
->phymap_dam
);
10344 char name
[SAS_PHY_NAME_LEN
];
10349 (void) snprintf(name
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10352 mutex_enter(&phymap
->phymap_lock
);
10353 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10354 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10355 "%s: %s: ua %s", context
, name
, ua
? ua
: "NULL"));
10356 mutex_exit(&phymap
->phymap_lock
);
10361 sas_phymap_lookup_uapriv(sas_phymap_t
*handle
, char *ua
)
10363 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10364 char *context
= damap_name(phymap
->phymap_dam
);
10367 void *ua_priv
= NULL
;
10371 mutex_enter(&phymap
->phymap_lock
);
10372 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10374 phyid
= damap_lookup(phymap
->phymap_dam
, name
);
10375 if (phyid
!= NODAM
) {
10376 ua_priv
= damap_id_priv_get(phymap
->phymap_dam
, phyid
);
10377 damap_id_rele(phymap
->phymap_dam
, phyid
);
10381 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10382 "%s: %s: ua %s ua_priv %p", context
, name
,
10383 ua
? ua
: "NULL", ua_priv
));
10384 mutex_exit(&phymap
->phymap_lock
);
10389 sas_phymap_uahasphys(sas_phymap_t
*handle
, char *ua
)
10391 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10396 mutex_enter(&phymap
->phymap_lock
);
10397 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10399 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10401 n
= bitset_is_null(phys
) ? 0 : 1;
10403 mutex_exit(&phymap
->phymap_lock
);
10407 sas_phymap_phys_t
*
10408 sas_phymap_ua2phys(sas_phymap_t
*handle
, char *ua
)
10410 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10413 bitset_t
*cphys
= NULL
;
10415 mutex_enter(&phymap
->phymap_lock
);
10416 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10420 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10424 /* dup the phys and return */
10425 cphys
= kmem_alloc(sizeof (*cphys
), KM_SLEEP
);
10426 bitset_init(cphys
);
10427 bitset_resize(cphys
, SAS_PHY_NPHY
);
10428 bitset_copy(phys
, cphys
);
10430 fail
: mutex_exit(&phymap
->phymap_lock
);
10431 return ((sas_phymap_phys_t
*)cphys
);
10435 sas_phymap_phys_next(sas_phymap_phys_t
*phys
)
10437 bitset_t
*cphys
= (bitset_t
*)phys
;
10440 phy
= bitset_find(cphys
);
10442 bitset_del(cphys
, phy
);
10447 sas_phymap_phys_free(sas_phymap_phys_t
*phys
)
10449 bitset_t
*cphys
= (bitset_t
*)phys
;
10452 bitset_fini(cphys
);
10453 kmem_free(cphys
, sizeof (*cphys
));
10458 sas_phymap_phy2ua(sas_phymap_t
*handle
, int phy
)
10460 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10465 mutex_enter(&phymap
->phymap_lock
);
10466 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10469 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10473 /* dup the ua and return */
10476 fail
: mutex_exit(&phymap
->phymap_lock
);
10481 sas_phymap_ua_free(char *ua
)