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 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
30 * Generic SCSI Host Bus Adapter interface implementation
32 #include <sys/scsi/scsi.h>
33 #include <sys/scsi/generic/sas.h>
35 #include <sys/disp.h> /* for minclsyspri */
36 #include <sys/ddi_impldefs.h>
37 #include <sys/ndi_impldefs.h>
38 #include <sys/sunndi.h>
40 #include <sys/sunmdi.h>
41 #include <sys/mdi_impldefs.h>
42 #include <sys/callb.h>
44 #include <sys/damap.h>
46 #include <sys/sunldi.h>
47 #include <sys/fm/protocol.h>
49 extern struct scsi_pkt
*scsi_init_cache_pkt(struct scsi_address
*,
50 struct scsi_pkt
*, struct buf
*, int, int, int, int,
51 int (*)(caddr_t
), caddr_t
);
52 extern void scsi_free_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
53 extern void scsi_cache_dmafree(struct scsi_address
*, struct scsi_pkt
*);
54 extern void scsi_sync_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
55 extern int modrootloaded
;
58 * Round up all allocations so that we can guarantee
59 * long-long alignment. This is the same alignment
60 * provided by kmem_alloc().
62 #define ROUNDUP(x) (((x) + 0x07) & ~0x07)
64 /* Magic number to track correct allocations in wrappers */
65 #define PKT_WRAPPER_MAGIC 0xa110ced /* alloced correctly */
67 kmutex_t scsi_flag_nointr_mutex
;
68 kcondvar_t scsi_flag_nointr_cv
;
69 kmutex_t scsi_log_mutex
;
71 /* asynchronous probe barrier deletion data structures */
72 static kmutex_t scsi_hba_barrier_mutex
;
73 static kcondvar_t scsi_hba_barrier_cv
;
74 static struct scsi_hba_barrier
{
75 struct scsi_hba_barrier
*barrier_next
;
76 clock_t barrier_endtime
;
77 dev_info_t
*barrier_probe
;
78 } *scsi_hba_barrier_list
;
79 static int scsi_hba_devi_is_barrier(dev_info_t
*probe
);
80 static void scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
);
81 static void scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
);
82 static int scsi_hba_remove_node(dev_info_t
*child
);
83 static void scsi_hba_barrier_daemon(void *arg
);
85 /* LUN-change ASC/ASCQ processing data structures (stage1 and stage2) */
86 static kmutex_t scsi_lunchg1_mutex
;
87 static kcondvar_t scsi_lunchg1_cv
;
88 static struct scsi_pkt
*scsi_lunchg1_list
;
89 static void scsi_lunchg1_daemon(void *arg
);
90 static kmutex_t scsi_lunchg2_mutex
;
91 static kcondvar_t scsi_lunchg2_cv
;
92 static struct scsi_lunchg2
{
93 struct scsi_lunchg2
*lunchg2_next
;
96 static void scsi_lunchg2_daemon(void *arg
);
98 static int scsi_findchild(dev_info_t
*self
, char *name
, char *addr
,
99 int init
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
);
101 /* return value defines for scsi_findchild */
102 #define CHILD_TYPE_NONE 0
103 #define CHILD_TYPE_DEVINFO 1
104 #define CHILD_TYPE_PATHINFO 2
107 * Enumeration code path currently being followed. SE_BUSCONFIG results in
108 * DEVI_SID_NODEID, and SE_HP (hotplug) results in DEVI_SID_HP_NODEID.
110 * Since hotplug enumeration is based on information obtained from hardware
111 * (tgtmap/report_lun) the type/severity of enumeration error messages is
112 * sometimes based SE_HP (indirectly via ndi_dev_is_hotplug_node()). By
113 * convention, these messages are all produced by scsi_enumeration_failed().
115 typedef enum { SE_BUSCONFIG
= 0, SE_HP
= 1 } scsi_enum_t
;
117 /* compatible properties of driver to use during probe/enumeration operations */
118 static char *compatible_probe
= "scsa,probe";
119 static char *compatible_nodev
= "scsa,nodev";
120 static char *scsi_probe_ascii
[] = SCSIPROBE_ASCII
;
122 /* number of LUNs we attempt to get on the first SCMD_REPORT_LUNS command */
123 int scsi_lunrpt_default_max
= 256;
124 int scsi_lunrpt_timeout
= 3; /* seconds */
127 * Only enumerate one lun if reportluns fails on a SCSI_VERSION_3 device
128 * (tunable based on calling context).
130 int scsi_lunrpt_failed_do1lun
= (1 << SE_HP
);
132 /* 'scsi-binding-set' value for legacy enumerated 'spi' transports */
133 char *scsi_binding_set_spi
= "spi";
135 /* enable NDI_DEVI_DEBUG for bus_[un]config operations */
136 int scsi_hba_bus_config_debug
= 0;
138 /* DEBUG: enable NDI_DEVI_REMOVE for bus_unconfig of dynamic node */
139 int scsi_hba_bus_unconfig_remove
= 0;
141 /* number of probe serilization messages */
142 int scsi_hba_wait_msg
= 5;
145 * Establish the timeout used to cache (in the probe node) the fact that the
146 * device does not exist. This replaces the target specific probe cache.
148 int scsi_hba_barrier_timeout
= (60); /* seconds */
151 int scsi_hba_bus_config_failure_msg
= 0;
152 int scsi_hba_bus_config_failure_dbg
= 0;
153 int scsi_hba_bus_config_success_msg
= 0;
154 int scsi_hba_bus_config_success_dbg
= 0;
158 * Structure for scsi_hba_iportmap_* implementation/wrap.
160 typedef struct impl_scsi_iportmap
{
161 dev_info_t
*iportmap_hba_dip
;
162 damap_t
*iportmap_dam
;
163 int iportmap_create_window
;
164 uint64_t iportmap_create_time
; /* clock64_t */
165 int iportmap_create_csync_usec
;
166 int iportmap_settle_usec
;
167 int iportmap_sync_cnt
;
168 } impl_scsi_iportmap_t
;
171 * Structure for scsi_hba_tgtmap_* implementation/wrap.
173 * Every call to scsi_hba_tgtmap_set_begin will increment tgtmap_reports,
174 * and a call to scsi_hba_tgtmap_set_end will reset tgtmap_reports to zero.
175 * If, in scsi_hba_tgtmap_set_begin, we detect a tgtmap_reports value of
176 * scsi_hba_tgtmap_reports_max we produce a message to indicate that
177 * the caller is never completing an observation (i.e. we are not making
178 * any forward progress). If this message occurs, it indicates that the
179 * solaris hotplug ramifications at the target and lun level are no longer
182 * NOTE: LUNMAPSIZE OK for now, but should be dynamic in reportlun code.
184 typedef struct impl_scsi_tgtmap
{
185 scsi_hba_tran_t
*tgtmap_tran
;
186 int tgtmap_reports
; /* _begin, no _end */
188 scsi_tgt_activate_cb_t tgtmap_activate_cb
;
189 scsi_tgt_deactivate_cb_t tgtmap_deactivate_cb
;
190 void *tgtmap_mappriv
;
191 damap_t
*tgtmap_dam
[SCSI_TGT_NTYPES
];
192 int tgtmap_create_window
;
193 uint64_t tgtmap_create_time
; /* clock64_t */
194 int tgtmap_create_csync_usec
;
195 int tgtmap_settle_usec
;
197 } impl_scsi_tgtmap_t
;
198 #define LUNMAPSIZE 256 /* 256 LUNs/target */
200 /* Produce warning if number of begins without an end exceed this value */
201 int scsi_hba_tgtmap_reports_max
= 256;
203 static int scsi_tgtmap_sync(scsi_hba_tgtmap_t
*, int);
205 /* Default settle_usec damap_sync factor */
206 int scsi_hba_map_settle_f
= 10;
209 /* Prototype for static dev_ops devo_*() functions */
210 static int scsi_hba_info(
212 ddi_info_cmd_t infocmd
,
216 /* Prototypes for static bus_ops bus_*() functions */
217 static int scsi_hba_bus_ctl(
224 static int scsi_hba_map_fault(
235 static int scsi_hba_get_eventcookie(
239 ddi_eventcookie_t
*eventp
);
241 static int scsi_hba_add_eventcall(
244 ddi_eventcookie_t event
,
247 ddi_eventcookie_t event
,
251 ddi_callback_id_t
*cb_id
);
253 static int scsi_hba_remove_eventcall(
255 ddi_callback_id_t id
);
257 static int scsi_hba_post_event(
260 ddi_eventcookie_t event
,
263 static int scsi_hba_bus_config(
266 ddi_bus_config_op_t op
,
268 dev_info_t
**childp
);
270 static int scsi_hba_bus_unconfig(
273 ddi_bus_config_op_t op
,
276 static int scsi_hba_fm_init_child(
280 ddi_iblock_cookie_t
*ibc
);
282 static int scsi_hba_bus_power(
285 pm_bus_power_op_t op
,
289 /* bus_ops vector for SCSI HBA's. */
290 static struct bus_ops scsi_hba_busops
= {
292 nullbusmap
, /* bus_map */
293 NULL
, /* bus_get_intrspec */
294 NULL
, /* bus_add_intrspec */
295 NULL
, /* bus_remove_intrspec */
296 scsi_hba_map_fault
, /* bus_map_fault */
297 NULL
, /* bus_dma_map */
298 ddi_dma_allochdl
, /* bus_dma_allochdl */
299 ddi_dma_freehdl
, /* bus_dma_freehdl */
300 ddi_dma_bindhdl
, /* bus_dma_bindhdl */
301 ddi_dma_unbindhdl
, /* bus_unbindhdl */
302 ddi_dma_flush
, /* bus_dma_flush */
303 ddi_dma_win
, /* bus_dma_win */
304 ddi_dma_mctl
, /* bus_dma_ctl */
305 scsi_hba_bus_ctl
, /* bus_ctl */
306 ddi_bus_prop_op
, /* bus_prop_op */
307 scsi_hba_get_eventcookie
, /* bus_get_eventcookie */
308 scsi_hba_add_eventcall
, /* bus_add_eventcall */
309 scsi_hba_remove_eventcall
, /* bus_remove_eventcall */
310 scsi_hba_post_event
, /* bus_post_event */
311 NULL
, /* bus_intr_ctl */
312 scsi_hba_bus_config
, /* bus_config */
313 scsi_hba_bus_unconfig
, /* bus_unconfig */
314 scsi_hba_fm_init_child
, /* bus_fm_init */
315 NULL
, /* bus_fm_fini */
316 NULL
, /* bus_fm_access_enter */
317 NULL
, /* bus_fm_access_exit */
318 scsi_hba_bus_power
/* bus_power */
321 /* cb_ops for hotplug :devctl and :scsi support */
322 static struct cb_ops scsi_hba_cbops
= {
325 nodev
, /* strategy */
330 scsi_hba_ioctl
, /* ioctl */
335 ddi_prop_op
, /* prop_op */
337 D_NEW
|D_MP
|D_HOTPLUG
, /* cb_flag */
339 nodev
, /* int (*cb_aread)() */
340 nodev
/* int (*cb_awrite)() */
343 /* Prototypes for static scsi_hba.c/SCSA private lunmap interfaces */
344 static int scsi_lunmap_create(
346 impl_scsi_tgtmap_t
*tgtmap
,
348 static void scsi_lunmap_destroy(
350 impl_scsi_tgtmap_t
*tgtmap
,
352 static void scsi_lunmap_set_begin(
355 static int scsi_lunmap_set_add(
359 scsi_lun64_t lun_num
,
361 static void scsi_lunmap_set_end(
365 /* Prototypes for static misc. scsi_hba.c private bus_config interfaces */
366 static int scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
367 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
368 static int scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
369 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
370 static dev_info_t
*scsi_hba_bus_config_port(dev_info_t
*self
,
371 char *nameaddr
, scsi_enum_t se
);
374 static int scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
375 void *arg
, dev_info_t
**childp
);
380 * SCSI_HBA_LOG is used for all messages. A logging level is specified when
381 * generating a message. Some levels correspond directly to cmn_err levels,
382 * some are associated with increasing levels diagnostic/debug output (LOG1-4),
383 * and others are associated with specific levels of interface (LOGMAP).
384 * For _LOG() messages, a __func__ prefix will identify the function origin
385 * of the message. For _LOG_NF messages, there is no function prefix or
386 * self/child context. Filtering of messages is provided based on logging
387 * level, but messages with cmn_err logging level and messages generated
388 * generated with _LOG_NF() are never filtered.
390 * For debugging, more complete information can be displayed with each message
391 * (full device path and pointer values) by adjusting scsi_hba_log_info.
394 #define SCSI_HBA_LOGCONT CE_CONT
395 #define SCSI_HBA_LOGNOTE CE_NOTE
396 #define SCSI_HBA_LOGWARN CE_WARN
397 #define SCSI_HBA_LOGPANIC CE_PANIC
398 #define SCSI_HBA_LOGIGNORE CE_IGNORE
399 #define SCSI_HBA_LOG_CE_MASK 0x0000000F /* no filter for these levels */
400 #define SCSI_HBA_LOG1 0x00000010 /* DIAG1 level enable */
401 #define SCSI_HBA_LOG2 0x00000020 /* DIAG2 level enable */
402 #define SCSI_HBA_LOG3 0x00000040 /* DIAG3 level enable */
403 #define SCSI_HBA_LOG4 0x00000080 /* DIAG4 level enable */
404 #define SCSI_HBA_LOGMAPPHY 0x00000100 /* MAPPHY level enable */
405 #define SCSI_HBA_LOGMAPIPT 0x00000200 /* MAPIPT level enable */
406 #define SCSI_HBA_LOGMAPTGT 0x00000400 /* MAPTGT level enable */
407 #define SCSI_HBA_LOGMAPLUN 0x00000800 /* MAPLUN level enable */
408 #define SCSI_HBA_LOGMAPCFG 0x00001000 /* MAPCFG level enable */
409 #define SCSI_HBA_LOGMAPUNCFG 0x00002000 /* MAPUNCFG level enable */
410 #define SCSI_HBA_LOGTRACE 0x00010000 /* TRACE enable */
411 #if (CE_CONT | CE_NOTE | CE_WARN | CE_PANIC | CE_IGNORE) > SCSI_HBA_LOG_CE_MASK
412 Error
, problem with CE_ definitions
416 * Tunable log message augmentation and filters: filters do not apply to
417 * SCSI_HBA_LOG_CE_MASK level messages or LOG_NF() messages.
419 * An example set of /etc/system tunings to simplify debug a SCSA pHCI HBA
420 * driver called "pmcs", including "scsi_vhci" operation, by capturing
421 * log information in the system log might be:
423 * echo "set scsi:scsi_hba_log_filter_level=0x3ff0" >> /etc/system
424 * echo "set scsi:scsi_hba_log_filter_phci=\"pmcs\"" >> /etc/system
425 * echo "set scsi:scsi_hba_log_filter_vhci=\"scsi_vhci\"" >> /etc/system
427 * To capture information on just HBA-SCSAv3 *map operation, use
428 * echo "set scsi:scsi_hba_log_filter_level=0x3f10" >> /etc/system
430 * For debugging an HBA driver, you may also want to set:
432 * echo "set scsi:scsi_hba_log_align=1" >> /etc/system
433 * echo "set scsi:scsi_hba_log_mt_disable=0x6" >> /etc/system
434 * echo "set mtc_off=1" >> /etc/system
435 * echo "set mdi_mtc_off=1" >> /etc/system
436 * echo "set scsi:scsi_hba_log_fcif=0" >> /etc/system
438 int scsi_hba_log_filter_level
=
441 char *scsi_hba_log_filter_phci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
442 char *scsi_hba_log_filter_vhci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
443 int scsi_hba_log_align
= 0; /* NOTE: will not cause truncation */
444 int scsi_hba_log_fcif
= '!'; /* "^!?" first char in format */
445 /* NOTE: iff level > SCSI_HBA_LOG1 */
446 /* '\0'0x00 -> console and system log */
447 /* '^' 0x5e -> console_only */
448 /* '!' 0x21 -> system log only */
449 /* '?' 0x2F -> See cmn_err(9F) */
450 int scsi_hba_log_info
= /* augmentation: extra info output */
451 (0 << 0) | /* 0x0001: process information */
452 (0 << 1) | /* 0x0002: full /devices path */
453 (0 << 2); /* 0x0004: devinfo pointer */
455 int scsi_hba_log_mt_disable
=
456 /* SCSI_ENUMERATION_MT_LUN_DISABLE | (ie 0x02) */
457 /* SCSI_ENUMERATION_MT_TARGET_DISABLE | (ie 0x04) */
460 /* static data for HBA logging subsystem */
461 static kmutex_t scsi_hba_log_mutex
;
462 static char scsi_hba_log_i
[512];
463 static char scsi_hba_log_buf
[512];
464 static char scsi_hba_fmt
[512];
466 /* Macros to use in scsi_hba.c source code below */
467 #define SCSI_HBA_LOG(x) scsi_hba_log x
468 #define _LOG(level) SCSI_HBA_LOG##level, __func__
469 #define _MAP(map) SCSI_HBA_LOGMAP##map, __func__
470 #define _LOG_NF(level) SCSI_HBA_LOG##level, NULL, NULL, NULL
471 #define _LOG_TRACE _LOG(TRACE)
472 #define _LOGLUN _MAP(LUN)
473 #define _LOGTGT _MAP(TGT)
474 #define _LOGIPT _MAP(IPT)
475 #define _LOGPHY _MAP(PHY)
476 #define _LOGCFG _MAP(CFG)
477 #define _LOGUNCFG _MAP(UNCFG)
481 scsi_hba_log(int level
, const char *func
, dev_info_t
*self
, dev_info_t
*child
,
482 const char *fmt
, ...)
491 /* derive self from child's parent */
492 if ((self
== NULL
) && child
)
493 self
= ddi_get_parent(child
);
495 /* no filtering of SCSI_HBA_LOG_CE_MASK or LOG_NF messages */
496 if (((level
& SCSI_HBA_LOG_CE_MASK
) != level
) && (func
!= NULL
)) {
497 /* scsi_hba_log_filter_level: filter on level as bitmask */
498 if ((level
& scsi_hba_log_filter_level
) == 0)
501 /* scsi_hba_log_filter_phci/vhci: on name of driver */
502 if (*scsi_hba_log_filter_phci
&&
504 (ddi_driver_name(self
) == NULL
) ||
505 strcmp(ddi_driver_name(self
), scsi_hba_log_filter_phci
))) {
506 /* does not match pHCI, check vHCI */
507 if (*scsi_hba_log_filter_vhci
&&
509 (ddi_driver_name(self
) == NULL
) ||
510 strcmp(ddi_driver_name(self
),
511 scsi_hba_log_filter_vhci
))) {
512 /* does not match vHCI */
518 /* passed filters, determine align */
519 align
= scsi_hba_log_align
;
521 /* shorten func for filtered output */
522 if (strncmp(func
, "scsi_hba_", 9) == 0)
524 if (strncmp(func
, "scsi_", 5) == 0)
527 /* don't align output that is never filtered */
531 /* determine the cmn_err form from the level */
532 clevel
= ((level
& SCSI_HBA_LOG_CE_MASK
) == level
) ? level
: CE_CONT
;
534 /* protect common buffers used to format output */
535 mutex_enter(&scsi_hba_log_mutex
);
537 /* skip special first characters, we add them back below */
539 if (*f
&& strchr("^!?", *f
))
542 (void) vsprintf(scsi_hba_log_buf
, f
, ap
);
545 /* augment message with 'information' */
546 info
= scsi_hba_log_i
;
548 if ((scsi_hba_log_info
& 0x0001) && curproc
&& PTOU(curproc
)->u_comm
) {
549 (void) sprintf(info
, "%s[%d]%p ",
550 PTOU(curproc
)->u_comm
, curproc
->p_pid
, (void *)curthread
);
551 info
+= strlen(info
);
554 if ((scsi_hba_log_info
& 0x0004) && (child
|| self
)) {
555 (void) sprintf(info
, "%p ",
556 (void *)(child
? child
: self
));
557 info
+= strlen(info
);
559 if (scsi_hba_log_info
& 0x0002) {
560 (void) ddi_pathname(child
? child
: self
, info
);
561 (void) strcat(info
, " ");
562 info
+= strlen(info
);
565 /* always provide 'default' information about self &child */
566 (void) sprintf(info
, "%s%d ", ddi_driver_name(self
),
567 ddi_get_instance(self
));
568 info
+= strlen(info
);
570 ua
= ddi_get_name_addr(child
);
571 (void) sprintf(info
, "%s@%s ",
572 ddi_node_name(child
), (ua
&& *ua
) ? ua
: "");
573 info
+= strlen(info
);
577 /* turn off alignment if truncation would occur */
578 if (align
&& ((strlen(func
) > 18) || (strlen(scsi_hba_log_i
) > 36)))
581 /* adjust for aligned output */
585 /* remove trailing blank with align output */
586 if ((info
!= scsi_hba_log_i
) && (*(info
-1) == '\b'))
590 /* special "first character in format" must be in format itself */
592 if (fmt
[0] && strchr("^!?", fmt
[0]))
594 else if (scsi_hba_log_fcif
&& (level
> SCSI_HBA_LOG1
))
595 *f
++ = (char)scsi_hba_log_fcif
; /* add global fcif */
597 (void) sprintf(f
, "%s", "%-18.18s: %36.36s: %s%s");
599 (void) sprintf(f
, "%s", func
? "%s: %s%s%s" : "%s%s%s");
602 cmn_err(clevel
, scsi_hba_fmt
, func
, scsi_hba_log_i
,
603 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
605 cmn_err(clevel
, scsi_hba_fmt
, scsi_hba_log_i
,
606 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
607 mutex_exit(&scsi_hba_log_mutex
);
610 int scsi_enumeration_failed_panic
= 0;
611 int scsi_enumeration_failed_hotplug
= 1;
614 scsi_enumeration_failed(dev_info_t
*child
, scsi_enum_t se
,
615 char *arg
, char *when
)
617 /* If 'se' is -1 the 'se' value comes from child. */
620 se
= ndi_dev_is_hotplug_node(child
) ? SE_HP
: SE_BUSCONFIG
;
623 if (scsi_enumeration_failed_panic
) {
624 /* set scsi_enumeration_failed_panic to debug */
625 SCSI_HBA_LOG((_LOG(PANIC
), NULL
, child
,
626 "%s%senumeration failed during %s",
627 arg
? arg
: "", arg
? " " : "", when
));
628 } else if (scsi_enumeration_failed_hotplug
&& (se
== SE_HP
)) {
629 /* set scsi_enumeration_failed_hotplug for console messages */
630 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
,
631 "%s%senumeration failed during %s",
632 arg
? arg
: "", arg
? " " : "", when
));
635 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
636 "%s%senumeration failed during %s",
637 arg
? arg
: "", arg
? " " : "", when
));
642 * scsi_hba version of [nm]di_devi_enter/[nm]di_devi_exit that detects if HBA
643 * is a PHCI, and chooses mdi/ndi locking implementation.
646 scsi_hba_devi_enter(dev_info_t
*self
, int *circp
)
649 mdi_devi_enter(self
, circp
);
651 ndi_devi_enter(self
, circp
);
655 scsi_hba_devi_tryenter(dev_info_t
*self
, int *circp
)
658 return (mdi_devi_tryenter(self
, circp
));
660 return (ndi_devi_tryenter(self
, circp
));
664 scsi_hba_devi_exit(dev_info_t
*self
, int circ
)
667 mdi_devi_exit(self
, circ
);
669 ndi_devi_exit(self
, circ
);
673 scsi_hba_devi_enter_phci(dev_info_t
*self
, int *circp
)
676 mdi_devi_enter_phci(self
, circp
);
680 scsi_hba_devi_exit_phci(dev_info_t
*self
, int circ
)
683 mdi_devi_exit_phci(self
, circ
);
687 scsi_hba_dev_is_sid(dev_info_t
*child
)
690 * Use ndi_dev_is_persistent_node instead of ddi_dev_is_sid to avoid
691 * any possible locking issues in mixed nexus devctl code (like usb).
693 return (ndi_dev_is_persistent_node(child
));
697 * Called from _init() when loading "scsi" module
700 scsi_initialize_hba_interface()
702 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
704 /* We need "scsiprobe" and "scsinodev" as an alias or a driver. */
705 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
) {
706 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
707 "driver alias, defaulting to 'nulldriver'",
710 /* If no "nulldriver" driver nothing will work... */
711 compatible_probe
= "nulldriver";
712 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
)
713 SCSI_HBA_LOG((_LOG_NF(WARN
), "no probe '%s' driver, "
714 "system misconfigured", compatible_probe
));
716 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
) {
717 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
718 "driver alias, defaulting to 'nulldriver'",
721 /* If no "nulldriver" driver nothing will work... */
722 compatible_nodev
= "nulldriver";
723 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
)
724 SCSI_HBA_LOG((_LOG_NF(WARN
), "no nodev '%s' driver, "
725 "system misconfigured", compatible_nodev
));
729 * Verify our special node name "probe" will not be used in other ways.
730 * Don't expect things to work if they are.
732 if (ddi_major_to_name(ddi_name_to_major("probe")))
733 SCSI_HBA_LOG((_LOG_NF(WARN
),
734 "driver already using special node name 'probe'"));
736 mutex_init(&scsi_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
737 mutex_init(&scsi_flag_nointr_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
738 cv_init(&scsi_flag_nointr_cv
, NULL
, CV_DRIVER
, NULL
);
739 mutex_init(&scsi_hba_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
741 /* initialize the asynchronous barrier deletion daemon */
742 mutex_init(&scsi_hba_barrier_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
743 cv_init(&scsi_hba_barrier_cv
, NULL
, CV_DRIVER
, NULL
);
744 (void) thread_create(NULL
, 0,
745 (void (*)())scsi_hba_barrier_daemon
, NULL
,
746 0, &p0
, TS_RUN
, minclsyspri
);
748 /* initialize lun change ASC/ASCQ processing daemon (stage1 & stage2) */
749 mutex_init(&scsi_lunchg1_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
750 cv_init(&scsi_lunchg1_cv
, NULL
, CV_DRIVER
, NULL
);
751 (void) thread_create(NULL
, 0,
752 (void (*)())scsi_lunchg1_daemon
, NULL
,
753 0, &p0
, TS_RUN
, minclsyspri
);
754 mutex_init(&scsi_lunchg2_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
755 cv_init(&scsi_lunchg2_cv
, NULL
, CV_DRIVER
, NULL
);
756 (void) thread_create(NULL
, 0,
757 (void (*)())scsi_lunchg2_daemon
, NULL
,
758 0, &p0
, TS_RUN
, minclsyspri
);
762 scsi_hba_pkt_constructor(void *buf
, void *arg
, int kmflag
)
764 struct scsi_pkt_cache_wrapper
*pktw
;
765 struct scsi_pkt
*pkt
;
766 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
771 * allocate a chunk of memory for the following:
775 * pkt_cdbp, if needed
776 * (pkt_private always null)
777 * pkt_scbp, if needed
779 pkt_len
= tran
->tran_hba_len
+ sizeof (struct scsi_pkt_cache_wrapper
);
780 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
781 pkt_len
+= DEFAULT_CDBLEN
;
782 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
783 pkt_len
+= DEFAULT_SCBLEN
;
788 ptr
+= sizeof (struct scsi_pkt_cache_wrapper
);
789 pkt
= &(pktw
->pcw_pkt
);
790 pkt
->pkt_ha_private
= (opaque_t
)ptr
;
792 pktw
->pcw_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
794 * keep track of the granularity at the time this handle was
797 pktw
->pcw_granular
= tran
->tran_dma_attr
.dma_attr_granular
;
799 if (ddi_dma_alloc_handle(tran
->tran_hba_dip
, &tran
->tran_dma_attr
,
800 kmflag
== KM_SLEEP
? SLEEP_FUNC
: NULL_FUNC
, NULL
,
801 &pkt
->pkt_handle
) != DDI_SUCCESS
) {
805 ptr
+= tran
->tran_hba_len
;
806 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) {
807 pkt
->pkt_cdbp
= (opaque_t
)ptr
;
808 ptr
+= DEFAULT_CDBLEN
;
810 pkt
->pkt_private
= NULL
;
811 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
812 pkt
->pkt_scbp
= (opaque_t
)ptr
;
813 if (tran
->tran_pkt_constructor
)
814 return ((*tran
->tran_pkt_constructor
)(pkt
, arg
, kmflag
));
819 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
822 scsi_hba_pkt_destructor(void *buf
, void *arg
)
824 struct scsi_pkt_cache_wrapper
*pktw
= buf
;
825 struct scsi_pkt
*pkt
= &(pktw
->pcw_pkt
);
826 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
828 ASSERT(pktw
->pcw_magic
== PKT_WRAPPER_MAGIC
);
829 ASSERT((pktw
->pcw_flags
& PCW_BOUND
) == 0);
830 if (tran
->tran_pkt_destructor
)
831 (*tran
->tran_pkt_destructor
)(pkt
, arg
);
833 /* make sure nobody messed with our pointers */
834 ASSERT(pkt
->pkt_ha_private
== (opaque_t
)((char *)pkt
+
835 sizeof (struct scsi_pkt_cache_wrapper
)));
836 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
) == 0) ||
837 (pkt
->pkt_scbp
== (opaque_t
)((char *)pkt
+
839 (((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ?
840 0 : DEFAULT_CDBLEN
) +
841 DEFAULT_PRIVLEN
+ sizeof (struct scsi_pkt_cache_wrapper
))));
842 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ||
843 (pkt
->pkt_cdbp
== (opaque_t
)((char *)pkt
+
845 sizeof (struct scsi_pkt_cache_wrapper
))));
846 ASSERT(pkt
->pkt_handle
);
847 ddi_dma_free_handle(&pkt
->pkt_handle
);
848 pkt
->pkt_handle
= NULL
;
849 pkt
->pkt_numcookies
= 0;
850 pktw
->pcw_total_xfer
= 0;
851 pktw
->pcw_totalwin
= 0;
852 pktw
->pcw_curwin
= 0;
856 * Called by an HBA from _init() to plumb in common SCSA bus_ops and
857 * cb_ops for the HBA's :devctl and :scsi minor nodes.
860 scsi_hba_init(struct modlinkage
*modlp
)
862 struct dev_ops
*hba_dev_ops
;
864 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
867 * Get a pointer to the dev_ops structure of the HBA and plumb our
868 * bus_ops vector into the HBA's dev_ops structure.
870 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
871 ASSERT(hba_dev_ops
->devo_bus_ops
== NULL
);
872 hba_dev_ops
->devo_bus_ops
= &scsi_hba_busops
;
875 * Plumb our cb_ops vector into the HBA's dev_ops structure to
876 * provide getinfo and hotplugging ioctl support if the HBA driver
877 * does not already provide this support.
879 if (hba_dev_ops
->devo_cb_ops
== NULL
) {
880 hba_dev_ops
->devo_cb_ops
= &scsi_hba_cbops
;
882 if (hba_dev_ops
->devo_cb_ops
->cb_open
== scsi_hba_open
) {
883 ASSERT(hba_dev_ops
->devo_cb_ops
->cb_close
== scsi_hba_close
);
884 hba_dev_ops
->devo_getinfo
= scsi_hba_info
;
890 * Called by an HBA attach(9E) to allocate a scsi_hba_tran(9S) structure. An
891 * HBA driver will then initialize the structure and then call
892 * scsi_hba_attach_setup(9F).
900 scsi_hba_tran_t
*tran
;
902 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
904 /* allocate SCSA flavors for self */
905 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
907 tran
= kmem_zalloc(sizeof (scsi_hba_tran_t
),
908 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
911 tran
->tran_interconnect_type
= INTERCONNECT_PARALLEL
;
914 * HBA driver called scsi_hba_tran_alloc(), so tran structure
915 * is proper size and unused/newer fields are zero.
917 * NOTE: We use SCSA_HBA_SCSA_TA as an obtuse form of
918 * versioning to detect old HBA drivers that do not use
919 * scsi_hba_tran_alloc, and would present garbage data
920 * (instead of valid/zero data) for newer tran fields.
922 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
;
929 * Called by an HBA to free a scsi_hba_tran structure
933 scsi_hba_tran_t
*tran
)
935 SCSI_HBA_LOG((_LOG_TRACE
, tran
->tran_hba_dip
, NULL
, __func__
));
937 kmem_free(tran
, sizeof (scsi_hba_tran_t
));
942 scsi_hba_tran_t
*tran
,
947 int ret
= DDI_FAILURE
;
949 tran_ext
= kmem_zalloc(length
,
950 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
951 if (tran_ext
!= NULL
) {
952 tran
->tran_extension
= tran_ext
;
960 scsi_hba_tran_t
*tran
,
963 if (tran
->tran_extension
!= NULL
) {
964 kmem_free(tran
->tran_extension
, length
);
965 tran
->tran_extension
= NULL
;
970 * Obsolete: Called by an HBA to attach an instance of the driver
971 * Implement this older interface in terms of the new.
977 ddi_dma_lim_t
*hba_lim
,
978 scsi_hba_tran_t
*tran
,
982 ddi_dma_attr_t hba_dma_attr
;
984 bzero(&hba_dma_attr
, sizeof (ddi_dma_attr_t
));
985 hba_dma_attr
.dma_attr_burstsizes
= hba_lim
->dlim_burstsizes
;
986 hba_dma_attr
.dma_attr_minxfer
= hba_lim
->dlim_minxfer
;
988 return (scsi_hba_attach_setup(self
, &hba_dma_attr
, tran
, flags
));
992 * Common nexus teardown code: used by both scsi_hba_detach() on SCSA HBA node
993 * and iport_postdetach_tran_scsi_device() on a SCSA HBA iport node (and for
994 * failure cleanup). Undo scsa_nexus_setup in reverse order.
996 * NOTE: Since we are in the Solaris IO framework, we can depend on
997 * undocumented cleanup operations performed by other parts of the framework:
998 * like detach_node() calling ddi_prop_remove_all() and
999 * ddi_remove_minor_node(,NULL).
1002 scsa_nexus_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1005 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_FM
) {
1007 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_FM
;
1012 * Common nexus setup code: used by both scsi_hba_attach_setup() on SCSA HBA
1013 * node and iport_preattach_tran_scsi_device() on a SCSA HBA iport node.
1015 * This code makes no assumptions about tran use by scsi_device children.
1018 scsa_nexus_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1024 * NOTE: SCSA maintains an 'fm-capable' domain, in tran_fm_capable,
1025 * that is not dependent (limited by) the capabilities of its parents.
1026 * For example a devinfo node in a branch that is not
1027 * DDI_FM_EREPORT_CAPABLE may report as capable, via tran_fm_capable,
1028 * to its scsi_device children.
1030 * Get 'fm-capable' property from driver.conf, if present. If not
1031 * present, default to the scsi_fm_capable global (which has
1032 * DDI_FM_EREPORT_CAPABLE set by default).
1034 if (tran
->tran_fm_capable
== DDI_FM_NOT_CAPABLE
)
1035 tran
->tran_fm_capable
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
1036 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1037 "fm-capable", scsi_fm_capable
);
1040 * If an HBA is *not* doing its own fma support by calling
1041 * ddi_fm_init() prior to scsi_hba_attach_setup(), we provide a minimal
1042 * common SCSA implementation so that scsi_device children can generate
1043 * ereports via scsi_fm_ereport_post(). We use ddi_fm_capable() to
1044 * detect an HBA calling ddi_fm_init() prior to scsi_hba_attach_setup().
1046 if (tran
->tran_fm_capable
&&
1047 (ddi_fm_capable(self
) == DDI_FM_NOT_CAPABLE
)) {
1049 * We are capable of something, pass our capabilities up the
1050 * tree, but use a local variable so our parent can't limit
1051 * our capabilities (we don't want our parent to clear
1052 * DDI_FM_EREPORT_CAPABLE).
1054 * NOTE: iblock cookies are not important because scsi HBAs
1055 * always interrupt below LOCK_LEVEL.
1057 capable
= tran
->tran_fm_capable
;
1058 ddi_fm_init(self
, &capable
, NULL
);
1061 * Set SCSI_HBA_SCSA_FM bit to mark us as using the common
1062 * minimal SCSA fm implementation - we called ddi_fm_init(),
1063 * so we are responsible for calling ddi_fm_fini() in
1064 * scsi_hba_detach().
1066 * NOTE: if ddi_fm_init fails to establish handle, SKIP cleanup.
1068 if (DEVI(self
)->devi_fmhdl
)
1069 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_FM
;
1072 /* If SCSA responsible for for minor nodes, create :devctl minor. */
1073 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1074 scsi_hba_open
) ? 1 : 0;
1075 if (scsa_minor
&& ((ddi_create_minor_node(self
, "devctl", S_IFCHR
,
1076 INST2DEVCTL(ddi_get_instance(self
)), DDI_NT_SCSI_NEXUS
, 0) !=
1078 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1079 "can't create :devctl minor node"));
1083 return (DDI_SUCCESS
);
1085 fail
: scsa_nexus_teardown(self
, tran
);
1086 return (DDI_FAILURE
);
1090 * Common tran teardown code: used by iport_postdetach_tran_scsi_device() on a
1091 * SCSA HBA iport node and (possibly) by scsi_hba_detach() on SCSA HBA node
1092 * (and for failure cleanup). Undo scsa_tran_setup in reverse order.
1094 * NOTE: Since we are in the Solaris IO framework, we can depend on
1095 * undocumented cleanup operations performed by other parts of the framework:
1096 * like detach_node() calling ddi_prop_remove_all() and
1097 * ddi_remove_minor_node(,NULL).
1100 scsa_tran_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1102 tran
->tran_iport_dip
= NULL
;
1104 /* Teardown pHCI registration */
1105 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_PHCI
) {
1106 (void) mdi_phci_unregister(self
, 0);
1107 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_PHCI
;
1112 * Common tran setup code: used by iport_preattach_tran_scsi_device() on a
1113 * SCSA HBA iport node and (possibly) by scsi_hba_attach_setup() on SCSA HBA
1117 scsa_tran_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1121 char *scsi_binding_set
;
1122 static const char *interconnect
[] = INTERCONNECT_TYPE_ASCII
;
1124 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1126 /* If SCSA responsible for for minor nodes, create ":scsi" */
1127 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1128 scsi_hba_open
) ? 1 : 0;
1129 if (scsa_minor
&& (ddi_create_minor_node(self
, "scsi", S_IFCHR
,
1130 INST2SCSI(ddi_get_instance(self
)),
1131 DDI_NT_SCSI_ATTACHMENT_POINT
, 0) != DDI_SUCCESS
)) {
1132 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1133 "can't create :scsi minor node"));
1138 * If the property does not already exist on self then see if we can
1139 * pull it from further up the tree and define it on self. If the
1140 * property does not exist above (including options.conf) then use the
1141 * default value specified (global variable). We pull things down from
1142 * above for faster "DDI_PROP_NOTPROM | DDI_PROP_DONTPASS" runtime
1145 * Future: Should we avoid creating properties when value == global?
1147 #define CONFIG_INT_PROP(s, p, dv) { \
1148 if ((ddi_prop_exists(DDI_DEV_T_ANY, s, \
1149 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, p) == 0) && \
1150 (ndi_prop_update_int(DDI_DEV_T_NONE, s, p, \
1151 ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(s), \
1152 DDI_PROP_NOTPROM, p, dv)) != DDI_PROP_SUCCESS)) \
1153 SCSI_HBA_LOG((_LOG(WARN), NULL, s, \
1154 "can't create property '%s'", p)); \
1157 /* Decorate with scsi configuration properties */
1158 CONFIG_INT_PROP(self
, "scsi-enumeration", scsi_enumeration
);
1159 CONFIG_INT_PROP(self
, "scsi-options", scsi_options
);
1160 CONFIG_INT_PROP(self
, "scsi-reset-delay", scsi_reset_delay
);
1161 CONFIG_INT_PROP(self
, "scsi-watchdog-tick", scsi_watchdog_tick
);
1162 CONFIG_INT_PROP(self
, "scsi-selection-timeout", scsi_selection_timeout
);
1163 CONFIG_INT_PROP(self
, "scsi-tag-age-limit", scsi_tag_age_limit
);
1166 * Pull down the scsi-initiator-id from further up the tree, or as
1167 * defined by OBP. Place on node for faster access. NOTE: there is
1168 * some confusion about what the name of the property should be.
1170 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0, "initiator-id", -1);
1172 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0,
1173 "scsi-initiator-id", -1);
1175 CONFIG_INT_PROP(self
, "scsi-initiator-id", id
);
1178 * If we are responsible for tran allocation, establish
1179 * 'initiator-interconnect-type'.
1181 if ((tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
) &&
1182 (tran
->tran_interconnect_type
> 0) &&
1183 (tran
->tran_interconnect_type
< INTERCONNECT_MAX
)) {
1184 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1185 "initiator-interconnect-type",
1186 (char *)interconnect
[tran
->tran_interconnect_type
])
1187 != DDI_PROP_SUCCESS
) {
1188 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1189 "failed to establish "
1190 "'initiator-interconnect-type'"));
1196 * The 'scsi-binding-set' property can be defined in driver.conf
1197 * files of legacy drivers on an as-needed basis. If 'scsi-binding-set'
1198 * is not driver.conf defined, and the HBA is not implementing its own
1199 * private bus_config, we define scsi-binding-set to the default
1200 * 'spi' legacy value.
1202 * NOTE: This default 'spi' value will be deleted if an HBA driver
1203 * ends up using the scsi_hba_tgtmap_create() enumeration services.
1205 * NOTE: If we were ever to decide to derive 'scsi-binding-set' from
1206 * the IEEE-1275 'device_type' property then this is where that code
1207 * should go - there is not enough consistency in 'device_type' to do
1208 * this correctly at this point in time.
1210 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
1211 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
1212 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
1213 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1214 "external 'scsi-binding-set' \"%s\"", scsi_binding_set
));
1215 ddi_prop_free(scsi_binding_set
);
1216 } else if (scsi_binding_set_spi
&&
1217 ((tran
->tran_bus_config
== NULL
) ||
1218 (tran
->tran_bus_config
== scsi_hba_bus_config_spi
))) {
1219 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1220 "scsi-binding-set", scsi_binding_set_spi
) !=
1222 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1223 "failed to establish 'scsi_binding_set' default"));
1226 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1227 "default 'scsi-binding-set' \"%s\"", scsi_binding_set_spi
));
1229 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1230 "no 'scsi-binding-set'"));
1233 * If SCSI_HBA_TRAN_PHCI is set, take care of pHCI registration of the
1236 if ((tran
->tran_hba_flags
& SCSI_HBA_TRAN_PHCI
) &&
1237 (mdi_phci_register(MDI_HCI_CLASS_SCSI
, self
, 0) == MDI_SUCCESS
))
1238 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_PHCI
;
1240 /* NOTE: tran_hba_dip is for DMA operation at the HBA node level */
1241 tran
->tran_iport_dip
= self
; /* for iport association */
1242 return (DDI_SUCCESS
);
1244 fail
: scsa_tran_teardown(self
, tran
);
1245 return (DDI_FAILURE
);
1249 * Called by a SCSA HBA driver to attach an instance of the driver to
1250 * SCSA HBA node enumerated by PCI.
1253 scsi_hba_attach_setup(
1255 ddi_dma_attr_t
*hba_dma_attr
,
1256 scsi_hba_tran_t
*tran
,
1260 char cache_name
[96];
1262 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1265 * Verify that we are a driver so other code does not need to
1266 * check for NULL ddi_get_driver() result.
1268 if (ddi_get_driver(self
) == NULL
)
1269 return (DDI_FAILURE
);
1272 * Verify that we are called on a SCSA HBA node (function enumerated
1273 * by PCI), not on an iport node.
1275 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1276 if (scsi_hba_iport_unit_address(self
))
1277 return (DDI_FAILURE
); /* self can't be an iport */
1279 /* Caller must provide the tran. */
1282 return (DDI_FAILURE
);
1285 * Verify correct scsi_hba_tran_t form:
1287 * o Both or none of tran_get_name/tran_get_addr.
1288 * NOTE: Older SCSA HBA drivers for SCSI transports with addressing
1289 * that did not fit the SPI "struct scsi_address" model were required
1290 * to implement tran_get_name and tran_get_addr. This is no longer
1291 * true - modern transport drivers should now use common SCSA
1292 * enumeration services. The SCSA enumeration code will represent
1293 * the unit-address using well-known address properties
1294 * (SCSI_ADDR_PROP_TARGET_PORT, SCSI_ADDR_PROP_LUN64) during
1295 * devinfo/pathinfo node creation. The HBA driver can obtain values
1296 * using scsi_device_prop_lookup_*() from its tran_tgt_init(9E).
1299 if ((tran
->tran_get_name
== NULL
) ^ (tran
->tran_get_bus_addr
== NULL
)) {
1300 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1301 "should support both or neither: "
1302 "tran_get_name, tran_get_bus_addr"));
1303 return (DDI_FAILURE
);
1307 * Establish the devinfo context of this tran structure, preserving
1308 * knowledge of how the tran was allocated.
1310 tran
->tran_hba_dip
= self
; /* for DMA */
1311 tran
->tran_hba_flags
= (flags
& ~SCSI_HBA_SCSA_TA
) |
1312 (tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
);
1314 /* Establish flavor of transport (and ddi_get_driver_private()) */
1315 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
1318 * Note: We only need dma_attr_minxfer and dma_attr_burstsizes
1319 * from the DMA attributes. scsi_hba_attach(9f) only guarantees
1320 * that these two fields are initialized properly. If this
1321 * changes, be sure to revisit the implementation of
1322 * scsi_hba_attach(9F).
1324 (void) memcpy(&tran
->tran_dma_attr
, hba_dma_attr
,
1325 sizeof (ddi_dma_attr_t
));
1327 /* Create tran_setup_pkt(9E) kmem_cache. */
1328 if (tran
->tran_setup_pkt
) {
1329 ASSERT(tran
->tran_init_pkt
== NULL
);
1330 ASSERT(tran
->tran_destroy_pkt
== NULL
);
1331 if (tran
->tran_init_pkt
|| tran
->tran_destroy_pkt
)
1334 tran
->tran_init_pkt
= scsi_init_cache_pkt
;
1335 tran
->tran_destroy_pkt
= scsi_free_cache_pkt
;
1336 tran
->tran_sync_pkt
= scsi_sync_cache_pkt
;
1337 tran
->tran_dmafree
= scsi_cache_dmafree
;
1339 len
= sizeof (struct scsi_pkt_cache_wrapper
);
1340 len
+= ROUNDUP(tran
->tran_hba_len
);
1341 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
1342 len
+= ROUNDUP(DEFAULT_CDBLEN
);
1343 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
1344 len
+= ROUNDUP(DEFAULT_SCBLEN
);
1346 (void) snprintf(cache_name
, sizeof (cache_name
),
1347 "pkt_cache_%s_%d", ddi_driver_name(self
),
1348 ddi_get_instance(self
));
1350 tran
->tran_pkt_cache_ptr
= kmem_cache_create(
1351 cache_name
, len
, 8, scsi_hba_pkt_constructor
,
1352 scsi_hba_pkt_destructor
, NULL
, tran
, NULL
, 0);
1355 /* Perform node setup independent of initiator role */
1356 if (scsa_nexus_setup(self
, tran
) != DDI_SUCCESS
)
1360 * The SCSI_HBA_HBA flag is passed to scsi_hba_attach_setup when the
1361 * HBA driver knows that *all* children of the SCSA HBA node will be
1362 * 'iports'. If the SCSA HBA node can have iport children and also
1363 * function as an initiator for xxx_device children then it should
1364 * not specify SCSI_HBA_HBA in its scsi_hba_attach_setup call. An
1365 * HBA driver that does not manage iports should not set SCSA_HBA_HBA.
1367 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
1369 * Set the 'ddi-config-driver-node' property on the nexus
1370 * node that notify attach_driver_nodes() to configure all
1371 * immediate children so that nodes which bind to the
1372 * same driver as parent are able to be added into per-driver
1375 if (ndi_prop_create_boolean(DDI_DEV_T_NONE
,
1376 self
, "ddi-config-driver-node") != DDI_PROP_SUCCESS
)
1379 if (scsa_tran_setup(self
, tran
) != DDI_SUCCESS
)
1383 return (DDI_SUCCESS
);
1385 fail
: (void) scsi_hba_detach(self
);
1386 return (DDI_FAILURE
);
1390 * Called by an HBA to detach an instance of the driver. This may be called
1391 * for SCSA HBA nodes and for SCSA iport nodes.
1394 scsi_hba_detach(dev_info_t
*self
)
1396 scsi_hba_tran_t
*tran
;
1398 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1399 if (scsi_hba_iport_unit_address(self
))
1400 return (DDI_FAILURE
); /* self can't be an iport */
1402 /* Check all error return conditions upfront */
1403 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1406 return (DDI_FAILURE
);
1408 ASSERT(tran
->tran_open_flag
== 0);
1409 if (tran
->tran_open_flag
)
1410 return (DDI_FAILURE
);
1412 if (!(tran
->tran_hba_flags
& SCSI_HBA_HBA
))
1413 scsa_tran_teardown(self
, tran
);
1414 scsa_nexus_teardown(self
, tran
);
1416 /* Teardown tran_setup_pkt(9E) kmem_cache. */
1417 if (tran
->tran_pkt_cache_ptr
) {
1418 kmem_cache_destroy(tran
->tran_pkt_cache_ptr
);
1419 tran
->tran_pkt_cache_ptr
= NULL
;
1422 (void) memset(&tran
->tran_dma_attr
, 0, sizeof (ddi_dma_attr_t
));
1424 /* Teardown flavor of transport (and ddi_get_driver_private()) */
1425 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
1427 tran
->tran_hba_dip
= NULL
;
1429 return (DDI_SUCCESS
);
1434 * Called by an HBA from _fini()
1437 scsi_hba_fini(struct modlinkage
*modlp
)
1439 struct dev_ops
*hba_dev_ops
;
1441 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
1443 /* Get the devops structure of this module and clear bus_ops vector. */
1444 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
1446 if (hba_dev_ops
->devo_cb_ops
== &scsi_hba_cbops
)
1447 hba_dev_ops
->devo_cb_ops
= NULL
;
1449 if (hba_dev_ops
->devo_getinfo
== scsi_hba_info
)
1450 hba_dev_ops
->devo_getinfo
= NULL
;
1452 hba_dev_ops
->devo_bus_ops
= (struct bus_ops
*)NULL
;
1456 * SAS specific functions
1459 smp_hba_tran_alloc(dev_info_t
*self
)
1461 /* allocate SCSA flavors for self */
1462 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
1463 return (kmem_zalloc(sizeof (smp_hba_tran_t
), KM_SLEEP
));
1467 smp_hba_tran_free(smp_hba_tran_t
*tran
)
1469 kmem_free(tran
, sizeof (smp_hba_tran_t
));
1473 smp_hba_attach_setup(
1475 smp_hba_tran_t
*tran
)
1477 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1478 if (scsi_hba_iport_unit_address(self
))
1479 return (DDI_FAILURE
); /* self can't be an iport */
1482 * The owner of the this devinfo_t was responsible
1483 * for informing the framework already about
1484 * additional flavors.
1486 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, tran
);
1487 return (DDI_SUCCESS
);
1491 smp_hba_detach(dev_info_t
*self
)
1493 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1494 if (scsi_hba_iport_unit_address(self
))
1495 return (DDI_FAILURE
); /* self can't be an iport */
1497 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, NULL
);
1498 return (DDI_SUCCESS
);
1502 * SMP child flavored functions
1505 smp_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1510 /* limit ndi_devi_findchild_by_callback to expected flavor */
1511 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1512 return (DDI_FAILURE
);
1514 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1515 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1516 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1517 (void) snprintf(addr
, maxlen
, "%s", tport
);
1518 ddi_prop_free(tport
);
1519 return (DDI_SUCCESS
);
1523 * NOTE: the following code should be deleted when mpt is changed to
1524 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1526 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1527 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1528 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1529 (void) snprintf(addr
, maxlen
, "w%s", wwn
);
1531 return (DDI_SUCCESS
);
1533 return (DDI_FAILURE
);
1537 smp_busctl_reportdev(dev_info_t
*child
)
1539 dev_info_t
*self
= ddi_get_parent(child
);
1543 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1544 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1545 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1546 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: target-port %s",
1547 ddi_driver_name(child
), ddi_get_instance(child
),
1548 ddi_driver_name(self
), ddi_get_instance(self
), tport
));
1549 ddi_prop_free(tport
);
1550 return (DDI_SUCCESS
);
1554 * NOTE: the following code should be deleted when mpt is changed to
1555 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1557 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1558 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1559 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1560 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: wwn %s",
1561 ddi_driver_name(child
), ddi_get_instance(child
),
1562 ddi_driver_name(self
), ddi_get_instance(self
), wwn
));
1564 return (DDI_SUCCESS
);
1566 return (DDI_FAILURE
);
1570 smp_busctl_initchild(dev_info_t
*child
)
1572 dev_info_t
*self
= ddi_get_parent(child
);
1573 smp_hba_tran_t
*tran
;
1575 char addr
[SCSI_MAXNAMELEN
];
1576 struct smp_device
*smp_sd
;
1579 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1582 return (DDI_FAILURE
);
1584 if (smp_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
1585 return (DDI_NOT_WELL_FORMED
);
1586 if (scsi_wwnstr_to_wwn(addr
, &wwn
))
1587 return (DDI_NOT_WELL_FORMED
);
1589 /* Prevent duplicate nodes. */
1590 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
1593 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SMP
);
1594 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SMP
) {
1595 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1596 "init failed: %s@%s: not SMP flavored",
1597 ddi_node_name(child
), addr
));
1598 return (DDI_FAILURE
);
1601 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1602 "init failed: %s@%s: detected duplicate %p",
1603 ddi_node_name(child
), addr
, (void *)dup
));
1604 return (DDI_FAILURE
);
1609 /* set the node @addr string */
1610 ddi_set_name_addr(child
, addr
);
1612 /* Allocate and initialize smp_device. */
1613 smp_sd
= kmem_zalloc(sizeof (struct smp_device
), KM_SLEEP
);
1614 smp_sd
->smp_sd_dev
= child
;
1615 smp_sd
->smp_sd_address
.smp_a_hba_tran
= tran
;
1616 bcopy(&wwn
, smp_sd
->smp_sd_address
.smp_a_wwn
, SAS_WWN_BYTE_SIZE
);
1618 ddi_set_driver_private(child
, smp_sd
);
1620 if (tran
->smp_tran_init
&& ((*tran
->smp_tran_init
)(self
, child
,
1621 tran
, smp_sd
) != DDI_SUCCESS
)) {
1622 kmem_free(smp_sd
, sizeof (struct smp_device
));
1623 scsi_enumeration_failed(child
, -1, NULL
, "smp_tran_init");
1624 ddi_set_driver_private(child
, NULL
);
1625 ddi_set_name_addr(child
, NULL
);
1626 return (DDI_FAILURE
);
1629 return (DDI_SUCCESS
);
1634 smp_busctl_uninitchild(dev_info_t
*child
)
1636 dev_info_t
*self
= ddi_get_parent(child
);
1637 struct smp_device
*smp_sd
= ddi_get_driver_private(child
);
1638 smp_hba_tran_t
*tran
;
1640 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1641 ASSERT(smp_sd
&& tran
);
1642 if ((smp_sd
== NULL
) || (tran
== NULL
))
1643 return (DDI_FAILURE
);
1645 if (tran
->smp_tran_free
)
1646 (*tran
->smp_tran_free
) (self
, child
, tran
, smp_sd
);
1648 kmem_free(smp_sd
, sizeof (*smp_sd
));
1649 ddi_set_driver_private(child
, NULL
);
1650 ddi_set_name_addr(child
, NULL
);
1651 return (DDI_SUCCESS
);
1654 /* Find an "smp" child at the specified address. */
1656 smp_findchild(dev_info_t
*self
, char *addr
)
1660 /* Search "smp" devinfo child at specified address. */
1661 ASSERT(self
&& DEVI_BUSY_OWNED(self
) && addr
);
1662 for (child
= ddi_get_child(self
); child
;
1663 child
= ddi_get_next_sibling(child
)) {
1664 /* skip non-"smp" nodes */
1665 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1668 /* Attempt initchild to establish unit-address */
1669 if (i_ddi_node_state(child
) < DS_INITIALIZED
)
1670 (void) ddi_initchild(self
, child
);
1672 /* Verify state and non-NULL unit-address. */
1673 if ((i_ddi_node_state(child
) < DS_INITIALIZED
) ||
1674 (ddi_get_name_addr(child
) == NULL
))
1677 /* Return "smp" child if unit-address matches. */
1678 if (strcmp(ddi_get_name_addr(child
), addr
) == 0)
1685 * Search for "smp" child of self at the specified address. If found, online
1686 * and return with a hold. Unlike general SCSI configuration, we can assume
1687 * the the device is actually there when we are called (i.e., device is
1688 * created by hotplug, not by bus_config).
1691 smp_hba_bus_config(dev_info_t
*self
, char *addr
, dev_info_t
**childp
)
1696 ASSERT(self
&& addr
&& childp
);
1699 /* Search for "smp" child. */
1700 scsi_hba_devi_enter(self
, &circ
);
1701 if ((child
= smp_findchild(self
, addr
)) == NULL
) {
1702 scsi_hba_devi_exit(self
, circ
);
1703 return (NDI_FAILURE
);
1706 /* Attempt online. */
1707 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
1708 scsi_hba_devi_exit(self
, circ
);
1709 return (NDI_FAILURE
);
1712 /* On success, return with active hold. */
1713 ndi_hold_devi(child
);
1714 scsi_hba_devi_exit(self
, circ
);
1716 return (NDI_SUCCESS
);
1721 /* Create "smp" child devinfo node at specified unit-address. */
1723 smp_hba_bus_config_taddr(dev_info_t
*self
, char *addr
)
1729 * NOTE: If we ever uses a generic node name (.vs. a driver name)
1730 * or define a 'compatible' property, this code will need to use
1731 * a 'probe' node (ala scsi_device support) to obtain identity
1732 * information from the device.
1735 /* Search for "smp" child. */
1736 scsi_hba_devi_enter(self
, &circ
);
1737 child
= smp_findchild(self
, addr
);
1739 /* Child exists, note if this was a new reinsert. */
1740 if (ndi_devi_device_insert(child
))
1741 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
1742 "devinfo smp@%s device_reinsert", addr
));
1744 scsi_hba_devi_exit(self
, circ
);
1745 return (NDI_SUCCESS
);
1748 /* Allocate "smp" child devinfo node and establish flavor of child. */
1749 ndi_devi_alloc_sleep(self
, "smp", DEVI_SID_HP_NODEID
, &child
);
1751 ndi_flavor_set(child
, SCSA_FLAVOR_SMP
);
1753 /* Add unit-address property to child. */
1754 if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
1755 SCSI_ADDR_PROP_TARGET_PORT
, addr
) != DDI_PROP_SUCCESS
) {
1756 (void) ndi_devi_free(child
);
1757 scsi_hba_devi_exit(self
, circ
);
1758 return (NDI_FAILURE
);
1761 /* Attempt to online the new "smp" node. */
1762 (void) ndi_devi_online(child
, 0);
1764 scsi_hba_devi_exit(self
, circ
);
1765 return (NDI_SUCCESS
);
1769 * Wrapper to scsi_ua_get which takes a devinfo argument instead of a
1770 * scsi_device structure.
1773 scsi_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1775 struct scsi_device
*sd
;
1777 /* limit ndi_devi_findchild_by_callback to expected flavor */
1778 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
)
1779 return (DDI_FAILURE
);
1781 /* nodes are named by tran_get_name or default "tgt,lun" */
1782 sd
= ddi_get_driver_private(child
);
1783 if (sd
&& (scsi_ua_get(sd
, addr
, maxlen
) == 1))
1784 return (DDI_SUCCESS
);
1786 return (DDI_FAILURE
);
1790 scsi_busctl_reportdev(dev_info_t
*child
)
1792 dev_info_t
*self
= ddi_get_parent(child
);
1793 struct scsi_device
*sd
= ddi_get_driver_private(child
);
1794 scsi_hba_tran_t
*tran
;
1795 char ua
[SCSI_MAXNAMELEN
];
1796 char ra
[SCSI_MAXNAMELEN
];
1798 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, child
, __func__
));
1800 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1802 if ((tran
== NULL
) || (sd
== NULL
))
1803 return (DDI_FAILURE
);
1805 /* get the unit_address and bus_addr information */
1806 if ((scsi_ua_get(sd
, ua
, sizeof (ua
)) == 0) ||
1807 (scsi_ua_get_reportdev(sd
, ra
, sizeof (ra
)) == 0)) {
1808 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
, "REPORTDEV failure"));
1809 return (DDI_FAILURE
);
1812 if (tran
->tran_get_name
== NULL
)
1813 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s",
1814 ddi_driver_name(child
), ddi_get_instance(child
),
1815 ddi_driver_name(self
), ddi_get_instance(self
), ra
));
1817 SCSI_HBA_LOG((_LOG_NF(CONT
),
1818 "?%s%d at %s%d: unit-address %s: %s",
1819 ddi_driver_name(child
), ddi_get_instance(child
),
1820 ddi_driver_name(self
), ddi_get_instance(self
), ua
, ra
));
1822 SCSI_HBA_LOG((_LOG_NF(CONT
),
1823 "?%s%d at %s%d: unit-address %s",
1824 ddi_driver_name(child
), ddi_get_instance(child
),
1825 ddi_driver_name(self
), ddi_get_instance(self
), ua
));
1827 return (DDI_SUCCESS
);
1832 * scsi_busctl_initchild is called to initialize the SCSA transport for
1833 * communication with a particular child scsi target device. Successful
1834 * initialization requires properties on the node which describe the address
1835 * of the target device. If the address of the target device can't be
1836 * determined from properties then DDI_NOT_WELL_FORMED is returned. Nodes that
1837 * are DDI_NOT_WELL_FORMED are considered an implementation artifact and
1838 * are hidden from devinfo snapshots by calling ndi_devi_set_hidden().
1839 * The child may be one of the following types of devinfo nodes:
1842 * OBP does not enumerate target devices attached a SCSI bus. These
1843 * template/stub/wild-card nodes are a legacy artifact for support of old
1844 * driver loading methods. Since they have no properties,
1845 * DDI_NOT_WELL_FORMED will be returned.
1848 * The node may be either a:
1849 * o probe/barrier SID node
1850 * o a dynamic SID target node
1852 * driver.conf node: The situation for this nexus is different than most.
1853 * Typically a driver.conf node definition is used to either define a
1854 * new child devinfo node or to further decorate (via merge) a SID
1855 * child with properties. In our case we use the nodes for *both*
1858 * In both the SID node and driver.conf node cases we must form the nodes
1859 * "@addr" from the well-known scsi(9P) device unit-address properties on
1862 * For HBA drivers that implement the deprecated tran_get_name interface,
1863 * "@addr" construction involves having that driver interpret properties via
1864 * scsi_busctl_ua -> scsi_ua_get -> tran_get_name: there is no
1865 * requirement for the property names to be well-known.
1867 * NOTE: We don't currently support "merge". When this support is added a
1868 * specific property, like "unit-address", should *always* identify a
1869 * driver.conf node that needs to be merged into a specific SID node. When
1870 * enumeration is enabled, a .conf node without the "unit-address" property
1871 * should be ignored. The best way to establish the "unit-address" property
1872 * would be to have the system assign parent= and unit-address= from an
1873 * instance=# driver.conf entry (by using the instance tree).
1876 scsi_busctl_initchild(dev_info_t
*child
)
1878 dev_info_t
*self
= ddi_get_parent(child
);
1880 scsi_hba_tran_t
*tran
;
1881 struct scsi_device
*sd
;
1882 scsi_hba_tran_t
*tran_clone
;
1887 int err
= DDI_FAILURE
;
1888 char addr
[SCSI_MAXNAMELEN
];
1890 ASSERT(DEVI_BUSY_OWNED(self
));
1891 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init begin"));
1894 * For a driver like fp with multiple upper-layer-protocols
1895 * it is possible for scsi_hba_init in _init to plumb SCSA
1896 * and have the load of fcp (which does scsi_hba_attach_setup)
1897 * to fail. In this case we may get here with a NULL hba.
1899 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1901 return (DDI_NOT_WELL_FORMED
);
1904 * OBP may create template/stub/wild-card nodes for legacy driver
1905 * loading methods. These nodes have no properties, so we lack the
1906 * addressing properties to initchild them. Hide the node and return
1907 * DDI_NOT_WELL_FORMED.
1909 * Future: define/use a ndi_devi_has_properties(dip) type interface.
1911 * NOTE: It would be nice if we could delete these ill formed nodes by
1912 * implementing a DDI_NOT_WELL_FORMED_DELETE return code. This can't
1913 * be done until leadville debug code removes its dependencies
1914 * on the devinfo still being present after a failed ndi_devi_online.
1916 if ((DEVI(child
)->devi_hw_prop_ptr
== NULL
) &&
1917 (DEVI(child
)->devi_drv_prop_ptr
== NULL
) &&
1918 (DEVI(child
)->devi_sys_prop_ptr
== NULL
)) {
1919 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1920 "init failed: no properties"));
1921 ndi_devi_set_hidden(child
);
1922 return (DDI_NOT_WELL_FORMED
);
1925 /* get legacy SPI addressing properties */
1926 if ((tgt
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1927 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1928 SCSI_ADDR_PROP_TARGET
, -1)) == -1) {
1931 * A driver.conf node for merging always has a target= property,
1932 * even if it is just a dummy that does not contain the real
1933 * target address. However drivers that register devids may
1934 * create stub driver.conf nodes without a target= property so
1935 * that pathological devid resolution works. Hide the stub
1936 * node and return DDI_NOT_WELL_FORMED.
1938 if (!scsi_hba_dev_is_sid(child
)) {
1939 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1940 "init failed: stub .conf node"));
1941 ndi_devi_set_hidden(child
);
1942 return (DDI_NOT_WELL_FORMED
);
1945 lun
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1946 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_LUN
, 0);
1947 sfunc
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1948 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_SFUNC
, -1);
1951 * The scsi_address structure may not specify all the addressing
1952 * information. For an old HBA that doesn't support tran_get_name
1953 * (most pre-SCSI-3 HBAs) the scsi_address structure is still used,
1954 * so the target property must exist and the LUN must be < 256.
1956 if ((tran
->tran_get_name
== NULL
) &&
1957 ((tgt
>= USHRT_MAX
) || (lun
>= 256))) {
1958 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1959 "init failed: illegal/missing properties"));
1960 ndi_devi_set_hidden(child
);
1961 return (DDI_NOT_WELL_FORMED
);
1965 * We need to initialize a fair amount of our environment to invoke
1966 * tran_get_name (via scsi_busctl_ua and scsi_ua_get) to
1967 * produce the "@addr" name from addressing properties. Allocate and
1968 * initialize scsi device structure.
1970 sd
= kmem_zalloc(sizeof (struct scsi_device
), KM_SLEEP
);
1971 mutex_init(&sd
->sd_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
1973 sd
->sd_pathinfo
= NULL
;
1974 sd
->sd_uninit_prevent
= 0;
1975 ddi_set_driver_private(child
, sd
);
1977 if (tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
) {
1979 * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
1980 * scsi_device in the scsi_address structure. This allows an
1981 * HBA driver to find its per-scsi_device private data
1982 * (accessible to the HBA given just the scsi_address by using
1983 * scsi_address_device(9F)/scsi_device_hba_private_get(9F)).
1985 sd
->sd_address
.a
.a_sd
= sd
;
1989 * Initialize the scsi_address so that a SCSI-2 target driver
1990 * talking to a SCSI-2 device on a SCSI-3 bus (spi) continues
1991 * to work. We skew the secondary function value so that we
1992 * can tell from the address structure if we are processing
1993 * a secondary function request.
1995 sd
->sd_address
.a_target
= (ushort_t
)tgt
;
1996 sd
->sd_address
.a_lun
= (uchar_t
)lun
;
1998 sd
->sd_address
.a_sublun
= (uchar_t
)0;
2000 sd
->sd_address
.a_sublun
= (uchar_t
)sfunc
+ 1;
2003 * NOTE: Don't limit LUNs to scsi_options value because a
2004 * scsi_device discovered via SPI dynamic enumeration might
2005 * still support SCMD_REPORT_LUNS.
2009 * Deprecated: Use SCSI_HBA_ADDR_COMPLEX:
2010 * Clone transport structure if requested. Cloning allows
2011 * an HBA to maintain target-specific information if
2012 * necessary, such as target addressing information that
2013 * does not adhere to the scsi_address structure format.
2015 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
2016 tran_clone
= kmem_alloc(
2017 sizeof (scsi_hba_tran_t
), KM_SLEEP
);
2018 bcopy((caddr_t
)tran
,
2019 (caddr_t
)tran_clone
, sizeof (scsi_hba_tran_t
));
2024 ASSERT(tran
->tran_sd
== NULL
);
2028 /* establish scsi_address pointer to the HBA's tran structure */
2029 sd
->sd_address
.a_hba_tran
= tran
;
2032 * This is a grotty hack that allows direct-access (non-scsa) drivers
2033 * (like chs, ata, and mlx which all make cmdk children) to put its
2034 * own vector in the 'a_hba_tran' field. When all the drivers that do
2035 * this are fixed, please remove this hack.
2037 * NOTE: This hack is also shows up in the DEVP_TO_TRAN implementation
2038 * in scsi_confsubr.c.
2040 sd
->sd_tran_safe
= tran
;
2043 * If the class property is not already established, set it to "scsi".
2044 * This is done so that parent= driver.conf nodes have class.
2046 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2047 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "class",
2048 &class) == DDI_PROP_SUCCESS
) {
2049 ddi_prop_free(class);
2050 } else if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
2051 "class", "scsi") != DDI_PROP_SUCCESS
) {
2052 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: class"));
2053 ndi_devi_set_hidden(child
);
2054 err
= DDI_NOT_WELL_FORMED
;
2058 /* Establish the @addr name of the child. */
2060 if (scsi_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
) {
2062 * Some driver.conf files add bogus target properties (relative
2063 * to their nexus representation of target) to their stub
2064 * nodes, causing the check above to not filter them.
2066 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
2067 "init failed: scsi_busctl_ua call"));
2068 ndi_devi_set_hidden(child
);
2069 err
= DDI_NOT_WELL_FORMED
;
2072 if (*addr
== '\0') {
2073 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: ua"));
2074 ndi_devi_set_hidden(child
);
2075 err
= DDI_NOT_WELL_FORMED
;
2079 /* Prevent duplicate nodes. */
2080 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2083 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SCSI_DEVICE
);
2084 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SCSI_DEVICE
) {
2085 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2086 "init failed: %s@%s: not SCSI_DEVICE flavored",
2087 ddi_node_name(child
), addr
));
2091 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2092 "init failed: %s@%s: detected duplicate %p",
2093 ddi_node_name(child
), addr
, (void *)dup
));
2098 /* set the node @addr string */
2099 ddi_set_name_addr(child
, addr
);
2101 /* call HBA's target init entry point if it exists */
2102 if (tran
->tran_tgt_init
!= NULL
) {
2103 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init tran_tgt_init"));
2104 sd
->sd_tran_tgt_free_done
= 0;
2105 if ((*tran
->tran_tgt_init
)
2106 (self
, child
, tran
, sd
) != DDI_SUCCESS
) {
2107 scsi_enumeration_failed(child
, -1, NULL
,
2113 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "init successful"));
2114 return (DDI_SUCCESS
);
2118 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2119 mutex_destroy(&sd
->sd_mutex
);
2120 kmem_free(sd
, sizeof (*sd
));
2121 ddi_set_driver_private(child
, NULL
);
2122 ddi_set_name_addr(child
, NULL
);
2124 return (err
); /* remove the node */
2128 scsi_busctl_uninitchild(dev_info_t
*child
)
2130 dev_info_t
*self
= ddi_get_parent(child
);
2131 struct scsi_device
*sd
= ddi_get_driver_private(child
);
2132 scsi_hba_tran_t
*tran
;
2133 scsi_hba_tran_t
*tran_clone
;
2135 ASSERT(DEVI_BUSY_OWNED(self
));
2137 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
2139 if ((tran
== NULL
) || (sd
== NULL
))
2140 return (DDI_FAILURE
);
2143 * We use sd_uninit_prevent to avoid uninitializing barrier/probe
2144 * nodes that are still in use. Since barrier/probe nodes are not
2145 * attached we can't prevent their state demotion via ndi_hold_devi.
2147 if (sd
->sd_uninit_prevent
) {
2148 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "uninit prevented"));
2149 return (DDI_FAILURE
);
2153 * Don't uninitialize a client node if it still has paths.
2155 if (MDI_CLIENT(child
) && mdi_client_get_path_count(child
)) {
2156 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
2157 "uninit prevented, client has paths"));
2158 return (DDI_FAILURE
);
2161 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit begin"));
2163 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
2164 tran_clone
= sd
->sd_address
.a_hba_tran
;
2166 /* ... grotty hack, involving sd_tran_safe, continued. */
2167 if (tran_clone
!= sd
->sd_tran_safe
) {
2168 tran_clone
= sd
->sd_tran_safe
;
2171 * Complain so things get fixed and hack can, at
2172 * some point in time, be removed.
2174 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2175 "'%s' is corrupting a_hba_tran", sd
->sd_dev
?
2176 ddi_driver_name(sd
->sd_dev
) : "unknown_driver"));
2180 ASSERT(tran_clone
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
);
2181 ASSERT(tran_clone
->tran_sd
== sd
);
2185 ASSERT(tran
->tran_sd
== NULL
);
2189 * To simplify host adapter drivers we guarantee that multiple
2190 * tran_tgt_init(9E) calls of the same unit address are never
2191 * active at the same time. This requires that we always call
2192 * tran_tgt_free on probe/barrier nodes directly prior to
2195 * NOTE: To correctly support SCSI_HBA_TRAN_CLONE, we must use
2196 * the (possibly cloned) hba_tran pointer from the scsi_device
2197 * instead of hba_tran.
2199 if (tran
->tran_tgt_free
) {
2200 if (!sd
->sd_tran_tgt_free_done
) {
2201 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2202 "uninit tran_tgt_free"));
2203 (*tran
->tran_tgt_free
) (self
, child
, tran
, sd
);
2204 sd
->sd_tran_tgt_free_done
= 1;
2206 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2207 "uninit tran_tgt_free already done"));
2212 * If a inquiry data is still allocated (by scsi_probe()) we
2213 * free the allocation here. This keeps scsi_inq valid for the
2214 * same duration as the corresponding inquiry properties. It
2215 * also allows a tran_tgt_init() implementation that establishes
2216 * sd_inq to deal with deallocation in its tran_tgt_free
2217 * (setting sd_inq back to NULL) without upsetting the
2218 * framework. Moving the inquiry free here also allows setting
2219 * of sd_uninit_prevent to preserve the data for lun0 based
2220 * scsi_get_device_type_scsi_options() calls.
2223 kmem_free(sd
->sd_inq
, SUN_INQSIZE
);
2224 sd
->sd_inq
= (struct scsi_inquiry
*)NULL
;
2227 mutex_destroy(&sd
->sd_mutex
);
2229 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2230 kmem_free(sd
, sizeof (*sd
));
2232 ddi_set_driver_private(child
, NULL
);
2233 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit complete"));
2234 ddi_set_name_addr(child
, NULL
);
2235 return (DDI_SUCCESS
);
2239 iport_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
2243 /* limit ndi_devi_findchild_by_callback to expected flavor */
2244 if (ndi_flavor_get(child
) != SCSA_FLAVOR_IPORT
)
2245 return (DDI_FAILURE
);
2247 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2248 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2249 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
) {
2250 return (DDI_FAILURE
);
2253 (void) snprintf(addr
, maxlen
, "%s", iport_ua
);
2254 ddi_prop_free(iport_ua
);
2255 return (DDI_SUCCESS
);
2259 iport_busctl_reportdev(dev_info_t
*child
)
2261 dev_info_t
*self
= ddi_get_parent(child
);
2263 char *initiator_port
= NULL
;
2265 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2266 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2267 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
)
2268 return (DDI_FAILURE
);
2270 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2271 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2272 SCSI_ADDR_PROP_INITIATOR_PORT
, &initiator_port
);
2274 if (initiator_port
) {
2275 SCSI_HBA_LOG((_LOG_NF(CONT
),
2276 "?%s%d at %s%d: %s %s %s %s",
2277 ddi_driver_name(child
), ddi_get_instance(child
),
2278 ddi_driver_name(self
), ddi_get_instance(self
),
2279 SCSI_ADDR_PROP_INITIATOR_PORT
, initiator_port
,
2280 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2281 ddi_prop_free(initiator_port
);
2283 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s %s",
2284 ddi_driver_name(child
), ddi_get_instance(child
),
2285 ddi_driver_name(self
), ddi_get_instance(self
),
2286 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2288 ddi_prop_free(iport_ua
);
2289 return (DDI_SUCCESS
);
2292 /* initchild SCSA iport 'child' node */
2294 iport_busctl_initchild(dev_info_t
*child
)
2296 dev_info_t
*self
= ddi_get_parent(child
);
2297 dev_info_t
*dup
= NULL
;
2298 char addr
[SCSI_MAXNAMELEN
];
2300 if (iport_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
2301 return (DDI_NOT_WELL_FORMED
);
2303 /* Prevent duplicate nodes. */
2304 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2307 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_IPORT
);
2308 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_IPORT
) {
2309 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2310 "init failed: %s@%s: not IPORT flavored",
2311 ddi_node_name(child
), addr
));
2312 return (DDI_FAILURE
);
2315 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2316 "init failed: %s@%s: detected duplicate %p",
2317 ddi_node_name(child
), addr
, (void *)dup
));
2318 return (DDI_FAILURE
);
2322 /* set the node @addr string */
2323 ddi_set_name_addr(child
, addr
);
2325 return (DDI_SUCCESS
);
2328 /* uninitchild SCSA iport 'child' node */
2330 iport_busctl_uninitchild(dev_info_t
*child
)
2332 ddi_set_name_addr(child
, NULL
);
2333 return (DDI_SUCCESS
);
2336 /* Uninitialize scsi_device flavor of transport on SCSA iport 'child' node. */
2338 iport_postdetach_tran_scsi_device(dev_info_t
*child
)
2340 scsi_hba_tran_t
*tran
;
2342 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SCSI_DEVICE
);
2346 scsa_tran_teardown(child
, tran
);
2347 scsa_nexus_teardown(child
, tran
);
2349 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
2350 scsi_hba_tran_free(tran
);
2353 /* Initialize scsi_device flavor of transport on SCSA iport 'child' node. */
2355 iport_preattach_tran_scsi_device(dev_info_t
*child
)
2357 dev_info_t
*hba
= ddi_get_parent(child
);
2358 scsi_hba_tran_t
*htran
;
2359 scsi_hba_tran_t
*tran
;
2361 /* parent HBA node scsi_device tran is required */
2362 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SCSI_DEVICE
);
2365 /* Allocate iport child's scsi_device transport vector */
2366 tran
= scsi_hba_tran_alloc(child
, SCSI_HBA_CANSLEEP
);
2369 /* Structure-copy scsi_device transport of HBA to iport. */
2373 * Reset scsi_device transport fields not shared with the
2374 * parent, and not established below.
2376 tran
->tran_open_flag
= 0;
2377 tran
->tran_hba_private
= NULL
;
2379 /* Establish the devinfo context of this tran structure. */
2380 tran
->tran_iport_dip
= child
;
2382 /* Clear SCSI_HBA_SCSA flags (except TA) */
2383 tran
->tran_hba_flags
&=
2384 ~(SCSI_HBA_SCSA_FM
| SCSI_HBA_SCSA_PHCI
); /* clear parent state */
2385 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
; /* always TA */
2386 tran
->tran_hba_flags
&= ~SCSI_HBA_HBA
; /* never HBA */
2388 /* Establish flavor of transport (and ddi_get_driver_private()) */
2389 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
2391 /* Setup iport node */
2392 if ((scsa_nexus_setup(child
, tran
) != DDI_SUCCESS
) ||
2393 (scsa_tran_setup(child
, tran
) != DDI_SUCCESS
))
2394 iport_postdetach_tran_scsi_device(child
);
2397 /* Uninitialize smp_device flavor of transport on SCSA iport 'child' node. */
2399 iport_postdetach_tran_smp_device(dev_info_t
*child
)
2401 smp_hba_tran_t
*tran
;
2403 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SMP
);
2407 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2408 smp_hba_tran_free(tran
);
2411 /* Initialize smp_device flavor of transport on SCSA iport 'child' node. */
2413 iport_preattach_tran_smp_device(dev_info_t
*child
)
2415 dev_info_t
*hba
= ddi_get_parent(child
);
2416 smp_hba_tran_t
*htran
;
2417 smp_hba_tran_t
*tran
;
2419 /* parent HBA node smp_device tran is optional */
2420 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SMP
);
2421 if (htran
== NULL
) {
2422 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2426 /* Allocate iport child's smp_device transport vector */
2427 tran
= smp_hba_tran_alloc(child
);
2429 /* Structure-copy smp_device transport of HBA to iport. */
2432 /* Establish flavor of transport */
2433 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, tran
);
2437 * Generic bus_ctl operations for SCSI HBA's,
2438 * hiding the busctl interface from the HBA.
2449 int child_flavor
= 0;
2451 ddi_dma_attr_t
*attr
;
2452 scsi_hba_tran_t
*tran
;
2453 struct attachspec
*as
;
2454 struct detachspec
*ds
;
2456 /* For some ops, child is 'arg'. */
2457 if ((op
== DDI_CTLOPS_INITCHILD
) || (op
== DDI_CTLOPS_UNINITCHILD
))
2458 child
= (dev_info_t
*)arg
;
2460 /* Determine the flavor of the child: scsi, smp, iport */
2461 child_flavor
= ndi_flavor_get(child
);
2464 case DDI_CTLOPS_INITCHILD
:
2465 switch (child_flavor
) {
2466 case SCSA_FLAVOR_SCSI_DEVICE
:
2467 return (scsi_busctl_initchild(child
));
2468 case SCSA_FLAVOR_SMP
:
2469 return (smp_busctl_initchild(child
));
2470 case SCSA_FLAVOR_IPORT
:
2471 return (iport_busctl_initchild(child
));
2473 return (DDI_FAILURE
);
2477 case DDI_CTLOPS_UNINITCHILD
:
2478 switch (child_flavor
) {
2479 case SCSA_FLAVOR_SCSI_DEVICE
:
2480 return (scsi_busctl_uninitchild(child
));
2481 case SCSA_FLAVOR_SMP
:
2482 return (smp_busctl_uninitchild(child
));
2483 case SCSA_FLAVOR_IPORT
:
2484 return (iport_busctl_uninitchild(child
));
2486 return (DDI_FAILURE
);
2490 case DDI_CTLOPS_REPORTDEV
:
2491 switch (child_flavor
) {
2492 case SCSA_FLAVOR_SCSI_DEVICE
:
2493 return (scsi_busctl_reportdev(child
));
2494 case SCSA_FLAVOR_SMP
:
2495 return (smp_busctl_reportdev(child
));
2496 case SCSA_FLAVOR_IPORT
:
2497 return (iport_busctl_reportdev(child
));
2499 return (DDI_FAILURE
);
2503 case DDI_CTLOPS_ATTACH
:
2504 as
= (struct attachspec
*)arg
;
2506 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2507 return (DDI_SUCCESS
);
2509 /* iport processing */
2510 if (as
->when
== DDI_PRE
) {
2511 /* setup pre attach(9E) */
2512 iport_preattach_tran_scsi_device(child
);
2513 iport_preattach_tran_smp_device(child
);
2514 } else if ((as
->when
== DDI_POST
) &&
2515 (as
->result
!= DDI_SUCCESS
)) {
2516 /* cleanup if attach(9E) failed */
2517 iport_postdetach_tran_scsi_device(child
);
2518 iport_postdetach_tran_smp_device(child
);
2520 return (DDI_SUCCESS
);
2522 case DDI_CTLOPS_DETACH
:
2523 ds
= (struct detachspec
*)arg
;
2525 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2526 return (DDI_SUCCESS
);
2528 /* iport processing */
2529 if ((ds
->when
== DDI_POST
) &&
2530 (ds
->result
== DDI_SUCCESS
)) {
2531 /* cleanup if detach(9E) was successful */
2532 iport_postdetach_tran_scsi_device(child
);
2533 iport_postdetach_tran_smp_device(child
);
2535 return (DDI_SUCCESS
);
2537 case DDI_CTLOPS_IOMIN
:
2538 tran
= ddi_get_driver_private(self
);
2541 return (DDI_FAILURE
);
2544 * The 'arg' value of nonzero indicates 'streaming'
2545 * mode. If in streaming mode, pick the largest
2546 * of our burstsizes available and say that that
2547 * is our minimum value (modulo what minxfer is).
2549 attr
= &tran
->tran_dma_attr
;
2550 val
= *((int *)result
);
2551 val
= maxbit(val
, attr
->dma_attr_minxfer
);
2552 *((int *)result
) = maxbit(val
, ((intptr_t)arg
?
2553 (1<<ddi_ffs(attr
->dma_attr_burstsizes
)-1) :
2554 (1<<(ddi_fls(attr
->dma_attr_burstsizes
)-1))));
2556 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2558 case DDI_CTLOPS_SIDDEV
:
2559 return (ndi_dev_is_persistent_node(child
) ?
2560 DDI_SUCCESS
: DDI_FAILURE
);
2562 case DDI_CTLOPS_POWER
:
2563 return (DDI_SUCCESS
);
2566 * These ops correspond to functions that "shouldn't" be called
2567 * by a SCSI target driver. So we whine when we're called.
2569 case DDI_CTLOPS_DMAPMAPC
:
2570 case DDI_CTLOPS_REPORTINT
:
2571 case DDI_CTLOPS_REGSIZE
:
2572 case DDI_CTLOPS_NREGS
:
2573 case DDI_CTLOPS_SLAVEONLY
:
2574 case DDI_CTLOPS_AFFINITY
:
2575 case DDI_CTLOPS_POKE
:
2576 case DDI_CTLOPS_PEEK
:
2577 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
, "invalid op (%d)", op
));
2578 return (DDI_FAILURE
);
2580 /* Everything else we pass up */
2581 case DDI_CTLOPS_PTOB
:
2582 case DDI_CTLOPS_BTOP
:
2583 case DDI_CTLOPS_BTOPR
:
2584 case DDI_CTLOPS_DVMAPAGESIZE
:
2586 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2592 * Private wrapper for scsi_pkt's allocated via scsi_hba_pkt_alloc()
2594 struct scsi_pkt_wrapper
{
2595 struct scsi_pkt scsi_pkt
;
2596 int pkt_wrapper_magic
;
2597 int pkt_wrapper_len
;
2601 _NOTE(SCHEME_PROTECTS_DATA("unique per thread", scsi_pkt_wrapper
))
2602 _NOTE(SCHEME_PROTECTS_DATA("Unshared Data", dev_ops
))
2606 * Called by an HBA to allocate a scsi_pkt
2612 struct scsi_address
*ap
,
2617 int (*callback
)(caddr_t arg
),
2620 struct scsi_pkt
*pkt
;
2621 struct scsi_pkt_wrapper
*hba_pkt
;
2623 int acmdlen
, astatuslen
, atgtlen
, ahbalen
;
2627 if (callback
!= SLEEP_FUNC
&& callback
!= NULL_FUNC
)
2628 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2629 "callback must be SLEEP_FUNC or NULL_FUNC"));
2632 * Round up so everything gets allocated on long-word boundaries
2634 acmdlen
= ROUNDUP(cmdlen
);
2635 astatuslen
= ROUNDUP(statuslen
);
2636 atgtlen
= ROUNDUP(tgtlen
);
2637 ahbalen
= ROUNDUP(hbalen
);
2638 pktlen
= sizeof (struct scsi_pkt_wrapper
) +
2639 acmdlen
+ astatuslen
+ atgtlen
+ ahbalen
;
2641 hba_pkt
= kmem_zalloc(pktlen
,
2642 (callback
== SLEEP_FUNC
) ? KM_SLEEP
: KM_NOSLEEP
);
2643 if (hba_pkt
== NULL
) {
2644 ASSERT(callback
== NULL_FUNC
);
2649 * Set up our private info on this pkt
2651 hba_pkt
->pkt_wrapper_len
= pktlen
;
2652 hba_pkt
->pkt_wrapper_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
2653 pkt
= &hba_pkt
->scsi_pkt
;
2656 * Set up pointers to private data areas, cdb, and status.
2658 p
= (caddr_t
)(hba_pkt
+ 1);
2660 pkt
->pkt_ha_private
= (opaque_t
)p
;
2664 pkt
->pkt_private
= (opaque_t
)p
;
2667 if (statuslen
> 0) {
2668 pkt
->pkt_scbp
= (uchar_t
*)p
;
2672 pkt
->pkt_cdbp
= (uchar_t
*)p
;
2676 * Initialize the pkt's scsi_address
2678 pkt
->pkt_address
= *ap
;
2681 * NB: It may not be safe for drivers, esp target drivers, to depend
2682 * on the following fields being set until all the scsi_pkt
2683 * allocation violations discussed in scsi_pkt.h are all resolved.
2685 pkt
->pkt_cdblen
= cmdlen
;
2686 pkt
->pkt_tgtlen
= tgtlen
;
2687 pkt
->pkt_scblen
= statuslen
;
2693 * Called by an HBA to free a scsi_pkt
2698 struct scsi_address
*ap
,
2699 struct scsi_pkt
*pkt
)
2701 kmem_free(pkt
, ((struct scsi_pkt_wrapper
*)pkt
)->pkt_wrapper_len
);
2705 * Return 1 if the scsi_pkt used a proper allocator.
2707 * The DDI does not allow a driver to allocate it's own scsi_pkt(9S), a
2708 * driver should not have *any* compiled in dependencies on "sizeof (struct
2709 * scsi_pkt)". While this has been the case for many years, a number of
2710 * drivers have still not been fixed. This function can be used to detect
2711 * improperly allocated scsi_pkt structures, and produce messages identifying
2712 * drivers that need to be fixed.
2714 * While drivers in violation are being fixed, this function can also
2715 * be used by the framework to detect packets that violated allocation
2718 * NB: It is possible, but very unlikely, for this code to return a false
2719 * positive (finding correct magic, but for wrong reasons). Careful
2720 * consideration is needed for callers using this interface to condition
2721 * access to newer scsi_pkt fields (those after pkt_reason).
2723 * NB: As an aid to minimizing the amount of work involved in 'fixing' legacy
2724 * drivers that violate scsi_*(9S) allocation rules, private
2725 * scsi_pkt_size()/scsi_size_clean() functions are available (see their
2726 * implementation for details).
2728 * *** Non-legacy use of scsi_pkt_size() is discouraged. ***
2730 * NB: When supporting broken HBA drivers is not longer a concern, this
2731 * code should be removed.
2734 scsi_pkt_allocated_correctly(struct scsi_pkt
*pkt
)
2736 struct scsi_pkt_wrapper
*hba_pkt
= (struct scsi_pkt_wrapper
*)pkt
;
2740 int *pspwm
, *pspcwm
;
2743 * We are getting scsi packets from two 'correct' wrapper schemes,
2744 * make sure we are looking at the same place in both to detect
2745 * proper allocation.
2747 pspwm
= &((struct scsi_pkt_wrapper
*)0)->pkt_wrapper_magic
;
2748 pspcwm
= &((struct scsi_pkt_cache_wrapper
*)0)->pcw_magic
;
2749 ASSERT(pspwm
== pspcwm
);
2754 * Check to see if driver is scsi_size_clean(), assume it
2755 * is using the scsi_pkt_size() interface everywhere it needs to
2756 * if the driver indicates it is scsi_size_clean().
2758 major
= ddi_driver_major(P_TO_TRAN(pkt
)->tran_hba_dip
);
2759 if (devnamesp
[major
].dn_flags
& DN_SCSI_SIZE_CLEAN
)
2760 return (1); /* ok */
2763 * Special case crossing a page boundary. If the scsi_pkt was not
2764 * allocated correctly, then across a page boundary we have a
2767 if ((((uintptr_t)(&hba_pkt
->scsi_pkt
)) & MMU_PAGEMASK
) ==
2768 (((uintptr_t)(&hba_pkt
->pkt_wrapper_magic
)) & MMU_PAGEMASK
)) {
2769 /* fastpath, no cross-page hazard */
2770 magic
= hba_pkt
->pkt_wrapper_magic
;
2772 /* add protection for cross-page hazard */
2773 if (ddi_peek32((dev_info_t
*)NULL
,
2774 &hba_pkt
->pkt_wrapper_magic
, &magic
) == DDI_FAILURE
) {
2775 return (0); /* violation */
2779 /* properly allocated packet always has correct magic */
2780 return ((magic
== PKT_WRAPPER_MAGIC
) ? 1 : 0);
2784 * Private interfaces to simplify conversion of legacy drivers so they don't
2785 * depend on scsi_*(9S) size. Instead of using these private interface, HBA
2786 * drivers should use DDI sanctioned allocation methods:
2788 * scsi_pkt Use scsi_hba_pkt_alloc(9F), or implement
2789 * tran_setup_pkt(9E).
2791 * scsi_device You are doing something strange/special, a scsi_device
2792 * structure should only be allocated by scsi_hba.c
2793 * initchild code or scsi_vhci.c code.
2795 * scsi_hba_tran Use scsi_hba_tran_alloc(9F).
2800 return (sizeof (struct scsi_pkt
));
2804 scsi_hba_tran_size()
2806 return (sizeof (scsi_hba_tran_t
));
2812 return (sizeof (struct scsi_device
));
2816 * Legacy compliance to scsi_pkt(9S) allocation rules through use of
2817 * scsi_pkt_size() is detected by the 'scsi-size-clean' driver.conf property
2818 * or an HBA driver calling to scsi_size_clean() from attach(9E). A driver
2819 * developer should only indicate that a legacy driver is clean after using
2820 * SCSI_SIZE_CLEAN_VERIFY to ensure compliance (see scsi_pkt.h).
2823 scsi_size_clean(dev_info_t
*self
)
2826 struct devnames
*dnp
;
2829 major
= ddi_driver_major(self
);
2830 ASSERT(major
< devcnt
);
2831 if (major
>= devcnt
) {
2832 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2833 "scsi_pkt_size: bogus major: %d", major
));
2837 /* Set DN_SCSI_SIZE_CLEAN flag in dn_flags. */
2838 dnp
= &devnamesp
[major
];
2839 if ((dnp
->dn_flags
& DN_SCSI_SIZE_CLEAN
) == 0) {
2840 LOCK_DEV_OPS(&dnp
->dn_lock
);
2841 dnp
->dn_flags
|= DN_SCSI_SIZE_CLEAN
;
2842 UNLOCK_DEV_OPS(&dnp
->dn_lock
);
2848 * Called by an HBA to map strings to capability indices
2851 scsi_hba_lookup_capstr(
2855 * Capability strings: only add entries to mask the legacy
2856 * '_' vs. '-' misery. All new capabilities should use '-',
2857 * and be captured be added to SCSI_CAP_ASCII.
2859 static struct cap_strings
{
2863 { "dma_max", SCSI_CAP_DMA_MAX
},
2864 { "msg_out", SCSI_CAP_MSG_OUT
},
2865 { "wide_xfer", SCSI_CAP_WIDE_XFER
},
2868 static char *cap_ascii
[] = SCSI_CAP_ASCII
;
2871 struct cap_strings
*cp
;
2873 for (cap
= cap_ascii
, i
= 0; *cap
!= NULL
; cap
++, i
++)
2874 if (strcmp(*cap
, capstr
) == 0)
2877 for (cp
= cap_strings
; cp
->cap_string
!= NULL
; cp
++)
2878 if (strcmp(cp
->cap_string
, capstr
) == 0)
2879 return (cp
->cap_index
);
2885 * Called by an HBA to determine if the system is in 'panic' state.
2890 return (panicstr
!= NULL
);
2894 * If a SCSI target driver attempts to mmap memory,
2895 * the buck stops here.
2910 return (DDI_FAILURE
);
2914 scsi_hba_get_eventcookie(
2918 ddi_eventcookie_t
*eventp
)
2920 scsi_hba_tran_t
*tran
;
2922 tran
= ddi_get_driver_private(self
);
2923 if (tran
->tran_get_eventcookie
&&
2924 ((*tran
->tran_get_eventcookie
)(self
,
2925 child
, name
, eventp
) == DDI_SUCCESS
)) {
2926 return (DDI_SUCCESS
);
2929 return (ndi_busop_get_eventcookie(self
, child
, name
, eventp
));
2933 scsi_hba_add_eventcall(
2936 ddi_eventcookie_t event
,
2939 ddi_eventcookie_t event
,
2941 void *bus_impldata
),
2943 ddi_callback_id_t
*cb_id
)
2945 scsi_hba_tran_t
*tran
;
2947 tran
= ddi_get_driver_private(self
);
2948 if (tran
->tran_add_eventcall
&&
2949 ((*tran
->tran_add_eventcall
)(self
, child
,
2950 event
, callback
, arg
, cb_id
) == DDI_SUCCESS
)) {
2951 return (DDI_SUCCESS
);
2954 return (DDI_FAILURE
);
2958 scsi_hba_remove_eventcall(dev_info_t
*self
, ddi_callback_id_t cb_id
)
2960 scsi_hba_tran_t
*tran
;
2963 tran
= ddi_get_driver_private(self
);
2964 if (tran
->tran_remove_eventcall
&&
2965 ((*tran
->tran_remove_eventcall
)(
2966 self
, cb_id
) == DDI_SUCCESS
)) {
2967 return (DDI_SUCCESS
);
2970 return (DDI_FAILURE
);
2974 scsi_hba_post_event(
2977 ddi_eventcookie_t event
,
2980 scsi_hba_tran_t
*tran
;
2982 tran
= ddi_get_driver_private(self
);
2983 if (tran
->tran_post_event
&&
2984 ((*tran
->tran_post_event
)(self
,
2985 child
, event
, bus_impldata
) == DDI_SUCCESS
)) {
2986 return (DDI_SUCCESS
);
2989 return (DDI_FAILURE
);
2993 * Default getinfo(9e) for scsi_hba
2997 scsi_hba_info(dev_info_t
*self
, ddi_info_cmd_t infocmd
, void *arg
,
3000 int error
= DDI_SUCCESS
;
3003 case DDI_INFO_DEVT2INSTANCE
:
3004 *result
= (void *)(intptr_t)(MINOR2INST(getminor((dev_t
)arg
)));
3007 error
= DDI_FAILURE
;
3013 * Default open and close routine for scsi_hba
3017 scsi_hba_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
3020 scsi_hba_tran_t
*tran
;
3023 if (otyp
!= OTYP_CHR
)
3026 if ((self
= e_ddi_hold_devi_by_dev(*devp
, 0)) == NULL
)
3029 tran
= ddi_get_driver_private(self
);
3031 ddi_release_devi(self
);
3036 * tran_open_flag bit field:
3038 * 1: shared open by minor at bit position
3039 * 1 at 31st bit: exclusive open
3041 mutex_enter(&(tran
->tran_open_lock
));
3042 if (flags
& FEXCL
) {
3043 if (tran
->tran_open_flag
!= 0) {
3044 rv
= EBUSY
; /* already open */
3046 tran
->tran_open_flag
= TRAN_OPEN_EXCL
;
3049 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3050 rv
= EBUSY
; /* already excl. open */
3052 int minor
= getminor(*devp
) & TRAN_MINOR_MASK
;
3053 tran
->tran_open_flag
|= (1 << minor
);
3055 * Ensure that the last framework reserved minor
3056 * is unused. Otherwise, the exclusive open
3057 * mechanism may break.
3059 ASSERT(minor
!= 31);
3062 mutex_exit(&(tran
->tran_open_lock
));
3064 ddi_release_devi(self
);
3070 scsi_hba_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
3073 scsi_hba_tran_t
*tran
;
3075 if (otyp
!= OTYP_CHR
)
3078 if ((self
= e_ddi_hold_devi_by_dev(dev
, 0)) == NULL
)
3081 tran
= ddi_get_driver_private(self
);
3083 ddi_release_devi(self
);
3087 mutex_enter(&(tran
->tran_open_lock
));
3088 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3089 tran
->tran_open_flag
= 0;
3091 int minor
= getminor(dev
) & TRAN_MINOR_MASK
;
3092 tran
->tran_open_flag
&= ~(1 << minor
);
3094 mutex_exit(&(tran
->tran_open_lock
));
3096 ddi_release_devi(self
);
3101 * standard ioctl commands for SCSI hotplugging
3105 scsi_hba_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
3109 struct devctl_iocdata
*dcp
= NULL
;
3110 dev_info_t
*child
= NULL
;
3111 mdi_pathinfo_t
*path
= NULL
;
3112 struct scsi_device
*sd
;
3113 scsi_hba_tran_t
*tran
;
3120 self
= e_ddi_hold_devi_by_dev(dev
, 0);
3126 tran
= ddi_get_driver_private(self
);
3132 /* Ioctls for which the generic implementation suffices. */
3134 case DEVCTL_BUS_GETSTATE
:
3135 rv
= ndi_devctl_ioctl(self
, cmd
, arg
, mode
, 0);
3139 /* read devctl ioctl data */
3140 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
) {
3145 /* Ioctls that require child identification */
3147 case DEVCTL_DEVICE_GETSTATE
:
3148 case DEVCTL_DEVICE_ONLINE
:
3149 case DEVCTL_DEVICE_OFFLINE
:
3150 case DEVCTL_DEVICE_REMOVE
:
3151 case DEVCTL_DEVICE_RESET
:
3152 name
= ndi_dc_getname(dcp
);
3153 addr
= ndi_dc_getaddr(dcp
);
3154 if ((name
== NULL
) || (addr
== NULL
)) {
3160 * Find child with name@addr - might find a devinfo
3161 * child (child), a pathinfo child (path), or nothing.
3163 scsi_hba_devi_enter(self
, &circ
);
3165 (void) scsi_findchild(self
, name
, addr
, 1, &child
, &path
, NULL
);
3167 /* Found a pathinfo */
3168 ASSERT(path
&& (child
== NULL
));
3169 mdi_hold_path(path
);
3170 scsi_hba_devi_exit_phci(self
, circ
);
3173 /* Found a devinfo */
3174 ASSERT(child
&& (path
== NULL
));
3176 /* verify scsi_device of child */
3177 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3178 sd
= ddi_get_driver_private(child
);
3182 ASSERT((path
== NULL
) && (child
== NULL
));
3183 scsi_hba_devi_exit(self
, circ
);
3184 rv
= ENXIO
; /* found nothing */
3189 case DEVCTL_BUS_RESETALL
: /* ioctl that operate on any child */
3191 * Find a child's scsi_address so we can invoke tran_reset.
3193 * Future: If no child exists, we could fake a child. This will
3194 * be a enhancement for the future - for now, we fall back to
3197 scsi_hba_devi_enter(self
, &circ
);
3198 child
= ddi_get_child(self
);
3201 /* verify scsi_device of child */
3202 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3203 sd
= ddi_get_driver_private(child
);
3206 * NOTE: node has a scsi_device structure, so
3207 * it must be initialized.
3209 ndi_hold_devi(child
);
3212 child
= ddi_get_next_sibling(child
);
3214 scsi_hba_devi_exit(self
, circ
);
3219 case DEVCTL_DEVICE_GETSTATE
:
3221 if (mdi_dc_return_dev_state(path
, dcp
) != MDI_SUCCESS
)
3224 if (ndi_dc_return_dev_state(child
, dcp
) != NDI_SUCCESS
)
3231 case DEVCTL_DEVICE_RESET
:
3236 if (tran
->tran_reset
== NULL
) {
3241 /* Start with the small stick */
3242 if (scsi_reset(&sd
->sd_address
, RESET_LUN
) == 1)
3243 break; /* LUN reset worked */
3244 if (scsi_reset(&sd
->sd_address
, RESET_TARGET
) != 1)
3245 rv
= EIO
; /* Target reset failed */
3248 case DEVCTL_BUS_QUIESCE
:
3249 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3250 (bus_state
== BUS_QUIESCED
))
3252 else if (tran
->tran_quiesce
== NULL
)
3253 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3254 else if (tran
->tran_quiesce(self
) != 0)
3256 else if (ndi_set_bus_state(self
, BUS_QUIESCED
) != NDI_SUCCESS
)
3260 case DEVCTL_BUS_UNQUIESCE
:
3261 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3262 (bus_state
== BUS_ACTIVE
))
3264 else if (tran
->tran_unquiesce
== NULL
)
3265 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3266 else if (tran
->tran_unquiesce(self
) != 0)
3268 else if (ndi_set_bus_state(self
, BUS_ACTIVE
) != NDI_SUCCESS
)
3272 case DEVCTL_BUS_RESET
:
3273 if (tran
->tran_bus_reset
== NULL
)
3274 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3275 else if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3279 case DEVCTL_BUS_RESETALL
:
3281 (scsi_reset(&sd
->sd_address
, RESET_ALL
) == 1)) {
3282 break; /* reset all worked */
3284 if (tran
->tran_bus_reset
== NULL
) {
3285 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3288 if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3289 rv
= EIO
; /* bus reset failed */
3292 case DEVCTL_BUS_CONFIGURE
:
3293 if (ndi_devi_config(self
, NDI_DEVFS_CLEAN
| NDI_DEVI_PERSIST
|
3294 NDI_CONFIG_REPROBE
) != NDI_SUCCESS
) {
3299 case DEVCTL_BUS_UNCONFIGURE
:
3300 if (ndi_devi_unconfig(self
,
3301 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
) {
3306 case DEVCTL_DEVICE_ONLINE
:
3307 ASSERT(child
|| path
);
3309 if (mdi_pi_online(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3312 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
)
3317 case DEVCTL_DEVICE_OFFLINE
:
3318 ASSERT(child
|| path
);
3320 (void) scsi_clear_task_set(&sd
->sd_address
);
3322 if (mdi_pi_offline(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3325 if (ndi_devi_offline(child
,
3326 NDI_DEVFS_CLEAN
) != NDI_SUCCESS
)
3331 case DEVCTL_DEVICE_REMOVE
:
3332 ASSERT(child
|| path
);
3334 (void) scsi_clear_task_set(&sd
->sd_address
);
3336 /* NOTE: don't pass NDI_DEVI_REMOVE to mdi_pi_offline */
3337 if (mdi_pi_offline(path
, NDI_USER_REQ
) == MDI_SUCCESS
) {
3338 scsi_hba_devi_enter_phci(self
, &circ
);
3339 mdi_rele_path(path
);
3341 /* ... here is the DEVICE_REMOVE part. */
3342 (void) mdi_pi_free(path
, 0);
3348 if (ndi_devi_offline(child
,
3349 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
)
3355 ASSERT(dcp
!= NULL
);
3360 /* all done -- clean up and return */
3362 /* release hold on what we found */
3364 scsi_hba_devi_enter_phci(self
, &circ
);
3365 mdi_rele_path(path
);
3368 scsi_hba_devi_exit(self
, circ
);
3371 ndi_dc_freehdl(dcp
);
3374 ddi_release_devi(self
);
3383 scsi_hba_fm_init_child(dev_info_t
*self
, dev_info_t
*child
, int cap
,
3384 ddi_iblock_cookie_t
*ibc
)
3386 scsi_hba_tran_t
*tran
= ddi_get_driver_private(self
);
3388 return (tran
? tran
->tran_fm_capable
: scsi_fm_capable
);
3392 scsi_hba_bus_power(dev_info_t
*self
, void *impl_arg
, pm_bus_power_op_t op
,
3393 void *arg
, void *result
)
3395 scsi_hba_tran_t
*tran
;
3397 tran
= ddi_get_driver_private(self
);
3398 if (tran
&& tran
->tran_bus_power
) {
3399 return (tran
->tran_bus_power(self
, impl_arg
,
3403 return (pm_busop_bus_power(self
, impl_arg
, op
, arg
, result
));
3407 * Return the lun64 value from a address string: "addr,lun[,sfunc]". Either
3408 * the lun is after the first ',' or the entire address string is the lun.
3409 * Return SCSI_LUN64_ILLEGAL if the format is incorrect. A lun64 is at most
3410 * 16 hex digits long.
3412 * If the address string specified has incorrect syntax (busconfig one of
3413 * bogus /devices path) then scsi_addr_to_lun64 can return SCSI_LUN64_ILLEGAL.
3416 scsi_addr_to_lun64(char *addr
)
3423 s
= strchr(addr
, ','); /* "addr,lun" */
3425 s
++; /* skip ',', at lun */
3427 s
= addr
; /* "lun" */
3429 for (lun64
= 0, i
= 0; *s
&& (i
< 16); s
++, i
++) {
3430 if (*s
>= '0' && *s
<= '9')
3431 lun64
= (lun64
<< 4) + (*s
- '0');
3432 else if (*s
>= 'A' && *s
<= 'F')
3433 lun64
= (lun64
<< 4) + 10 + (*s
- 'A');
3434 else if (*s
>= 'a' && *s
<= 'f')
3435 lun64
= (lun64
<< 4) + 10 + (*s
- 'a');
3439 if (*s
&& (*s
!= ',')) /* [,sfunc] is OK */
3440 lun64
= SCSI_LUN64_ILLEGAL
;
3442 lun64
= SCSI_LUN64_ILLEGAL
;
3444 if (lun64
== SCSI_LUN64_ILLEGAL
)
3445 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
3446 "addr_to_lun64 %s lun %" PRIlun64
,
3447 addr
? addr
: "NULL", lun64
));
3452 * Return the sfunc value from a address string: "addr,lun[,sfunc]". Either the
3453 * sfunc is after the second ',' or the entire address string is the sfunc.
3454 * Return -1 if there is only one ',' in the address string or the string is
3455 * invalid. An sfunc is at most two hex digits long.
3458 scsi_addr_to_sfunc(char *addr
)
3465 s
= strchr(addr
, ','); /* "addr,lun" */
3467 s
++; /* skip ',', at lun */
3468 s
= strchr(s
, ','); /* "lun,sfunc" */
3470 return (-1); /* no ",sfunc" */
3471 s
++; /* skip ',', at sfunc */
3473 s
= addr
; /* "sfunc" */
3475 for (sfunc
= 0, i
= 0; *s
&& (i
< 2); s
++, i
++) {
3476 if (*s
>= '0' && *s
<= '9')
3477 sfunc
= (sfunc
<< 4) + (*s
- '0');
3478 else if (*s
>= 'A' && *s
<= 'F')
3479 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'A');
3480 else if (*s
>= 'a' && *s
<= 'f')
3481 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'a');
3486 sfunc
= -1; /* illegal */
3493 * Convert scsi ascii string data to NULL terminated (semi) legal IEEE 1275
3494 * "compatible" (name) property form.
3496 * For ASCII INQUIRY data, a one-way conversion algorithm is needed to take
3497 * SCSI_ASCII (20h - 7Eh) to a 1275-like compatible form. The 1275 spec allows
3498 * letters, digits, one ",", and ". _ + -", all limited by a maximum 31
3499 * character length. Since ", ." are used as separators in the compatible
3500 * string itself, they are converted to "_". All SCSI_ASCII characters that
3501 * are illegal in 1275, as well as any illegal SCSI_ASCII characters
3502 * encountered, are converted to "_". To reduce length, trailing blanks are
3503 * trimmed from SCSI_ASCII fields prior to conversion.
3505 * Example: SCSI_ASCII "ST32550W SUN2.1G" -> "ST32550W_SUN2_1G"
3507 * NOTE: the 1275 string form is always less than or equal to the scsi form.
3510 string_scsi_to_1275(char *s_1275
, char *s_scsi
, int len
)
3512 (void) strncpy(s_1275
, s_scsi
, len
);
3513 s_1275
[len
--] = '\0';
3516 if (s_1275
[len
] == ' ')
3517 s_1275
[len
--] = '\0'; /* trim trailing " " */
3523 if (((s_1275
[len
] >= 'a') && (s_1275
[len
] <= 'z')) ||
3524 ((s_1275
[len
] >= 'A') && (s_1275
[len
] <= 'Z')) ||
3525 ((s_1275
[len
] >= '0') && (s_1275
[len
] <= '9')) ||
3526 (s_1275
[len
] == '_') ||
3527 (s_1275
[len
] == '+') ||
3528 (s_1275
[len
] == '-'))
3529 len
--; /* legal 1275 */
3531 s_1275
[len
--] = '_'; /* illegal SCSI_ASCII | 1275 */
3538 * Given the inquiry data, binding_set, and dtype_node for a scsi device,
3539 * return the nodename and compatible property for the device. The "compatible"
3540 * concept comes from IEEE-1275. The compatible information is returned is in
3541 * the correct form for direct use defining the "compatible" string array
3542 * property. Internally, "compatible" is also used to determine the nodename
3545 * This function is provided as a separate entry point for use by drivers that
3546 * currently issue their own non-SCSA inquiry command and perform their own
3547 * node creation based their own private compiled in tables. Converting these
3548 * drivers to use this interface provides a quick easy way of obtaining
3549 * consistency as well as the flexibility associated with the 1275 techniques.
3551 * The dtype_node is passed as a separate argument (instead of having the
3552 * implementation use inq_dtype). It indicates that information about
3553 * a secondary function embedded service should be produced.
3555 * Callers must always use scsi_hba_nodename_compatible_free, even if
3556 * *nodenamep is null, to free the nodename and compatible information
3559 * If a nodename can't be determined then **compatiblep will point to a
3560 * diagnostic string containing all the compatible forms.
3562 * NOTE: some compatible strings may violate the 31 character restriction
3563 * imposed by IEEE-1275. This is not a problem because Solaris does not care
3564 * about this 31 character limit.
3566 * Each compatible form belongs to a form-group. The form-groups currently
3567 * defined are generic ("scsiclass"), binding-set ("scsa.b"), and failover
3570 * The following compatible forms, in high to low precedence
3571 * order, are defined for SCSI target device nodes.
3573 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (1 *1&2)
3574 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (2 *1)
3575 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (3 *2)
3576 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (4)
3577 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (5 *1&2)
3578 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP (6 *1)
3579 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (7 *2)
3580 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP (8)
3581 * scsa,DD.bBBBBBBBB (8.5 *3)
3582 * scsiclass,DDEEFFF (9 *1&2)
3583 * scsiclass,DDEE (10 *1)
3584 * scsiclass,DDFFF (11 *2)
3586 * scsa.fFFF (12.5 *4)
3589 * *1 only produced on a secondary function node
3590 * *2 only produced when generic form-group flags exist.
3591 * *3 only produced when binding-set form-group legacy support is needed
3592 * *4 only produced when failover form-group flags exist.
3596 * v is the letter 'v'. Denotest the
3597 * beginning of VVVVVVVV.
3599 * VVVVVVVV Translated scsi_vendor.
3601 * p is the letter 'p'. Denotes the
3602 * beginning of PPPPPPPPPPPPPPPP.
3604 * PPPPPPPPPPPPPPPP Translated scsi_product.
3606 * r is the letter 'r'. Denotes the
3607 * beginning of RRRR.
3609 * RRRR Translated scsi_revision.
3611 * DD is a two digit ASCII hexadecimal
3612 * number. The value of the two digits is
3613 * based one the SCSI "Peripheral device
3614 * type" command set associated with the
3615 * node. On a primary node this is the
3616 * scsi_dtype of the primary command set,
3617 * on a secondary node this is the
3618 * scsi_dtype associated with the secondary
3619 * function embedded command set.
3621 * EE Same encoding used for DD. This form is
3622 * only generated on secondary function
3623 * nodes. The DD secondary function is embedded
3626 * FFF Concatenation, in alphabetical order,
3627 * of the flag characters within a form-group.
3628 * For a given form-group, the following
3629 * flags are defined.
3631 * scsiclass: (generic form-group):
3632 * R Removable_Media: Used when
3634 * S SAF-TE device: Used when
3635 * inquiry information indicates
3638 * scsa.f: (failover form-group):
3639 * E Explicit Target_Port_Group: Used
3640 * when inq_tpgse is set and 'G' is
3642 * G GUID: Used when a GUID can be
3643 * generated for the device.
3644 * I Implicit Target_Port_Group: Used
3645 * when inq_tpgs is set and 'G' is
3648 * Forms using FFF are only be generated
3649 * if there are applicable flag
3652 * b is the letter 'b'. Denotes the
3653 * beginning of BBBBBBBB.
3655 * BBBBBBBB Binding-set. Operating System Specific:
3656 * scsi-binding-set property of HBA.
3658 #define NCOMPAT (1 + (13 + 2) + 1)
3659 #define COMPAT_LONGEST (strlen( \
3660 "scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR" + 1))
3663 * Private version with extra device 'identity' arguments to allow code
3664 * to determine GUID FFF support.
3667 scsi_hba_ident_nodename_compatible_get(struct scsi_inquiry
*inq
,
3668 uchar_t
*inq80
, size_t inq80len
, uchar_t
*inq83
, size_t inq83len
,
3669 char *binding_set
, int dtype_node
, char *compat0
,
3670 char **nodenamep
, char **drivernamep
,
3671 char ***compatiblep
, int *ncompatiblep
)
3673 char vid
[sizeof (inq
->inq_vid
) + 1 ];
3674 char pid
[sizeof (inq
->inq_pid
) + 1];
3675 char rev
[sizeof (inq
->inq_revision
) + 1];
3676 char gf
[sizeof ("RS\0")];
3677 char ff
[sizeof ("EGI\0")];
3679 int ncompat
; /* number of compatible */
3680 char **compatp
; /* compatible ptrs */
3682 char *nname
; /* nodename */
3683 char *dname
; /* driver name */
3691 uchar_t
*iqd
= (uchar_t
*)inq
;
3694 * Nodename_aliases: This table was originally designed to be
3695 * implemented via a new nodename_aliases file - a peer to the
3696 * driver_aliases that selects a nodename based on compatible
3697 * forms in much the same say driver_aliases is used to select
3698 * driver bindings from compatible forms. Each compatible form
3699 * is an 'alias'. Until a more general need for a
3700 * nodename_aliases file exists, which may never occur, the
3701 * scsi mappings are described here via a compiled in table.
3703 * This table contains nodename mappings for self-identifying
3704 * scsi devices enumerated by the Solaris kernel. For a given
3705 * device, the highest precedence "compatible" form with a
3706 * mapping is used to select the nodename for the device. This
3707 * will typically be a generic nodename, however in some legacy
3708 * compatibility cases a driver nodename mapping may be selected.
3710 * Because of possible breakage associated with switching SCSI
3711 * target devices from driver nodenames to generic nodenames,
3712 * we are currently unable to support generic nodenames for all
3713 * SCSI devices (binding-sets). Although /devices paths are
3714 * defined as unstable, avoiding possible breakage is
3715 * important. Some of the newer SCSI transports (USB) already
3716 * use generic nodenames. All new SCSI transports and target
3717 * devices should use generic nodenames. At times this decision
3718 * may be architecture dependent (sparc .vs. intel) based on when
3719 * a transport was supported on a particular architecture.
3721 * We provide a base set of generic nodename mappings based on
3722 * scsiclass dtype and higher-precedence driver nodename
3723 * mappings based on scsa "binding-set" to cover legacy
3724 * issues. The binding-set is typically associated with
3725 * "scsi-binding-set" property value of the HBA. The legacy
3726 * mappings are provided independent of whether the driver they
3727 * refer to is installed. This allows a correctly named node
3728 * be created at discovery time, and binding to occur when/if
3729 * an add_drv of the legacy driver occurs.
3731 * We also have mappings for legacy SUN hardware that
3732 * misidentifies itself (enclosure services which identify
3733 * themselves as processors). All future hardware should use
3734 * the correct dtype.
3736 * As SCSI HBAs are modified to use the SCSA interfaces for
3737 * self-identifying SCSI target devices (PSARC/2004/116) the
3738 * nodename_aliases table (PSARC/2004/420) should be augmented
3739 * with legacy mappings in order to maintain compatibility with
3740 * existing /devices paths, especially for devices that house
3741 * an OS. Failure to do this may cause upgrade problems.
3742 * Additions for new target devices or transports should not
3743 * add scsa binding-set compatible mappings.
3745 static struct nodename_aliases
{
3746 char *na_nodename
; /* nodename */
3747 char *na_alias
; /* compatible form match */
3749 /* # mapping to generic nodenames based on scsi dtype */
3750 {"disk", "scsiclass,00"},
3751 {"tape", "scsiclass,01"},
3752 {"printer", "scsiclass,02"},
3753 {"processor", "scsiclass,03"},
3754 {"worm", "scsiclass,04"},
3755 {"cdrom", "scsiclass,05"},
3756 {"scanner", "scsiclass,06"},
3757 {"optical-disk", "scsiclass,07"},
3758 {"medium-changer", "scsiclass,08"},
3759 {"obsolete", "scsiclass,09"},
3760 {"prepress-a", "scsiclass,0a"},
3761 {"prepress-b", "scsiclass,0b"},
3762 {"array-controller", "scsiclass,0c"},
3763 {"enclosure", "scsiclass,0d"},
3764 {"disk", "scsiclass,0e"},
3765 {"card-reader", "scsiclass,0f"},
3766 {"bridge", "scsiclass,10"},
3767 {"object-store", "scsiclass,11"},
3768 {"reserved", "scsiclass,12"},
3769 {"reserved", "scsiclass,13"},
3770 {"reserved", "scsiclass,14"},
3771 {"reserved", "scsiclass,15"},
3772 {"reserved", "scsiclass,16"},
3773 {"reserved", "scsiclass,17"},
3774 {"reserved", "scsiclass,18"},
3775 {"reserved", "scsiclass,19"},
3776 {"reserved", "scsiclass,1a"},
3777 {"reserved", "scsiclass,1b"},
3778 {"reserved", "scsiclass,1c"},
3779 {"reserved", "scsiclass,1d"},
3780 {"well-known-lun", "scsiclass,1e"},
3781 {"unknown", "scsiclass,1f"},
3784 /* # legacy mapping to driver nodenames for fcp binding-set */
3785 {"ssd", "scsa,00.bfcp"},
3786 {"st", "scsa,01.bfcp"},
3787 {"sgen", "scsa,08.bfcp"},
3788 {"ses", "scsa,0d.bfcp"},
3790 /* # legacy mapping to driver nodenames for vhci binding-set */
3791 {"ssd", "scsa,00.bvhci"},
3792 {"st", "scsa,01.bvhci"},
3793 {"sgen", "scsa,08.bvhci"},
3794 {"ses", "scsa,0d.bvhci"},
3796 /* # for x86 fcp and vhci use generic nodenames */
3799 /* # legacy mapping to driver nodenames for spi binding-set */
3800 {"sd", "scsa,00.bspi"},
3801 {"sd", "scsa,05.bspi"},
3802 {"sd", "scsa,07.bspi"},
3803 {"st", "scsa,01.bspi"},
3804 {"ses", "scsa,0d.bspi"},
3806 /* # SUN misidentified spi hardware */
3807 {"ses", "scsiclass,03.vSUN.pD2"},
3808 {"ses", "scsiclass,03.vSYMBIOS.pD1000"},
3810 /* # legacy mapping to driver nodenames for atapi binding-set */
3811 {"sd", "scsa,00.batapi"},
3812 {"sd", "scsa,05.batapi"},
3813 {"sd", "scsa,07.batapi"},
3814 {"st", "scsa,01.batapi"},
3815 {"unknown", "scsa,0d.batapi"},
3817 /* # legacy mapping to generic nodenames for usb binding-set */
3818 {"disk", "scsa,05.busb"},
3819 {"disk", "scsa,07.busb"},
3820 {"changer", "scsa,08.busb"},
3821 {"comm", "scsa,09.busb"},
3822 {"array_ctlr", "scsa,0c.busb"},
3823 {"esi", "scsa,0d.busb"},
3826 * mapping nodenames for mpt based on scsi dtype
3827 * for being compatible with the original node names
3828 * under mpt controller
3830 {"sd", "scsa,00.bmpt"},
3831 {"sd", "scsa,05.bmpt"},
3832 {"sd", "scsa,07.bmpt"},
3833 {"st", "scsa,01.bmpt"},
3834 {"ses", "scsa,0d.bmpt"},
3835 {"sgen", "scsa,08.bmpt"},
3838 struct nodename_aliases
*nap
;
3840 /* NOTE: drivernamep can be NULL */
3841 ASSERT(nodenamep
&& compatiblep
&& ncompatiblep
&&
3842 (binding_set
== NULL
|| (strlen(binding_set
) <= 8)));
3843 if ((nodenamep
== NULL
) || (compatiblep
== NULL
) ||
3844 (ncompatiblep
== NULL
))
3848 * In order to reduce runtime we allocate one block of memory that
3849 * contains both the NULL terminated array of pointers to compatible
3850 * forms and the individual compatible strings. This block is
3851 * somewhat larger than needed, but is short lived - it only exists
3852 * until the caller can transfer the information into the "compatible"
3853 * string array property and call scsi_hba_nodename_compatible_free.
3855 tlen
= NCOMPAT
* COMPAT_LONGEST
;
3856 compatp
= kmem_alloc((NCOMPAT
* sizeof (char *)) + tlen
, KM_SLEEP
);
3858 /* convert inquiry data from SCSI ASCII to 1275 string */
3859 (void) string_scsi_to_1275(vid
, inq
->inq_vid
,
3860 sizeof (inq
->inq_vid
));
3861 (void) string_scsi_to_1275(pid
, inq
->inq_pid
,
3862 sizeof (inq
->inq_pid
));
3863 (void) string_scsi_to_1275(rev
, inq
->inq_revision
,
3864 sizeof (inq
->inq_revision
));
3865 ASSERT((strlen(vid
) <= sizeof (inq
->inq_vid
)) &&
3866 (strlen(pid
) <= sizeof (inq
->inq_pid
)) &&
3867 (strlen(rev
) <= sizeof (inq
->inq_revision
)));
3870 * Form flags in ***ALPHABETICAL*** order within form-group:
3872 * NOTE: When adding a new flag to an existing form-group, careful
3873 * consideration must be given to not breaking existing bindings
3874 * based on that form-group.
3878 * generic form-group flags
3880 * Set when inq_rmb is set and for well known scsi dtypes. For a
3881 * bus where the entire device is removable (like USB), we expect
3882 * the HBA to intercept the inquiry data and set inq_rmb.
3883 * Since OBP does not distinguish removable media in its generic
3884 * name selection we avoid setting the 'R' flag if the root is not
3887 * Set when the device type is SAT-TE.
3890 dtype_device
= inq
->inq_dtype
& DTYPE_MASK
;
3891 if (modrootloaded
&& (inq
->inq_rmb
||
3892 (dtype_device
== DTYPE_WORM
) ||
3893 (dtype_device
== DTYPE_RODIRECT
) ||
3894 (dtype_device
== DTYPE_OPTICAL
)))
3895 gf
[i
++] = 'R'; /* removable */
3898 if (modrootloaded
&&
3899 (dtype_device
== DTYPE_PROCESSOR
) &&
3900 (strncmp((char *)&iqd
[44], "SAF-TE", 4) == 0))
3905 * failover form-group flags
3906 * E Explicit Target_Port_Group_Supported:
3907 * Set for a device that has a GUID if inq_tpgse also set.
3909 * Set when we have identity information, can determine a devid
3910 * from the identity information, and can generate a guid from
3912 * I Implicit Target_Port_Group_Supported:
3913 * Set for a device that has a GUID if inq_tpgs also set.
3916 if ((inq80
|| inq83
) &&
3917 (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, NULL
,
3918 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
3919 &devid
) == DDI_SUCCESS
)) {
3920 guid
= ddi_devid_to_guid(devid
);
3921 ddi_devid_free(devid
);
3924 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_EXPLICIT
))
3925 ff
[i
++] = 'E'; /* EXPLICIT TPGS */
3927 ff
[i
++] = 'G'; /* GUID */
3928 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_IMPLICIT
))
3929 ff
[i
++] = 'I'; /* IMPLICIT TPGS */
3932 ddi_devid_free_guid(guid
);
3935 * Construct all applicable compatible forms. See comment at the
3936 * head of the function for a description of the compatible forms.
3939 p
= (char *)(compatp
+ NCOMPAT
);
3941 /* ( 0) driver (optional, not documented in scsi(4)) */
3944 (void) snprintf(p
, tlen
, "%s", compat0
);
3945 len
= strlen(p
) + 1;
3950 /* ( 1) scsiclass,DDEEFFF.vV.pP.rR */
3951 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
&& *rev
) {
3953 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s.r%s",
3954 dtype_node
, dtype_device
, gf
, vid
, pid
, rev
);
3955 len
= strlen(p
) + 1;
3960 /* ( 2) scsiclass,DDEE.vV.pP.rR */
3961 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
&& *rev
) {
3963 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s.r%s",
3964 dtype_node
, dtype_device
, vid
, pid
, rev
);
3965 len
= strlen(p
) + 1;
3970 /* ( 3) scsiclass,DDFFF.vV.pP.rR */
3971 if (*gf
&& *vid
&& *pid
&& *rev
) {
3973 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s.r%s",
3974 dtype_node
, gf
, vid
, pid
, rev
);
3975 len
= strlen(p
) + 1;
3980 /* ( 4) scsiclass,DD.vV.pP.rR */
3981 if (*vid
&& *pid
&& *rev
) {
3983 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s.r%s",
3984 dtype_node
, vid
, pid
, rev
);
3985 len
= strlen(p
) + 1;
3990 /* ( 5) scsiclass,DDEEFFF.vV.pP */
3991 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
) {
3993 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s",
3994 dtype_node
, dtype_device
, gf
, vid
, pid
);
3995 len
= strlen(p
) + 1;
4000 /* ( 6) scsiclass,DDEE.vV.pP */
4001 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
) {
4003 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s",
4004 dtype_node
, dtype_device
, vid
, pid
);
4005 len
= strlen(p
) + 1;
4010 /* ( 7) scsiclass,DDFFF.vV.pP */
4011 if (*gf
&& *vid
&& *pid
) {
4013 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s",
4014 dtype_node
, gf
, vid
, pid
);
4015 len
= strlen(p
) + 1;
4020 /* ( 8) scsiclass,DD.vV.pP */
4023 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s",
4024 dtype_node
, vid
, pid
);
4025 len
= strlen(p
) + 1;
4030 /* (8.5) scsa,DD.bB (not documented in scsi(4)) */
4033 (void) snprintf(p
, tlen
, "scsa,%02x.b%s",
4034 dtype_node
, binding_set
);
4035 len
= strlen(p
) + 1;
4040 /* ( 9) scsiclass,DDEEFFF */
4041 if ((dtype_device
!= dtype_node
) && *gf
) {
4043 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s",
4044 dtype_node
, dtype_device
, gf
);
4045 len
= strlen(p
) + 1;
4050 /* (10) scsiclass,DDEE */
4051 if (dtype_device
!= dtype_node
) {
4053 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x",
4054 dtype_node
, dtype_device
);
4055 len
= strlen(p
) + 1;
4060 /* (11) scsiclass,DDFFF */
4063 (void) snprintf(p
, tlen
, "scsiclass,%02x%s",
4065 len
= strlen(p
) + 1;
4070 /* (12) scsiclass,DD */
4072 (void) snprintf(p
, tlen
, "scsiclass,%02x", dtype_node
);
4073 len
= strlen(p
) + 1;
4077 /* (12.5) scsa.fFFF */
4080 (void) snprintf(p
, tlen
, "scsa.f%s", ff
);
4081 len
= strlen(p
) + 1;
4086 /* (13) scsiclass */
4088 (void) snprintf(p
, tlen
, "scsiclass");
4089 len
= strlen(p
) + 1;
4094 *csp
= NULL
; /* NULL terminate array of pointers */
4095 ncompat
= csp
- compatp
;
4098 * When determining a nodename, a nodename_aliases specified
4099 * mapping has precedence over using a driver_aliases specified
4100 * driver binding as a nodename.
4102 * See if any of the compatible forms have a nodename_aliases
4103 * specified nodename. These mappings are described by
4104 * nodename_aliases entries like:
4106 * disk "scsiclass,00"
4107 * enclosure "scsiclass,03.vSYMBIOS.pD1000"
4108 * ssd "scsa,00.bfcp"
4110 * All nodename_aliases mappings should idealy be to generic
4111 * names, however a higher precedence legacy mapping to a
4112 * driver name may exist. The highest precedence mapping
4113 * provides the nodename, so legacy driver nodename mappings
4114 * (if they exist) take precedence over generic nodename
4117 for (nname
= NULL
, csp
= compatp
; (nname
== NULL
) && *csp
; csp
++) {
4118 for (nap
= na
; nap
->na_nodename
; nap
++) {
4119 if (strcmp(*csp
, nap
->na_alias
) == 0) {
4120 nname
= nap
->na_nodename
;
4127 * Determine the driver name based on compatible (which may
4128 * have the passed in compat0 as the first item). The driver_aliases
4129 * file has entries like
4133 * that map compatible forms to specific drivers. These entries are
4134 * established by add_drv/update_drv. We use the most specific
4135 * driver binding as the nodename. This matches the eventual
4136 * ddi_driver_compatible_major() binding that will be
4137 * established by bind_node()
4139 for (dname
= NULL
, csp
= compatp
; *csp
; csp
++) {
4140 major
= ddi_name_to_major(*csp
);
4141 if ((major
== DDI_MAJOR_T_NONE
) ||
4142 (devnamesp
[major
].dn_flags
& DN_DRIVER_REMOVED
))
4144 if (dname
= ddi_major_to_name(major
))
4149 * If no nodename_aliases mapping exists then use the
4150 * driver_aliases specified driver binding as a nodename.
4155 /* return results */
4157 *nodenamep
= kmem_alloc(strlen(nname
) + 1, KM_SLEEP
);
4158 (void) strcpy(*nodenamep
, nname
);
4163 * If no nodename could be determined return a special
4164 * 'compatible' to be used for a diagnostic message. This
4165 * compatible contains all compatible forms concatenated
4166 * into a single string pointed to by the first element.
4168 for (csp
= compatp
; *(csp
+ 1); csp
++)
4169 *((*csp
) + strlen(*csp
)) = ' ';
4170 *(compatp
+ 1) = NULL
;
4176 *drivernamep
= kmem_alloc(strlen(dname
) + 1, KM_SLEEP
);
4177 (void) strcpy(*drivernamep
, dname
);
4179 *drivernamep
= NULL
;
4181 *compatiblep
= compatp
;
4182 *ncompatiblep
= ncompat
;
4186 * Free allocations associated with scsi_hba_ident_nodename_compatible_get.
4189 scsi_hba_ident_nodename_compatible_free(char *nodename
, char *drivername
,
4193 kmem_free(nodename
, strlen(nodename
) + 1);
4195 kmem_free(drivername
, strlen(drivername
) + 1);
4197 kmem_free(compatible
, (NCOMPAT
* sizeof (char *)) +
4198 (NCOMPAT
* COMPAT_LONGEST
));
4202 scsi_hba_nodename_compatible_get(struct scsi_inquiry
*inq
,
4203 char *binding_set
, int dtype_node
, char *compat0
,
4204 char **nodenamep
, char ***compatiblep
, int *ncompatiblep
)
4206 scsi_hba_ident_nodename_compatible_get(inq
,
4207 NULL
, 0, NULL
, 0, binding_set
, dtype_node
, compat0
, nodenamep
,
4208 NULL
, compatiblep
, ncompatiblep
);
4212 scsi_hba_nodename_compatible_free(char *nodename
, char **compatible
)
4214 scsi_hba_ident_nodename_compatible_free(nodename
, NULL
, compatible
);
4217 /* return the unit_address associated with a scsi_device */
4219 scsi_device_unit_address(struct scsi_device
*sd
)
4221 mdi_pathinfo_t
*pip
;
4223 ASSERT(sd
&& sd
->sd_dev
);
4224 if ((sd
== NULL
) || (sd
->sd_dev
== NULL
))
4227 pip
= (mdi_pathinfo_t
*)sd
->sd_pathinfo
;
4229 return (mdi_pi_get_addr(pip
));
4231 return (ddi_get_name_addr(sd
->sd_dev
));
4234 /* scsi_device property interfaces */
4235 #define _TYPE_DEFINED(flags) \
4236 (((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) || \
4237 ((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_DEVICE))
4239 #define _DEVICE_PIP(sd, flags) \
4240 ((((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) && \
4241 sd->sd_pathinfo) ? (mdi_pathinfo_t *)sd->sd_pathinfo : NULL)
4244 scsi_device_prop_get_int(struct scsi_device
*sd
, uint_t flags
,
4245 char *name
, int defval
)
4247 mdi_pathinfo_t
*pip
;
4252 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4253 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4254 !_TYPE_DEFINED(flags
))
4257 pip
= _DEVICE_PIP(sd
, flags
);
4259 rv
= mdi_prop_lookup_int(pip
, name
, &data
);
4260 if (rv
== DDI_PROP_SUCCESS
)
4263 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, sd
->sd_dev
,
4264 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4270 scsi_device_prop_get_int64(struct scsi_device
*sd
, uint_t flags
,
4271 char *name
, int64_t defval
)
4273 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
))
4283 pip
= _DEVICE_PIP(sd
, flags
);
4285 rv
= mdi_prop_lookup_int64(pip
, name
, &data
);
4286 if (rv
== DDI_PROP_SUCCESS
)
4289 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, sd
->sd_dev
,
4290 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4295 scsi_device_prop_lookup_byte_array(struct scsi_device
*sd
, uint_t flags
,
4296 char *name
, uchar_t
**data
, uint_t
*nelements
)
4298 mdi_pathinfo_t
*pip
;
4301 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4302 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4303 !_TYPE_DEFINED(flags
))
4304 return (DDI_PROP_INVAL_ARG
);
4306 pip
= _DEVICE_PIP(sd
, flags
);
4308 rv
= mdi_prop_lookup_byte_array(pip
, name
, data
, nelements
);
4310 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4311 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4312 name
, data
, nelements
);
4317 scsi_device_prop_lookup_int_array(struct scsi_device
*sd
, uint_t flags
,
4318 char *name
, int **data
, uint_t
*nelements
)
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_int_array(pip
, name
, data
, nelements
);
4332 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4333 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4334 name
, data
, nelements
);
4340 scsi_device_prop_lookup_string(struct scsi_device
*sd
, uint_t flags
,
4341 char *name
, char **data
)
4343 mdi_pathinfo_t
*pip
;
4346 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4347 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4348 !_TYPE_DEFINED(flags
))
4349 return (DDI_PROP_INVAL_ARG
);
4351 pip
= _DEVICE_PIP(sd
, flags
);
4353 rv
= mdi_prop_lookup_string(pip
, name
, data
);
4355 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, sd
->sd_dev
,
4356 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4362 scsi_device_prop_lookup_string_array(struct scsi_device
*sd
, uint_t flags
,
4363 char *name
, char ***data
, uint_t
*nelements
)
4365 mdi_pathinfo_t
*pip
;
4368 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4369 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4370 !_TYPE_DEFINED(flags
))
4371 return (DDI_PROP_INVAL_ARG
);
4373 pip
= _DEVICE_PIP(sd
, flags
);
4375 rv
= mdi_prop_lookup_string_array(pip
, name
, data
, nelements
);
4377 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4378 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4379 name
, data
, nelements
);
4384 scsi_device_prop_update_byte_array(struct scsi_device
*sd
, uint_t flags
,
4385 char *name
, uchar_t
*data
, uint_t nelements
)
4387 mdi_pathinfo_t
*pip
;
4390 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4391 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4392 !_TYPE_DEFINED(flags
))
4393 return (DDI_PROP_INVAL_ARG
);
4395 pip
= _DEVICE_PIP(sd
, flags
);
4397 rv
= mdi_prop_update_byte_array(pip
, name
, data
, nelements
);
4399 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4400 name
, data
, nelements
);
4405 scsi_device_prop_update_int(struct scsi_device
*sd
, uint_t flags
,
4406 char *name
, int data
)
4408 mdi_pathinfo_t
*pip
;
4411 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4412 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4413 !_TYPE_DEFINED(flags
))
4414 return (DDI_PROP_INVAL_ARG
);
4416 pip
= _DEVICE_PIP(sd
, flags
);
4418 rv
= mdi_prop_update_int(pip
, name
, data
);
4420 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, sd
->sd_dev
,
4426 scsi_device_prop_update_int64(struct scsi_device
*sd
, uint_t flags
,
4427 char *name
, int64_t data
)
4429 mdi_pathinfo_t
*pip
;
4432 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4433 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4434 !_TYPE_DEFINED(flags
))
4435 return (DDI_PROP_INVAL_ARG
);
4437 pip
= _DEVICE_PIP(sd
, flags
);
4439 rv
= mdi_prop_update_int64(pip
, name
, data
);
4441 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, sd
->sd_dev
,
4447 scsi_device_prop_update_int_array(struct scsi_device
*sd
, uint_t flags
,
4448 char *name
, int *data
, uint_t nelements
)
4450 mdi_pathinfo_t
*pip
;
4453 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4454 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4455 !_TYPE_DEFINED(flags
))
4456 return (DDI_PROP_INVAL_ARG
);
4458 pip
= _DEVICE_PIP(sd
, flags
);
4460 rv
= mdi_prop_update_int_array(pip
, name
, data
, nelements
);
4462 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4463 name
, data
, nelements
);
4468 scsi_device_prop_update_string(struct scsi_device
*sd
, uint_t flags
,
4469 char *name
, char *data
)
4471 mdi_pathinfo_t
*pip
;
4474 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4475 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4476 !_TYPE_DEFINED(flags
))
4477 return (DDI_PROP_INVAL_ARG
);
4479 pip
= _DEVICE_PIP(sd
, flags
);
4481 rv
= mdi_prop_update_string(pip
, name
, data
);
4483 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, sd
->sd_dev
,
4489 scsi_device_prop_update_string_array(struct scsi_device
*sd
, uint_t flags
,
4490 char *name
, char **data
, uint_t nelements
)
4492 mdi_pathinfo_t
*pip
;
4495 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4496 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4497 !_TYPE_DEFINED(flags
))
4498 return (DDI_PROP_INVAL_ARG
);
4500 pip
= _DEVICE_PIP(sd
, flags
);
4502 rv
= mdi_prop_update_string_array(pip
, name
, data
, nelements
);
4504 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4505 name
, data
, nelements
);
4510 scsi_device_prop_remove(struct scsi_device
*sd
, uint_t flags
, char *name
)
4512 mdi_pathinfo_t
*pip
;
4515 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4516 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4517 !_TYPE_DEFINED(flags
))
4518 return (DDI_PROP_INVAL_ARG
);
4520 pip
= _DEVICE_PIP(sd
, flags
);
4522 rv
= mdi_prop_remove(pip
, name
);
4524 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, sd
->sd_dev
, name
);
4529 scsi_device_prop_free(struct scsi_device
*sd
, uint_t flags
, void *data
)
4531 mdi_pathinfo_t
*pip
;
4533 ASSERT(sd
&& data
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4534 if ((sd
== NULL
) || (data
== NULL
) || (sd
->sd_dev
== NULL
) ||
4535 !_TYPE_DEFINED(flags
))
4538 pip
= _DEVICE_PIP(sd
, flags
);
4540 (void) mdi_prop_free(data
);
4542 ddi_prop_free(data
);
4545 /* SMP device property interfaces */
4547 smp_device_prop_get_int(struct smp_device
*smp_sd
, char *name
, int defval
)
4551 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4552 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4555 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4556 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4562 smp_device_prop_get_int64(struct smp_device
*smp_sd
, char *name
, int64_t defval
)
4566 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4567 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4570 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4571 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4576 smp_device_prop_lookup_byte_array(struct smp_device
*smp_sd
, char *name
,
4577 uchar_t
**data
, uint_t
*nelements
)
4581 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4582 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4583 return (DDI_PROP_INVAL_ARG
);
4585 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4586 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4587 name
, data
, nelements
);
4592 smp_device_prop_lookup_int_array(struct smp_device
*smp_sd
, char *name
,
4593 int **data
, uint_t
*nelements
)
4597 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4598 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4599 return (DDI_PROP_INVAL_ARG
);
4601 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4602 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4603 name
, data
, nelements
);
4609 smp_device_prop_lookup_string(struct smp_device
*smp_sd
, char *name
,
4614 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4615 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4616 return (DDI_PROP_INVAL_ARG
);
4618 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4619 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4625 smp_device_prop_lookup_string_array(struct smp_device
*smp_sd
, char *name
,
4626 char ***data
, uint_t
*nelements
)
4630 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4631 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4632 return (DDI_PROP_INVAL_ARG
);
4634 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4635 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4636 name
, data
, nelements
);
4641 smp_device_prop_update_byte_array(struct smp_device
*smp_sd
, char *name
,
4642 uchar_t
*data
, uint_t nelements
)
4646 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4647 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4648 return (DDI_PROP_INVAL_ARG
);
4650 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4651 name
, data
, nelements
);
4656 smp_device_prop_update_int(struct smp_device
*smp_sd
, char *name
, int data
)
4660 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4661 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4662 return (DDI_PROP_INVAL_ARG
);
4664 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4670 smp_device_prop_update_int64(struct smp_device
*smp_sd
, char *name
,
4675 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4676 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4677 return (DDI_PROP_INVAL_ARG
);
4679 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4685 smp_device_prop_update_int_array(struct smp_device
*smp_sd
, char *name
,
4686 int *data
, uint_t nelements
)
4690 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4691 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4692 return (DDI_PROP_INVAL_ARG
);
4694 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4695 name
, data
, nelements
);
4700 smp_device_prop_update_string(struct smp_device
*smp_sd
, char *name
, char *data
)
4704 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4705 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4706 return (DDI_PROP_INVAL_ARG
);
4708 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4714 smp_device_prop_update_string_array(struct smp_device
*smp_sd
, char *name
,
4715 char **data
, uint_t nelements
)
4719 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4720 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4721 return (DDI_PROP_INVAL_ARG
);
4723 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4724 name
, data
, nelements
);
4729 smp_device_prop_remove(struct smp_device
*smp_sd
, char *name
)
4733 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4734 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4735 return (DDI_PROP_INVAL_ARG
);
4737 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
, name
);
4742 smp_device_prop_free(struct smp_device
*smp_sd
, void *data
)
4744 ASSERT(smp_sd
&& data
&& smp_sd
->smp_sd_dev
);
4745 if ((smp_sd
== NULL
) || (data
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4748 ddi_prop_free(data
);
4752 * scsi_hba_ua_set: given "unit-address" string, set properties.
4754 * Function to set the properties on a devinfo or pathinfo node from
4755 * the "unit-address" part of a "name@unit-address" /devices path 'name'
4758 * This function works in conjunction with scsi_ua_get()/scsi_hba_ua_get()
4759 * (and possibly with an HBA driver's tran_tgt_init() implementation).
4762 scsi_hba_ua_set(char *ua
, dev_info_t
*dchild
, mdi_pathinfo_t
*pchild
)
4772 /* Caller must choose to decorate devinfo *or* pathinfo */
4773 ASSERT((dchild
!= NULL
) ^ (pchild
!= NULL
));
4774 if (dchild
&& pchild
)
4778 * generic implementation based on "tgt,lun[,sfunc]" address form.
4779 * parse hex "tgt" part of "tgt,lun[,sfunc]"
4782 tgt_port_end
= NULL
;
4783 for (tgt
= 0; *p
&& *p
!= ','; p
++) {
4784 if (*p
>= '0' && *p
<= '9')
4785 tgt
= (tgt
<< 4) + (*p
- '0');
4786 else if (*p
>= 'a' && *p
<= 'f')
4787 tgt
= (tgt
<< 4) + 10 + (*p
- 'a');
4789 tgt
= -1; /* non-numeric */
4792 * if non-numeric or our of range set tgt to -1 and
4797 for (; *p
&& *p
!= ','; p
++)
4804 /* parse hex ",lun" part of "tgt,lun[,sfunc]" */
4807 for (lun64
= 0; *p
&& *p
!= ','; p
++) {
4808 if (*p
>= '0' && *p
<= '9')
4809 lun64
= (lun64
<< 4) + (*p
- '0');
4810 else if (*p
>= 'a' && *p
<= 'f')
4811 lun64
= (lun64
<< 4) + 10 + (*p
- 'a');
4816 /* parse hex ",sfunc" part of "tgt,lun[,sfunc]" */
4819 for (sfunc
= 0; *p
; p
++) {
4820 if (*p
>= '0' && *p
<= '9')
4821 sfunc
= (sfunc
<< 4) + (*p
- '0');
4822 else if (*p
>= 'a' && *p
<= 'f')
4823 sfunc
= (sfunc
<< 4) + 10 + (*p
- 'a');
4832 * Decorate a devinfo node with unit address properties.
4833 * This adds the the addressing properties needed to
4834 * DDI_CTLOPS_UNINITCHILD the devinfo node (i.e. perform
4835 * the reverse operation - form unit address from properties).
4837 if ((tgt
!= -1) && (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4838 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4842 tgt_port_len
= tgt_port_end
- ua
+ 1;
4843 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4844 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4845 if (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
4846 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4848 kmem_free(tgt_port
, tgt_port_len
);
4851 kmem_free(tgt_port
, tgt_port_len
);
4854 /* Set the appropriate lun properties. */
4855 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4856 if (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4857 SCSI_ADDR_PROP_LUN
, (int)lun64
) != DDI_PROP_SUCCESS
)
4860 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, dchild
,
4861 SCSI_ADDR_PROP_LUN64
, lun64
) != DDI_PROP_SUCCESS
)
4864 /* Set the sfunc property */
4865 if ((sfunc
!= -1) &&
4866 (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4867 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4869 } else if (pchild
) {
4871 * Decorate a pathinfo node with unit address properties.
4873 if ((tgt
!= -1) && (mdi_prop_update_int(pchild
,
4874 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4878 tgt_port_len
= tgt_port_end
- ua
+ 1;
4879 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4880 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4881 if (mdi_prop_update_string(pchild
,
4882 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4884 kmem_free(tgt_port
, tgt_port_len
);
4887 kmem_free(tgt_port
, tgt_port_len
);
4890 /* Set the appropriate lun properties */
4891 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4892 if (mdi_prop_update_int(pchild
, SCSI_ADDR_PROP_LUN
,
4893 (int)lun64
) != DDI_PROP_SUCCESS
)
4897 if (mdi_prop_update_int64(pchild
, SCSI_ADDR_PROP_LUN64
,
4898 lun64
) != DDI_PROP_SUCCESS
)
4901 /* Set the sfunc property */
4902 if ((sfunc
!= -1) &&
4903 (mdi_prop_update_int(pchild
,
4904 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4911 * Private ndi_devi_find/mdi_pi_find implementation - find the child
4912 * dev_info/path_info of self whose phci name matches "name@caddr".
4913 * We have our own implementation because we need to search with both
4914 * forms of sibling lists (dev_info and path_info) and we need to be able
4915 * to search with a NULL name in order to find siblings already associated
4916 * with a given unit-address (same @addr). NOTE: NULL name search will never
4917 * return probe node.
4919 * If pchildp is NULL and we find a pathinfo child, we return the client
4920 * devinfo node in *dchildp.
4922 * The init flag argument should be clear when called from places where
4923 * recursion could occur (like scsi_busctl_initchild) and when the caller
4924 * has already performed a search for name@addr with init set (performance).
4926 * Future: Integrate ndi_devi_findchild_by_callback into scsi_findchild.
4929 scsi_findchild(dev_info_t
*self
, char *name
, char *addr
, int init
,
4930 dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
)
4932 dev_info_t
*dchild
; /* devinfo child */
4933 mdi_pathinfo_t
*pchild
; /* pathinfo child */
4934 int found
= CHILD_TYPE_NONE
;
4937 ASSERT(self
&& DEVI_BUSY_OWNED(self
));
4938 ASSERT(addr
&& dchildp
);
4939 if ((self
== NULL
) || (addr
== NULL
) || (dchildp
== NULL
))
4940 return (CHILD_TYPE_NONE
);
4948 /* Walk devinfo child list to find a match */
4949 for (dchild
= ddi_get_child(self
); dchild
;
4950 dchild
= ddi_get_next_sibling(dchild
)) {
4951 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
4954 daddr
= ddi_get_name_addr(dchild
);
4955 if (daddr
&& (strcmp(addr
, daddr
) == 0) &&
4957 (strcmp(name
, DEVI(dchild
)->devi_node_name
) == 0))) {
4959 * If we are asked to find "anything" at a given
4960 * unit-address (name == NULL), we don't realy want
4961 * to find the 'probe' node. The existance of
4962 * a probe node on a 'name == NULL' search should
4963 * fail. This will trigger slow-path code where
4964 * we explicity look for, and synchronize against,
4965 * a node named "probe" at the unit-address.
4967 if ((name
== NULL
) &&
4968 scsi_hba_devi_is_barrier(dchild
)) {
4969 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4970 "%s@%s 'probe' devinfo found, skip",
4971 name
? name
: "", addr
));
4975 /* We have found a match. */
4976 found
|= CHILD_TYPE_DEVINFO
;
4977 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4978 "%s@%s devinfo found", name
? name
: "", addr
));
4979 *dchildp
= dchild
; /* devinfo found */
4985 * Walk pathinfo child list to find a match.
4987 * NOTE: Unlike devinfo nodes, pathinfo nodes have a string searchable
4988 * unit-address from creation - so there is no need for an 'init'
4989 * search block of code for pathinfo nodes below.
4991 pchild
= mdi_pi_find(self
, NULL
, addr
);
4994 * NOTE: If name specified and we match a pathinfo unit
4995 * address, we don't check the client node name.
4998 *ppi
= mdi_pi_get_path_instance(pchild
);
4999 found
|= CHILD_TYPE_PATHINFO
;
5002 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5003 "%s pathinfo found", mdi_pi_spathname(pchild
)));
5004 *pchildp
= pchild
; /* pathinfo found */
5005 } else if (*dchildp
== NULL
) {
5007 * Did not find a devinfo node, found a pathinfo node,
5008 * but caller did not ask us to return a pathinfo node:
5009 * we return the 'client' devinfo node instead (but
5010 * with CHILD_TYPE_PATHINFO 'found' return value).
5012 dchild
= mdi_pi_get_client(pchild
);
5013 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5014 "%s pathinfo found, client switch",
5015 mdi_pi_spathname(pchild
)));
5018 * A pathinfo node always has a 'client' devinfo node,
5019 * but we need to ensure that the 'client' is
5020 * initialized and has a scsi_device structure too.
5023 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
) {
5024 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5025 "%s found client, initchild",
5026 mdi_pi_spathname(pchild
)));
5027 (void) ddi_initchild(ddi_get_parent(dchild
),
5030 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
) {
5031 /* client found and initialized */
5034 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5035 "%s found client, but failed initchild",
5036 mdi_pi_spathname(pchild
)));
5041 /* Try devinfo again with initchild of uninitialized nodes */
5042 if ((found
== CHILD_TYPE_NONE
) && init
) {
5043 for (dchild
= ddi_get_child(self
); dchild
;
5044 dchild
= ddi_get_next_sibling(dchild
)) {
5045 /* skip if checked above */
5046 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
)
5048 /* attempt initchild to establish unit-address */
5049 (void) ddi_initchild(self
, dchild
);
5050 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
5052 daddr
= ddi_get_name_addr(dchild
);
5054 ((name
== NULL
) || (strcmp(name
,
5055 DEVI(dchild
)->devi_node_name
) == 0)) &&
5056 (strcmp(addr
, daddr
) == 0)) {
5057 found
|= CHILD_TYPE_DEVINFO
;
5058 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5059 "%s@%s devinfo found post initchild",
5060 name
? name
: "", addr
));
5061 *dchildp
= dchild
; /* devinfo found */
5062 break; /* node found */
5068 * We should never find devinfo and pathinfo at the same
5071 ASSERT(found
!= (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
));
5072 if (found
== (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
)) {
5073 found
= CHILD_TYPE_NONE
;
5081 * Given information about a child device (contained on probe node) construct
5082 * and return a pointer to the dynamic SID devinfo node associated with the
5083 * device. In the creation of this SID node a compatible property for the
5084 * device is formed and used to establish a nodename (via
5085 * /etc/nodename_aliases) and to bind a driver (via /etc/driver_aliases).
5087 * If this routine is called then we got a response from a device and
5088 * obtained the inquiry data from the device. Some inquiry results indicate
5089 * that the specific LUN we addressed does not exist, and we don't want to
5090 * bind a standard target driver to the node we create. Even though the
5091 * specific LUN is not usable, the framework may still want to bind a
5092 * target driver to the device for internal communication with the device -
5093 * an example would be issuing a report_lun to enumerate other LUNs under a
5094 * DPQ_NEVER LUN0. Another example would be wanting to known that the
5095 * DPQ_NEVER LUN0 device exists in BUS_CONFIG_ONE for non-existent LUN
5096 * caching optimizations. To support this we let the caller specify a
5097 * compatible property (or driver). If LUN0 inquiry data indicates that the
5098 * LUN does not exist then we establish compat0 as the highest precedence(0)
5099 * compatible form. If used, this compat0 driver will never be called on to
5100 * issue external commands to the device.
5102 * If no driver binds to the device using driver_alias we establish the driver
5103 * passed in as the node name.
5106 extern int e_devid_cache_pathinfo(mdi_pathinfo_t
*, ddi_devid_t
);
5109 scsi_device_createchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5110 struct scsi_device
*sdprobe
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
)
5120 char **compat
= NULL
;
5122 dev_info_t
*dchild
= NULL
;
5123 mdi_pathinfo_t
*pchild
= NULL
;
5124 dev_info_t
*probe
= sdprobe
->sd_dev
;
5125 struct scsi_inquiry
*inq
= sdprobe
->sd_inq
;
5126 uchar_t
*inq80
= NULL
;
5127 uchar_t
*inq83
= NULL
;
5128 uint_t inq80len
, inq83len
;
5129 char *binding_set
= NULL
;
5134 int have_cdevid
= 0;
5138 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5139 ASSERT(dchildp
&& pchildp
);
5142 * Determine the lun and whether the lun exists. We may need to create
5143 * a node for LUN0 (with compat0 driver binding) even if the lun does
5144 * not exist - so we can run report_lun to find additional LUNs.
5146 lun64
= scsi_addr_to_lun64(addr
);
5147 dtype
= inq
->inq_dtype
& DTYPE_MASK
; /* device */
5148 dpq
= inq
->inq_dtype
& DPQ_MASK
;
5149 dpq_vu
= inq
->inq_dtype
& DPQ_VUNIQ
? 1 : 0;
5151 dtype_node
= scsi_addr_to_sfunc(addr
); /* secondary function */
5152 if (dtype_node
== -1)
5153 dtype_node
= dtype
; /* node for device */
5155 lunexists
= (dtype
!= dtype_node
) || /* override */
5156 ((dpq_vu
== 0) && (dpq
== DPQ_POSSIBLE
)) || /* ANSII */
5157 (dpq_vu
&& (lun64
== 0)); /* VU LUN0 */
5158 if (dtype
== DTYPE_UNKNOWN
)
5161 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5162 "@%s dtype %x %x dpq_vu %d dpq %x: %d",
5163 addr
, dtype
, dtype_node
, dpq_vu
, dpq
, lunexists
));
5165 /* A non-existent LUN0 uses compatible_nodev. */
5167 compat0
= NULL
; /* compat0 not needed */
5168 } else if (lun64
== 0) {
5169 compat0
= compatible_nodev
;
5170 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5171 "@%s lun 0 with compat0 %s", addr
, compat0
));
5173 goto out
; /* no node created */
5175 /* Obtain identity information from probe node. */
5176 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5177 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-80",
5178 &inq80
, &inq80len
) != DDI_PROP_SUCCESS
)
5180 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5181 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-83",
5182 &inq83
, &inq83len
) != DDI_PROP_SUCCESS
)
5185 /* Get "scsi-binding-set" property (if there is one). */
5186 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
5187 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
5188 "scsi-binding-set", &binding_set
) == DDI_PROP_SUCCESS
)
5189 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
5190 "binding_set '%s'", binding_set
));
5192 /* determine the node name and compatible information */
5193 scsi_hba_ident_nodename_compatible_get(inq
,
5194 inq80
, inq80len
, inq83
, inq83len
, binding_set
, dtype_node
,
5195 compat0
, &nname
, &dname
, &compat
, &ncompat
);
5197 if (nname
== NULL
) {
5199 * We will not be able to create a node because we could not
5200 * determine a node name. Print out a NODRIVER level warning
5201 * message with the compatible forms for the device. Note that
5202 * there may be a driver.conf node that attaches to the device,
5203 * which is why we only produce this warning message for debug
5206 SCSI_HBA_LOG((_LOG(1), NULL
, self
,
5207 "no node_name for device @%s:\n compatible: %s",
5213 * FUTURE: some day we may want an accurate "compatible" on the probe
5214 * node so that vhci_is_dev_supported() in scsi_vhci could, at
5215 * least in part, determine/configure based on "compatible".
5217 * if (ndi_prop_update_string_array(DDI_DEV_T_NONE, probe,
5218 * "compatible", compat, ncompat) != DDI_PROP_SUCCESS) {
5219 * SCSI_HBA_LOG((_LOG(3), self, NULL,
5220 * "%s@%s failed probe compatible decoration",
5226 /* Encode devid from identity information. */
5227 if (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, dname
,
5228 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
5229 &devid
) == DDI_SUCCESS
) {
5232 /* Attempt to form guid from devid. */
5233 guid
= ddi_devid_to_guid(devid
);
5235 /* Produce string devid for debug. */
5236 devid_str
= ddi_devid_str_encode(devid
, NULL
);
5237 SCSI_HBA_LOG((_LOG(3), self
, probe
, "devid '%s' guid '%s'",
5238 devid_str
? devid_str
: "NULL", guid
? guid
: "NULL"));
5239 ddi_devid_str_free(devid_str
);
5244 * Determine if the device should be enumerated as under the vHCI
5245 * (client node) or under the pHCI. By convention scsi_vhci expects
5246 * the "cinfo" argument identity information to be represented as a
5247 * devinfo node with the needed information (i.e. the pHCI probe node).
5249 if ((guid
== NULL
) ||
5250 (mdi_is_dev_supported(MDI_HCI_CLASS_SCSI
, self
, sdprobe
) !=
5252 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==> devinfo"));
5255 * Enumerate under pHCI:
5257 * Create dynamic SID dchild node. No attempt is made to
5258 * transfer information (except the addressing and identity
5259 * information) from the probe node to the dynamic node since
5260 * there may be HBA specific side effects that the framework
5261 * does not known how to transfer.
5263 ndi_devi_alloc_sleep(self
, nname
,
5264 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
5267 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5270 * Decorate new node with addressing properties (via
5271 * scsi_hba_ua_set()), compatible, identity information, and
5274 if ((scsi_hba_ua_set(addr
, dchild
, NULL
) == 0) ||
5275 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, dchild
,
5276 "compatible", compat
, ncompat
) != DDI_PROP_SUCCESS
) ||
5277 (inq80
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5278 dchild
, "inquiry-page-80", inq80
, inq80len
) !=
5279 DDI_PROP_SUCCESS
)) ||
5280 (inq83
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5281 dchild
, "inquiry-page-83", inq83
, inq83len
) !=
5282 DDI_PROP_SUCCESS
)) ||
5283 (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
5284 "class", "scsi") != DDI_PROP_SUCCESS
)) {
5285 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5286 "devinfo @%s failed decoration", addr
));
5287 (void) scsi_hba_remove_node(dchild
);
5292 /* Bind the driver */
5293 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5294 /* need to bind in order to register a devid */
5295 SCSI_HBA_LOG((_LOGCFG
, NULL
, dchild
,
5296 "devinfo @%s created, no driver-> "
5297 "no devid_register", addr
));
5301 /* Register devid */
5303 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5304 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5305 "devinfo @%s created, "
5306 "devid register failed", addr
));
5308 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5309 "devinfo @%s created with devid", addr
));
5311 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5312 "devinfo @%s created, no devid", addr
));
5315 * Enumerate under vHCI:
5317 * Create a pathinfo pchild node.
5319 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==>pathinfo"));
5321 if (mdi_pi_alloc_compatible(self
, nname
, guid
, addr
, compat
,
5322 ncompat
, 0, &pchild
) != MDI_SUCCESS
) {
5323 SCSI_HBA_LOG((_LOG(2), self
, probe
,
5324 "pathinfo alloc failed"));
5329 dchild
= mdi_pi_get_client(pchild
);
5331 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5334 * Decorate new node with addressing properties via
5335 * scsi_hba_ua_set().
5337 if (scsi_hba_ua_set(addr
, NULL
, pchild
) == 0) {
5338 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5339 "pathinfo %s decoration failed",
5340 mdi_pi_spathname(pchild
)));
5341 (void) mdi_pi_free(pchild
, 0);
5346 /* Bind the driver */
5347 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5348 /* need to bind in order to register a devid */
5349 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
5350 "pathinfo %s created, no client driver-> "
5351 "no devid_register", mdi_pi_spathname(pchild
)));
5355 /* Watch out for inconsistancies in devids. */
5356 if (ddi_devid_get(dchild
, &cdevid
) == DDI_SUCCESS
)
5359 if (have_devid
&& !have_cdevid
) {
5360 /* Client does not yet have devid, register ours. */
5361 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5362 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5363 "pathinfo %s created, "
5364 "devid register failed",
5365 mdi_pi_spathname(pchild
)));
5367 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5368 "pathinfo %s created with devid",
5369 mdi_pi_spathname(pchild
)));
5370 } else if (have_devid
&& have_cdevid
) {
5372 * We have devid and client already has devid:
5373 * they must be the same.
5375 if (ddi_devid_compare(cdevid
, devid
) != 0) {
5376 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5377 "mismatched devid on path %s",
5378 mdi_pi_spathname(pchild
)));
5380 } else if (!have_devid
&& have_cdevid
) {
5382 * Client already has a devid, but we don't:
5383 * we should not have missing devids.
5385 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5386 "missing devid on path %s",
5387 mdi_pi_spathname(pchild
)));
5388 } else if (!have_cdevid
&& !have_devid
) {
5389 /* devid not supported */
5390 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5391 "pathinfo %s created, no devid",
5392 mdi_pi_spathname(pchild
)));
5396 * The above has registered devid for the device under
5397 * the client node. Now register it under the full pHCI
5398 * path to the device. We'll get an entry equivalent to
5399 * booting with mpxio disabled. This is needed for
5400 * telemetry during enumeration.
5402 if (e_devid_cache_pathinfo(pchild
, devid
) == DDI_SUCCESS
) {
5403 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5404 "pathinfo @%s created with devid", addr
));
5406 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5407 "pathinfo @%s devid cache failed", addr
));
5411 /* free the node name and compatible information */
5412 out
: if (have_devid
)
5413 ddi_devid_free(devid
);
5415 ddi_devid_free(cdevid
);
5417 ddi_devid_free_guid(guid
);
5419 scsi_hba_ident_nodename_compatible_free(nname
, dname
, compat
);
5421 ddi_prop_free(inq80
);
5423 ddi_prop_free(inq83
);
5425 ddi_prop_free(binding_set
);
5427 /* return child_type results */
5431 return (CHILD_TYPE_PATHINFO
);
5432 } else if (dchild
) {
5435 return (CHILD_TYPE_DEVINFO
);
5438 return (CHILD_TYPE_NONE
);
5442 * Call scsi_device_createchild and then initchild the new node.
5445 scsi_device_configchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5446 struct scsi_device
*sdprobe
, int *circp
, int *ppi
)
5450 mdi_pathinfo_t
*pchild
;
5454 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5458 child_type
= scsi_device_createchild(self
, addr
, se
, sdprobe
,
5462 * Prevent multiple initialized (tran_tgt_init) nodes associated with
5463 * the same @addr at the same time by calling tran_tgt_free() on the
5464 * probe node prior to promotion of the 'real' node. After the call
5465 * to scsi_hba_barrier_tran_tgt_free(), the HBA no longer has any
5466 * probe node context.
5468 scsi_hba_barrier_tran_tgt_free(sdprobe
->sd_dev
);
5470 switch (child_type
) {
5471 case CHILD_TYPE_NONE
:
5475 case CHILD_TYPE_PATHINFO
:
5477 * Online pathinfo: Hold the path and exit the pHCI while
5478 * calling mdi_pi_online() to avoid deadlock with power
5479 * management of pHCI.
5481 ASSERT(MDI_PHCI(self
));
5482 mdi_hold_path(pchild
);
5483 scsi_hba_devi_exit_phci(self
, *circp
);
5485 rval
= mdi_pi_online(pchild
, 0);
5487 scsi_hba_devi_enter_phci(self
, circp
);
5488 mdi_rele_path(pchild
);
5490 if (rval
!= MDI_SUCCESS
) {
5491 /* pathinfo form of "failed during tran_tgt_init" */
5492 scsi_enumeration_failed(NULL
, se
,
5493 mdi_pi_spathname(pchild
), "path online");
5494 (void) mdi_pi_free(pchild
, 0);
5499 * Return the path_instance of the pathinfo node.
5501 * NOTE: We assume that sd_inq is not path-specific.
5504 *ppi
= mdi_pi_get_path_instance(pchild
);
5508 * Fallthrough into CHILD_TYPE_DEVINFO code to promote
5509 * the 'client' devinfo node as a dchild.
5511 dchild
= mdi_pi_get_client(pchild
);
5512 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5513 "pathinfo online successful"));
5516 case CHILD_TYPE_DEVINFO
:
5518 * For now, we ndi_devi_online() the child because some other
5519 * parts of the IO framework, like degenerate devid code,
5520 * depend on bus_config driving nodes to DS_ATTACHED. At some
5521 * point in the future, to keep things light-weight, we would
5522 * like to change the ndi_devi_online call below to be
5524 * if (ddi_initchild(self, dchild) != DDI_SUCCESS)
5526 * This would promote the node so that framework code could
5527 * find the child with an @addr search, but does not incur
5528 * attach(9E) overhead for BUS_CONFIG_ALL cases where the
5529 * framework is not interested in attach of the node.
5531 * NOTE: If the addr specified has incorrect syntax (busconfig
5532 * one of bogus /devices path) then call below can fail.
5534 if (ndi_devi_online(dchild
, 0) != NDI_SUCCESS
) {
5535 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5536 "devinfo online failed"));
5538 /* failed online does not remove the node */
5539 (void) scsi_hba_remove_node(dchild
);
5542 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5543 "devinfo initchild successful"));
5551 scsi_hba_pkt_comp(struct scsi_pkt
*pkt
)
5553 scsi_hba_tran_t
*tran
;
5559 * Catch second call on the same packet before doing anything else.
5561 if (pkt
->pkt_flags
& FLAG_PKT_COMP_CALLED
) {
5568 "%s duplicate scsi_hba_pkt_comp(9F) on same scsi_pkt(9S)",
5569 mod_containing_pc(caller()));
5572 pkt
->pkt_flags
|= FLAG_PKT_COMP_CALLED
;
5574 if (pkt
->pkt_comp
== NULL
)
5578 * For HBA drivers that implement tran_setup_pkt(9E), if we are
5579 * completing a 'consistent' mode DMA operation then we must
5580 * perform dma_sync prior to calling pkt_comp to ensure that
5581 * the target driver sees the correct data in memory.
5583 ASSERT((pkt
->pkt_flags
& FLAG_NOINTR
) == 0);
5584 if (((pkt
->pkt_dma_flags
& DDI_DMA_CONSISTENT
) &&
5585 (pkt
->pkt_dma_flags
& DDI_DMA_READ
)) &&
5586 ((P_TO_TRAN(pkt
)->tran_setup_pkt
) != NULL
)) {
5591 * If the HBA driver is using SCSAv3 scsi_hba_tgtmap_create enumeration
5592 * then we detect the special ASC/ASCQ completion codes that indicate
5593 * that the lun configuration of a target has changed. Since we need to
5594 * be determine scsi_device given scsi_address enbedded in
5595 * scsi_pkt (via scsi_address_device(9F)), we also require use of
5596 * SCSI_HBA_ADDR_COMPLEX.
5598 tran
= pkt
->pkt_address
.a_hba_tran
;
5600 if ((tran
->tran_tgtmap
== NULL
) ||
5601 !(tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
))
5602 goto comp
; /* not using tgtmap */
5605 * Check for lun-change notification and queue the scsi_pkt for
5606 * lunchg1 processing. The 'pkt_comp' call to the target driver
5607 * is part of lunchg1 processing.
5609 if ((pkt
->pkt_reason
== CMD_CMPLT
) &&
5610 (((*pkt
->pkt_scbp
) & STATUS_MASK
) == STATUS_CHECK
) &&
5611 (pkt
->pkt_state
& STATE_ARQ_DONE
)) {
5612 sensep
= (uint8_t *)&(((struct scsi_arq_status
*)(uintptr_t)
5613 (pkt
->pkt_scbp
))->sts_sensedata
);
5614 if (((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5615 (scsi_sense_asc(sensep
) == 0x3f) &&
5616 (scsi_sense_ascq(sensep
) == 0x0e)) ||
5618 ((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5619 (scsi_sense_asc(sensep
) == 0x25) &&
5620 (scsi_sense_ascq(sensep
) == 0x00))) {
5622 * The host adaptor is done with the packet, we use
5623 * pkt_stmp stage-temporary to link the packet for
5624 * lunchg1 processing.
5626 * NOTE: pkt_ha_private is not available since its use
5627 * extends to tran_teardown_pkt.
5629 mutex_enter(&scsi_lunchg1_mutex
);
5630 pkt
->pkt_stmp
= scsi_lunchg1_list
;
5631 scsi_lunchg1_list
= pkt
;
5632 if (pkt
->pkt_stmp
== NULL
)
5633 (void) cv_signal(&scsi_lunchg1_cv
);
5634 mutex_exit(&scsi_lunchg1_mutex
);
5639 comp
: (*pkt
->pkt_comp
)(pkt
);
5643 * return 1 if the specified node is a barrier/probe node
5646 scsi_hba_devi_is_barrier(dev_info_t
*probe
)
5648 if (probe
&& (strcmp(ddi_node_name(probe
), "probe") == 0))
5654 * A host adapter driver is easier to write if we prevent multiple initialized
5655 * (tran_tgt_init) scsi_device structures to the same unit-address at the same
5656 * time. We prevent this from occurring all the time during the barrier/probe
5657 * node to real child hand-off by calling scsi_hba_barrier_tran_tgt_free
5658 * on the probe node prior to ddi_inichild of the 'real' node. As part of
5659 * this early tran_tgt_free implementation, we must also call this function
5660 * as we put a probe node on the scsi_hba_barrier_list.
5663 scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
)
5665 struct scsi_device
*sdprobe
;
5667 scsi_hba_tran_t
*tran
;
5669 ASSERT(probe
&& scsi_hba_devi_is_barrier(probe
));
5671 /* Return if we never called tran_tgt_init(9E). */
5672 if (i_ddi_node_state(probe
) < DS_INITIALIZED
)
5675 sdprobe
= ddi_get_driver_private(probe
);
5676 self
= ddi_get_parent(probe
);
5677 ASSERT(sdprobe
&& self
);
5678 tran
= ddi_get_driver_private(self
);
5681 if (tran
->tran_tgt_free
) {
5683 * To correctly support TRAN_CLONE, we need to use the same
5684 * cloned scsi_hba_tran(9S) structure for both tran_tgt_init(9E)
5685 * and tran_tgt_free(9E).
5687 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
)
5688 tran
= sdprobe
->sd_address
.a_hba_tran
;
5690 if (!sdprobe
->sd_tran_tgt_free_done
) {
5691 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5692 "tran_tgt_free EARLY"));
5693 (*tran
->tran_tgt_free
) (self
, probe
, tran
, sdprobe
);
5694 sdprobe
->sd_tran_tgt_free_done
= 1;
5696 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5697 "tran_tgt_free EARLY already done"));
5703 * Add an entry to the list of barrier nodes to be asynchronously deleted by
5704 * the scsi_hba_barrier_daemon after the specified timeout. Nodes on
5705 * the barrier list are used to implement the bus_config probe cache
5706 * of non-existent devices. The nodes are at DS_INITIALIZED, so their
5707 * @addr is established for searching. Since devi_ref of a DS_INITIALIZED
5708 * node will *not* prevent demotion, demotion is prevented by setting
5709 * sd_uninit_prevent. Devinfo snapshots attempt to attach probe cache
5710 * nodes, and on failure attempt to demote the node (without the participation
5711 * of bus_unconfig) to DS_BOUND - this demotion is prevented via
5712 * sd_uninit_prevent causing any attempted DDI_CTLOPS_UNINITCHILD to fail.
5713 * Probe nodes are bound to nulldriver. The list is sorted by
5716 * NOTE: If we drove a probe node to DS_ATTACHED, we could use ndi_hold_devi()
5717 * to prevent demotion (instead of sd_uninit_prevent).
5720 scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
)
5722 struct scsi_hba_barrier
*nb
;
5723 struct scsi_hba_barrier
*b
;
5724 struct scsi_hba_barrier
**bp
;
5727 ASSERT(scsi_hba_devi_is_barrier(probe
));
5729 /* HBA is no longer responsible for nodes on the barrier list. */
5730 scsi_hba_barrier_tran_tgt_free(probe
);
5731 nb
= kmem_alloc(sizeof (struct scsi_hba_barrier
), KM_SLEEP
);
5732 mutex_enter(&scsi_hba_barrier_mutex
);
5733 endtime
= ddi_get_lbolt() + drv_usectohz(seconds
* MICROSEC
);
5734 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
;
5735 bp
= &b
->barrier_next
)
5736 if (b
->barrier_endtime
> endtime
)
5738 nb
->barrier_next
= *bp
;
5739 nb
->barrier_endtime
= endtime
;
5740 nb
->barrier_probe
= probe
;
5742 if (bp
== &scsi_hba_barrier_list
)
5743 (void) cv_signal(&scsi_hba_barrier_cv
);
5744 mutex_exit(&scsi_hba_barrier_mutex
);
5748 * Attempt to remove devinfo node node, return 1 if removed. We
5749 * don't try to remove barrier nodes that have sd_uninit_prevent set
5750 * (even though they should fail device_uninitchild).
5753 scsi_hba_remove_node(dev_info_t
*child
)
5755 dev_info_t
*self
= ddi_get_parent(child
);
5756 struct scsi_device
*sd
;
5760 char na
[SCSI_MAXNAMELEN
];
5762 scsi_hba_devi_enter(self
, &circ
);
5764 /* Honor sd_uninit_prevent on barrier nodes */
5765 if (scsi_hba_devi_is_barrier(child
)) {
5766 sd
= ddi_get_driver_private(child
);
5767 if (sd
&& sd
->sd_uninit_prevent
)
5772 (void) ddi_deviname(child
, na
);
5773 if (ddi_remove_child(child
, 0) != DDI_SUCCESS
) {
5774 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
5775 "remove_node failed"));
5777 child
= NULL
; /* child is gone */
5778 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5779 "remove_node removed %s", *na
? &na
[1] : na
));
5783 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "remove_node prevented"));
5785 scsi_hba_devi_exit(self
, circ
);
5790 * The asynchronous barrier deletion daemon. Waits for a barrier timeout
5791 * to expire, then deletes the barrier (removes it as a child).
5795 scsi_hba_barrier_daemon(void *arg
)
5797 struct scsi_hba_barrier
*b
;
5799 callb_cpr_t cprinfo
;
5803 CALLB_CPR_INIT(&cprinfo
, &scsi_hba_barrier_mutex
,
5804 callb_generic_cpr
, "scsi_hba_barrier_daemon");
5805 again
: mutex_enter(&scsi_hba_barrier_mutex
);
5807 b
= scsi_hba_barrier_list
;
5809 /* all barriers expired, wait for barrier_add */
5810 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5811 (void) cv_wait(&scsi_hba_barrier_cv
,
5812 &scsi_hba_barrier_mutex
);
5813 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_hba_barrier_mutex
);
5815 if (ddi_get_lbolt() >= b
->barrier_endtime
) {
5817 * Drop and retry if ordering issue. Do this
5818 * before calling scsi_hba_remove_node() and
5821 probe
= b
->barrier_probe
;
5822 self
= ddi_get_parent(probe
);
5823 if (scsi_hba_devi_tryenter(self
, &circ
) == 0) {
5824 delay
: mutex_exit(&scsi_hba_barrier_mutex
);
5829 /* process expired barrier */
5830 if (!scsi_hba_remove_node(probe
)) {
5831 /* remove failed, delay and retry */
5832 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5834 scsi_hba_devi_exit(self
, circ
);
5837 scsi_hba_barrier_list
= b
->barrier_next
;
5838 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5839 scsi_hba_devi_exit(self
, circ
);
5841 /* establish timeout for next barrier expire */
5842 (void) cv_timedwait(&scsi_hba_barrier_cv
,
5843 &scsi_hba_barrier_mutex
,
5844 b
->barrier_endtime
);
5851 * Remove all barriers associated with the specified HBA. This is called
5852 * from from the bus_unconfig implementation to remove probe nodes associated
5853 * with the specified HBA (self) so that probe nodes that have not expired
5854 * will not prevent DR of the HBA.
5857 scsi_hba_barrier_purge(dev_info_t
*self
)
5859 struct scsi_hba_barrier
**bp
;
5860 struct scsi_hba_barrier
*b
;
5862 mutex_enter(&scsi_hba_barrier_mutex
);
5863 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
; ) {
5864 if (ddi_get_parent(b
->barrier_probe
) == self
) {
5865 if (scsi_hba_remove_node(b
->barrier_probe
)) {
5866 *bp
= b
->barrier_next
;
5867 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5869 SCSI_HBA_LOG((_LOG(4), NULL
, b
->barrier_probe
,
5873 bp
= &b
->barrier_next
;
5876 mutex_exit(&scsi_hba_barrier_mutex
);
5880 * LUN-change processing daemons: processing occurs in two stages:
5882 * Stage 1: Daemon waits for a lunchg1 queued scsi_pkt, dequeues the pkt,
5883 * forms the path, completes the scsi_pkt (pkt_comp), and
5884 * queues the path for stage 2 processing. The use of stage 1
5885 * avoids issues related to memory allocation in interrupt context
5886 * (scsi_hba_pkt_comp()). We delay the pkt_comp completion until
5887 * after lunchg1 processing forms the path for stage 2 - this is
5888 * done to prevent the target driver from detaching until the
5889 * path formation is complete (driver with outstanding commands
5890 * should not detach).
5892 * Stage 2: Daemon waits for a lunchg2 queued request, dequeues the
5893 * request, and opens the path using ldi_open_by_name(). The
5894 * path opened uses a special "@taddr,*" unit address that will
5895 * trigger lun enumeration in scsi_hba_bus_configone(). We
5896 * trigger lun enumeration in stage 2 to avoid problems when
5897 * initial ASC/ASCQ trigger occurs during discovery.
5901 scsi_lunchg1_daemon(void *arg
)
5903 callb_cpr_t cprinfo
;
5904 struct scsi_pkt
*pkt
;
5905 scsi_hba_tran_t
*tran
;
5907 struct scsi_device
*sd
;
5909 char taddr
[SCSI_MAXNAMELEN
];
5910 char path
[MAXPATHLEN
];
5911 struct scsi_lunchg2
*lunchg2
;
5913 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg1_mutex
,
5914 callb_generic_cpr
, "scsi_lunchg1_daemon");
5915 mutex_enter(&scsi_lunchg1_mutex
);
5917 pkt
= scsi_lunchg1_list
;
5919 /* All lunchg1 processing requests serviced, wait. */
5920 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5921 (void) cv_wait(&scsi_lunchg1_cv
,
5922 &scsi_lunchg1_mutex
);
5923 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg1_mutex
);
5927 /* Unlink and perform lunchg1 processing on pkt. */
5928 scsi_lunchg1_list
= pkt
->pkt_stmp
;
5930 /* Determine initiator port (self) from the pkt_address. */
5931 tran
= pkt
->pkt_address
.a_hba_tran
;
5932 ASSERT(tran
&& tran
->tran_tgtmap
&& tran
->tran_iport_dip
);
5933 self
= tran
->tran_iport_dip
;
5936 * Determine scsi_devie from pkt_address (depends on
5937 * SCSI_HBA_ADDR_COMPLEX).
5939 sd
= scsi_address_device(&(pkt
->pkt_address
));
5942 (*pkt
->pkt_comp
)(pkt
);
5946 /* Determine unit-address from scsi_device. */
5947 ua
= scsi_device_unit_address(sd
);
5949 /* Extract taddr from the unit-address. */
5950 for (p
= taddr
; (*ua
!= ',') && (*ua
!= '\0'); )
5952 *p
= '\0'; /* NULL terminate taddr */
5955 * Form path using special "@taddr,*" notation to trigger
5958 (void) ddi_pathname(self
, path
);
5959 (void) strcat(path
, "/luns@");
5960 (void) strcat(path
, taddr
);
5961 (void) strcat(path
, ",*");
5964 * Now that we have the path, complete the pkt that
5965 * triggered lunchg1 processing.
5967 (*pkt
->pkt_comp
)(pkt
);
5969 /* Allocate element for stage2 processing queue. */
5970 lunchg2
= kmem_alloc(sizeof (*lunchg2
), KM_SLEEP
);
5971 lunchg2
->lunchg2_path
= strdup(path
);
5973 /* Queue and dispatch to stage 2. */
5974 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5975 "lunchg stage1: queue %s", lunchg2
->lunchg2_path
));
5976 mutex_enter(&scsi_lunchg2_mutex
);
5977 lunchg2
->lunchg2_next
= scsi_lunchg2_list
;
5978 scsi_lunchg2_list
= lunchg2
;
5979 if (lunchg2
->lunchg2_next
== NULL
)
5980 (void) cv_signal(&scsi_lunchg2_cv
);
5981 mutex_exit(&scsi_lunchg2_mutex
);
5987 scsi_lunchg2_daemon(void *arg
)
5989 callb_cpr_t cprinfo
;
5990 struct scsi_lunchg2
*lunchg2
;
5994 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg2_mutex
,
5995 callb_generic_cpr
, "scsi_lunchg2_daemon");
5997 li
= ldi_ident_from_anon();
5998 mutex_enter(&scsi_lunchg2_mutex
);
6000 lunchg2
= scsi_lunchg2_list
;
6001 if (lunchg2
== NULL
) {
6002 /* All lunchg2 processing requests serviced, wait. */
6003 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
6004 (void) cv_wait(&scsi_lunchg2_cv
,
6005 &scsi_lunchg2_mutex
);
6006 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg2_mutex
);
6010 /* Unlink and perform lunchg2 processing on pkt. */
6011 scsi_lunchg2_list
= lunchg2
->lunchg2_next
;
6014 * Open and close the path to trigger lun enumeration. We
6015 * don't expect the open to succeed, but we do expect code in
6016 * scsi_hba_bus_configone() to trigger lun enumeration.
6018 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
6019 "lunchg stage2: open %s", lunchg2
->lunchg2_path
));
6020 if (ldi_open_by_name(lunchg2
->lunchg2_path
,
6021 FREAD
, kcred
, &lh
, li
) == 0)
6022 (void) ldi_close(lh
, FREAD
, kcred
);
6024 /* Free path and linked element. */
6025 strfree(lunchg2
->lunchg2_path
);
6026 kmem_free(lunchg2
, sizeof (*lunchg2
));
6031 * Enumerate a child at the specified @addr. If a device exists @addr then
6032 * ensure that we have the appropriately named devinfo node for it. Name is
6033 * NULL in the bus_config_all case. This routine has no knowledge of the
6034 * format of an @addr string or associated addressing properties.
6036 * The caller must guarantee that there is an open scsi_hba_devi_enter on the
6037 * parent. We return the scsi_device structure for the child device. This
6038 * scsi_device structure is valid until the caller scsi_hba_devi_exit the
6039 * parent. The caller can add do ndi_hold_devi of the child prior to the
6040 * scsi_hba_devi_exit to extend the validity of the child.
6042 * In some cases the returned scsi_device structure may be used to drive
6043 * additional SCMD_REPORT_LUNS operations by bus_config_all callers.
6045 * The first operation performed is to see if there is a dynamic SID nodes
6046 * already attached at the specified "name@addr". This is the fastpath
6047 * case for resolving a reference to a node that has already been created.
6048 * All other references are serialized for a given @addr prior to probing
6049 * to determine the type of device, if any, at the specified @addr.
6050 * If no device is present then NDI_FAILURE is returned. The fact that a
6051 * device does not exist may be determined via the barrier/probe cache,
6052 * minimizing the probes of non-existent devices.
6054 * When there is a device present the dynamic SID node is created based on
6055 * the device found. If a driver.conf node exists for the same @addr it
6056 * will either merge into the dynamic SID node (if the SID node bound to
6057 * that driver), or exist independently. To prevent the actions of one driver
6058 * causing side effects in another, code prevents multiple SID nodes from
6059 * binding to the same "@addr" at the same time. There is autodetach code
6060 * to allow one device to be replaced with another at the same @addr for
6061 * slot addressed SCSI bus implementations (SPI). For compatibility with
6062 * legacy driver.conf behavior, the code does not prevent multiple driver.conf
6063 * nodes from attaching to the same @addr at the same time.
6065 * This routine may have the side effect of creating nodes for devices other
6066 * than the one being sought. It is possible that there is a different type of
6067 * target device at that target/lun address than we were asking for. In that
6068 * It is the caller's responsibility to determine whether the device we found,
6069 * if any, at the specified address, is the one it really wanted.
6071 static struct scsi_device
*
6072 scsi_device_config(dev_info_t
*self
, char *name
, char *addr
, scsi_enum_t se
,
6073 int *circp
, int *ppi
)
6075 dev_info_t
*child
= NULL
;
6076 dev_info_t
*probe
= NULL
;
6077 struct scsi_device
*sdchild
;
6078 struct scsi_device
*sdprobe
;
6079 dev_info_t
*dsearch
;
6080 mdi_pathinfo_t
*psearch
;
6084 int wait_msg
= scsi_hba_wait_msg
;
6087 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6089 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s wanted",
6090 name
? name
: "", addr
));
6092 /* playing with "probe" node name is dangerous */
6093 if (name
&& (strcmp(name
, "probe") == 0))
6097 * NOTE: use 'goto done;' or 'goto fail;'. There should only be one
6098 * 'return' statement from here to the end of the function - the one
6099 * on the last line of the function.
6103 * Fastpath: search to see if we are requesting a named SID node that
6104 * already exists (we already created) - probe node does not count.
6105 * scsi_findchild() does not hold the returned devinfo node, but
6106 * this is OK since the caller has a scsi_hba_devi_enter on the
6107 * attached parent HBA (self). The caller is responsible for attaching
6108 * and placing a hold on the child (directly via ndi_hold_devi or
6109 * indirectly via ndi_busop_bus_config) before doing an
6110 * scsi_hba_devi_exit on the parent.
6112 * NOTE: This fastpath prevents detecting a driver binding change
6113 * (autodetach) if the same nodename is used for old and new binding.
6115 /* first call is with init set */
6116 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6117 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
) &&
6118 !scsi_hba_devi_is_barrier(dsearch
)) {
6119 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6120 "%s@%s devinfo fastpath", name
? name
: "", addr
));
6126 * Create a barrier devinfo node used to "probe" the device with. We
6127 * need to drive this node to DS_INITIALIZED so that the
6128 * DDI_CTLOPS_INITCHILD has occurred, bringing the SCSA transport to
6129 * a state useable state for issuing our "probe" commands. We establish
6130 * this barrier node with a node name of "probe" and compatible
6131 * property of "scsiprobe". The compatible property must be associated
6132 * in /etc/driver_aliases with a scsi target driver available in the
6133 * root file system (sd).
6135 * The "probe" that we perform on the barrier node, after it is
6136 * DS_INITIALIZED, is used to find the information needed to create a
6137 * dynamic devinfo (SID) node. This "probe" is separate from the
6138 * probe(9E) call associated with the transition of a node from
6139 * DS_INITIALIZED to DS_PROBED. The probe(9E) call that eventually
6140 * occurs against the created SID node should find ddi_dev_is_sid and
6141 * just return DDI_PROBE_DONTCARE.
6143 * Trying to avoid the use of a barrier node is not a good idea
6144 * because we may have an HBA driver that uses generic bus_config
6145 * (this code) but implements its own DDI_CTLOPS_INITCHILD with side
6146 * effects that we can't duplicate (such as the ATA nexus driver).
6148 * The probe/barrier node plays an integral part of the locking scheme.
6149 * The objective is to single thread probes of the same device (same
6150 * @addr) while allowing parallelism for probes of different devices
6151 * with the same parent. At this point we are serialized on our self.
6152 * For parallelism we will need to release our self. Prior to release
6153 * we construct a barrier for probes of the same device to serialize
6154 * against. The "probe@addr" node acts as this barrier. An entering
6155 * thread must wait until the probe node does not exist - it can then
6156 * create and link the probe node - dropping the HBA (self) lock after
6157 * the node is linked and visible (after ddi_initchild). A side effect
6158 * of this is that transports should not "go over the wire" (i.e. do
6159 * things that incur significant delays) until after tran_target_init.
6160 * This means that the first "over the wire" operation should occur
6161 * at tran_target_probe time - when things are running in parallel
6164 * If the probe node exists then another probe with the same @addr is
6165 * in progress, we must wait until there is no probe in progress
6166 * before proceeding, and when we proceed we must continue to hold the
6167 * HBA (self) until we have linked a new probe node as a barrier.
6169 * When a device is found to *not* exist, its probe/barrier node may be
6170 * marked with DEVICE_REMOVED with node deletion scheduled for some
6171 * future time (seconds). This asynchronous deletion allows the
6172 * framework to detect repeated requests to the same non-existent
6173 * device and avoid overhead associated with contacting a non-existent
6174 * device again and again.
6178 * Search for probe node - they should only exist as devinfo
6181 (void) scsi_findchild(self
, "probe", addr
,
6182 0, &probe
, &psearch
, NULL
);
6183 if (probe
== NULL
) {
6185 SCSI_HBA_LOG((_LOG(2), self
,
6186 mdi_pi_get_client(psearch
),
6187 "???? @%s 'probe' search found "
6188 "pathinfo: %p", addr
, (void *)psearch
));
6193 * The barrier node may cache the non-existence of a device
6194 * by leaving the barrier node in place (with
6195 * DEVI_DEVICE_REMOVED flag set ) for some amount of time after
6196 * the failure of a probe. This flag is used to fail
6197 * additional probes until the barrier probe node is deleted,
6198 * which will occur from a timeout some time after a failed
6199 * probe. The failed probe will use DEVI_SET_DEVICE_REMOVED
6200 * and schedule probe node deletion from a timeout. The callers
6201 * scsi_hba_devi_exit on the way out of the first failure will
6202 * do the cv_broadcast associated with the cv_wait below - this
6203 * handles threads that wait prior to DEVI_DEVICE_REMOVED being
6206 if (DEVI_IS_DEVICE_REMOVED(probe
)) {
6207 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6208 "detected probe DEVICE_REMOVED"));
6209 probe
= NULL
; /* deletion already scheduled */
6214 * Drop the lock on the HBA (self) and wait until the probe in
6215 * progress has completed. A changes in the sibling list from
6216 * removing the probe node will cause cv_wait to return
6217 * (scsi_hba_devi_exit does the cv_broadcast).
6221 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6222 "exists, probe already in progress: %s", wait_msg
?
6223 "waiting..." : "last msg, but still waiting..."));
6227 * NOTE: we could avoid rare case of one second delay by
6228 * implementing scsi_hba_devi_exit_and_wait based on
6229 * ndi/mdi_devi_exit_and_wait (and consider switching devcfg.c
6230 * code to use these ndi/mdi interfaces too).
6232 scsi_hba_devi_exit(self
, *circp
);
6233 mutex_enter(&DEVI(self
)->devi_lock
);
6234 (void) cv_timedwait(&DEVI(self
)->devi_cv
,
6235 &DEVI(self
)->devi_lock
,
6236 ddi_get_lbolt() + drv_usectohz(MICROSEC
));
6237 mutex_exit(&DEVI(self
)->devi_lock
);
6238 scsi_hba_devi_enter(self
, circp
);
6240 ASSERT(probe
== NULL
);
6243 * Search to see if we are requesting a SID node that already exists.
6244 * We hold the HBA (self) and there is not another probe in progress at
6245 * the same @addr. scsi_findchild() does not hold the returned
6246 * devinfo node but this is OK since we hold the HBA (self).
6249 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6250 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
)) {
6251 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6252 "%s@%s probe devinfo fastpath",
6253 name
? name
: "", addr
));
6260 * We are looking for a SID node that does not exist or a driver.conf
6263 * To avoid probe side effects, before we probe the device at the
6264 * specified address we need to check to see if there is already an
6265 * initialized child "@addr".
6267 * o If we find an initialized SID child and name is NULL or matches
6268 * the name or the name of the attached driver then we return the
6271 * o If we find a non-matching SID node, we will attempt to autodetach
6272 * and remove the node in preference to our new node.
6274 * o If SID node found does not match and can't be autodetached, we
6275 * fail: we only allow one SID node at an address.
6277 * NOTE: This code depends on SID nodes showing up prior to
6278 * driver.conf nodes in the sibling list.
6281 /* first NULL name call is with init set */
6282 (void) scsi_findchild(self
, NULL
, addr
, 1, &dsearch
, NULL
, &pi
);
6283 if (dsearch
== NULL
)
6285 ASSERT(!scsi_hba_devi_is_barrier(dsearch
));
6288 * To detect changes in driver binding that should attempt
6289 * autodetach we determine the major number of the driver
6290 * that should currently be associated with the device based
6291 * on the compatible property.
6293 major
= DDI_MAJOR_T_NONE
;
6294 if (scsi_hba_dev_is_sid(dsearch
))
6295 major
= ddi_compatible_driver_major(dsearch
, NULL
);
6296 if ((major
== DDI_MAJOR_T_NONE
) && (name
== NULL
))
6297 major
= ddi_driver_major(dsearch
);
6299 if ((scsi_hba_dev_is_sid(dsearch
) ||
6300 (i_ddi_node_state(dsearch
) >= DS_INITIALIZED
)) &&
6302 (strcmp(ddi_node_name(dsearch
), name
) == 0) ||
6303 (strcmp(ddi_driver_name(dsearch
), name
) == 0)) &&
6304 (major
== ddi_driver_major(dsearch
))) {
6305 SCSI_HBA_LOG((_LOG(3), NULL
, dsearch
,
6306 "already attached @addr"));
6311 if (!scsi_hba_dev_is_sid(dsearch
))
6312 break; /* driver.conf node */
6315 * Implement autodetach of SID node for situations like a
6316 * previously "scsinodev" LUN0 coming into existence (or a
6317 * disk/tape on an SPI transport at same addr but never both
6318 * powered on at the same time). Try to autodetach the existing
6319 * SID node @addr. If that works, search again - otherwise fail.
6321 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6322 "looking for %s@%s: SID @addr exists, autodetach",
6323 name
? name
: "", addr
));
6324 if (!scsi_hba_remove_node(dsearch
)) {
6325 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6326 "autodetach @%s failed: fail %s@%s",
6327 addr
, name
? name
: "", addr
));
6330 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "autodetach @%s OK", addr
));
6334 * We will be creating a new SID node, allocate probe node
6335 * used to find out information about the device located @addr.
6336 * The probe node also acts as a barrier against additional
6337 * configuration at the same address, and in the case of non-existent
6338 * devices it will (for some amount of time) avoid re-learning that
6339 * the device does not exist on every reference. Once the probe
6340 * node is DS_LINKED we can drop the HBA (self).
6342 * The probe node is allocated as a hidden node so that it does not
6343 * show up in devinfo snapshots.
6345 ndi_devi_alloc_sleep(self
, "probe",
6346 (se
== SE_HP
) ? DEVI_SID_HP_HIDDEN_NODEID
: DEVI_SID_HIDDEN_NODEID
,
6349 ndi_flavor_set(probe
, SCSA_FLAVOR_SCSI_DEVICE
);
6352 * Decorate the probe node with the property representation of @addr
6353 * unit-address string prior to initchild so that initchild can
6354 * construct the name of the node from properties and tran_tgt_init
6355 * implementation can determine what LUN is being referenced.
6357 * If the addr specified has incorrect syntax (busconfig one of bogus
6358 * /devices path) then scsi_hba_ua_set can fail. If the address
6359 * is not understood by the SCSA HBA driver then this operation will
6360 * work, but tran_tgt_init may still fail (for example the HBA
6361 * driver may not support secondary functions).
6363 if (scsi_hba_ua_set(addr
, probe
, NULL
) == 0) {
6364 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6365 "@%s failed scsi_hba_ua_set", addr
));
6370 * Set the class property to "scsi". This is sufficient to distinguish
6371 * the node for HBAs that have multiple classes of children (like uata
6372 * - which has "dada" class for ATA children and "scsi" class for
6373 * ATAPI children) and may not use our scsi_busctl_initchild()
6374 * implementation. We also add a "compatible" property of "scsiprobe"
6375 * to select the probe driver.
6377 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, probe
,
6378 "class", "scsi") != DDI_PROP_SUCCESS
) ||
6379 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, probe
,
6380 "compatible", &compatible_probe
, 1) != DDI_PROP_SUCCESS
)) {
6381 SCSI_HBA_LOG((_LOG(1), NULL
, probe
,
6382 "@%s failed node decoration", addr
));
6387 * Promote probe node to DS_INITIALIZED so that transport can be used
6388 * for scsi_probe. After this the node is linked and visible as a
6389 * barrier for serialization of other @addr operations.
6391 * NOTE: If we attached the probe node, we could get rid of
6394 if (ddi_initchild(self
, probe
) != DDI_SUCCESS
) {
6395 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6396 "@%s failed initchild", addr
));
6398 /* probe node will be removed in fail exit path */
6402 /* get the scsi_device structure of the probe node */
6403 sdprobe
= ddi_get_driver_private(probe
);
6407 * Do scsi_probe. The probe node is linked and visible as a barrier.
6408 * We prevent uninitialization of the probe node and drop our HBA (self)
6409 * while we run scsi_probe() of this "@addr". This allows the framework
6410 * to support multiple scsi_probes for different devices attached to
6411 * the same HBA (self) in parallel. We prevent node demotion of the
6412 * probe node from DS_INITIALIZED by setting sd_uninit_prevent. The
6413 * probe node can not be successfully demoted below DS_INITIALIZED
6414 * (scsi_busctl_uninitchild will fail) until we zero sd_uninit_prevent
6415 * as we are freeing the node via scsi_hba_remove_node(probe).
6417 sdprobe
->sd_uninit_prevent
++;
6418 scsi_hba_devi_exit(self
, *circp
);
6419 sp
= scsi_probe(sdprobe
, SLEEP_FUNC
);
6421 /* Introduce a small delay here to increase parallelism. */
6424 if (sp
== SCSIPROBE_EXISTS
) {
6426 * For a device that exists, while still running in parallel,
6427 * also get identity information from device. This is done
6428 * separate from scsi_probe/tran_tgt_probe/scsi_hba_probe
6429 * since the probe code path may still be used for HBAs
6430 * that don't use common bus_config services (we don't want
6431 * to expose that code path to a behavior change). This
6432 * operation is called 'identity' to avoid confusion with
6433 * deprecated identify(9E).
6435 * Future: We may eventually want to allow HBA customization via
6436 * scsi_identity/tran_tgt_identity/scsi_device_identity, but for
6437 * now we just scsi_device_identity.
6439 * The identity operation will establish additional properties
6440 * on the probe node related to device identity:
6442 * "inquiry-page-80" byte array of SCSI page 80
6443 * "inquiry-page-83" byte array of SCSI page 83
6445 * These properties will be used to generate a devid
6446 * (ddi_devid_scsi_encode) and guid - and to register
6447 * (ddi_devid_register) a devid for the device.
6449 * If identify fails (non-zero return), the we had allocation
6450 * problems or the device returned inconsistent results then
6451 * we pretend that device does not exist.
6453 if (scsi_device_identity(sdprobe
, SLEEP_FUNC
)) {
6454 scsi_enumeration_failed(probe
, -1, NULL
, "identify");
6455 sp
= SCSIPROBE_FAILURE
;
6459 * Future: Is there anything more we can do here to help avoid
6460 * serialization on iport parent during scsi_device attach(9E)?
6463 scsi_hba_devi_enter(self
, circp
);
6464 sdprobe
->sd_uninit_prevent
--;
6466 if (sp
!= SCSIPROBE_EXISTS
) {
6467 scsi_enumeration_failed(probe
, -1, NULL
, "probe");
6469 if ((se
!= SE_HP
) && scsi_hba_barrier_timeout
) {
6471 * Target does not exist. Mark the barrier probe node
6472 * as DEVICE_REMOVED and schedule an asynchronous
6473 * deletion of the node in scsi_hba_barrier_timeout
6474 * seconds. We keep our hold on the probe node
6475 * until we are ready perform the asynchronous node
6478 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6479 "set probe DEVICE_REMOVED"));
6480 mutex_enter(&DEVI(probe
)->devi_lock
);
6481 DEVI_SET_DEVICE_REMOVED(probe
);
6482 mutex_exit(&DEVI(probe
)->devi_lock
);
6484 scsi_hba_barrier_add(probe
, scsi_hba_barrier_timeout
);
6490 /* Create the child node from the inquiry data in the probe node. */
6491 if ((child
= scsi_device_configchild(self
, addr
, se
, sdprobe
,
6492 circp
, &pi
)) == NULL
) {
6494 * This may fail because there was no driver binding identified
6495 * via driver_alias. We may still have a conf node.
6498 (void) scsi_findchild(self
, name
, addr
,
6499 0, &child
, NULL
, &pi
);
6501 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6502 "using driver.conf driver binding"));
6504 if (child
== NULL
) {
6505 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6506 "device not configured"));
6512 * Transfer the inquiry data from the probe node to the child
6513 * SID node to avoid an extra scsi_probe. Callers depend on
6514 * established inquiry data for the returned scsi_device.
6516 sdchild
= ddi_get_driver_private(child
);
6517 if (sdchild
&& (sdchild
->sd_inq
== NULL
)) {
6518 sdchild
->sd_inq
= sdprobe
->sd_inq
;
6519 sdprobe
->sd_inq
= NULL
;
6523 * If we are doing a bus_configone and the node we created has the
6524 * wrong node and driver name then switch the return result to a
6525 * driver.conf node with the correct name - if such a node exists.
6527 if (name
&& (strcmp(ddi_node_name(child
), name
) != 0) &&
6528 (strcmp(ddi_driver_name(child
), name
) != 0)) {
6529 (void) scsi_findchild(self
, name
, addr
,
6530 0, &dsearch
, NULL
, &pi
);
6531 if (dsearch
== NULL
) {
6532 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6533 "wrong device configured %s@%s", name
, addr
));
6535 * We can't remove when modrootloaded == 0 in case
6536 * boot-device a uses generic name and
6537 * scsi_hba_nodename_compatible_get() returned a
6538 * legacy binding-set driver oriented name.
6540 if (modrootloaded
) {
6541 (void) scsi_hba_remove_node(child
);
6546 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6547 "device configured, but switching to driver.conf"));
6552 /* get the scsi_device structure from the node */
6553 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "device configured"));
6556 done
: ASSERT(child
);
6557 sdchild
= ddi_get_driver_private(child
);
6561 * We may have ended up here after promotion of a previously
6562 * demoted node, where demotion deleted sd_inq data in
6563 * scsi_busctl_uninitchild. We redo the scsi_probe() to
6564 * reestablish sd_inq. We also want to redo the scsi_probe
6565 * for devices are currently device_isremove in order to
6566 * detect new device_insert.
6568 if ((sdchild
->sd_inq
== NULL
) ||
6569 ((pi
== NULL
) && ndi_devi_device_isremoved(child
))) {
6571 /* hotplug_node can only be revived via hotplug. */
6572 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
6573 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6574 "scsi_probe() demoted devinfo"));
6576 sp
= scsi_probe(sdchild
, SLEEP_FUNC
);
6578 if (sp
== SCSIPROBE_EXISTS
) {
6579 ASSERT(sdchild
->sd_inq
);
6582 * Devinfo child exists and we are
6583 * talking to the device, report
6584 * reinsert and note if this was a
6587 chg
= ndi_devi_device_insert(child
);
6588 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6589 "devinfo %s@%s device_reinsert%s",
6590 name
? name
: "", addr
,
6591 chg
? "" : "ed already"));
6593 scsi_enumeration_failed(child
, se
,
6596 chg
= ndi_devi_device_remove(child
);
6597 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6598 "%s device_remove%s",
6599 (sp
> (sizeof (scsi_probe_ascii
) /
6600 sizeof (scsi_probe_ascii
[0]))) ?
6601 "UNKNOWN" : scsi_probe_ascii
[sp
],
6602 chg
? "" : "ed already"));
6608 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6616 fail
: ASSERT(child
== NULL
);
6621 * Clean up probe node, destroying node if uninit_prevent
6622 * it is going to zero. Destroying the probe node (deleting
6623 * from the sibling list) will wake up any people waiting on
6624 * the probe node barrier.
6626 SCSI_HBA_LOG((_LOG(4), NULL
, probe
, "remove probe"));
6627 if (!scsi_hba_remove_node(probe
)) {
6629 * Probe node removal should not fail, but if it
6630 * does we hand that responsibility over to the
6631 * async barrier deletion thread - other references
6632 * to the same unit-address can hang until the
6633 * probe node delete completes.
6635 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
6636 "remove probe failed, go async"));
6637 scsi_hba_barrier_add(probe
, 1);
6643 * If we successfully resolved via a pathinfo node, we need to find
6644 * the pathinfo node and ensure that it is online (if possible). This
6645 * is done for the case where the device was open when
6646 * scsi_device_unconfig occurred, so mdi_pi_free did not occur. If the
6647 * device has now been reinserted, we want the path back online.
6648 * NOTE: This needs to occur after destruction of the probe node to
6649 * avoid ASSERT related to two nodes at the same unit-address.
6651 if (sdchild
&& pi
&& (probe
== NULL
)) {
6652 ASSERT(MDI_PHCI(self
));
6654 (void) scsi_findchild(self
, NULL
, addr
,
6655 0, &dsearch
, &psearch
, NULL
);
6656 ASSERT((psearch
== NULL
) ||
6657 (mdi_pi_get_client(psearch
) == child
));
6659 if (psearch
&& mdi_pi_device_isremoved(psearch
)) {
6661 * Verify that we can talk to the device, and if
6662 * so note if this is a new device_insert.
6664 * NOTE: We depend on mdi_path_select(), when given
6665 * a specific path_instance, to select that path
6666 * even if the path is offline.
6668 * NOTE: A Client node is not ndi_dev_is_hotplug_node().
6671 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6672 "%s scsi_probe() demoted pathinfo",
6673 mdi_pi_spathname(psearch
)));
6675 sp
= scsi_hba_probe_pi(sdchild
, SLEEP_FUNC
, pi
);
6677 if (sp
== SCSIPROBE_EXISTS
) {
6679 * Pathinfo child exists and we are
6680 * talking to the device, report
6681 * reinsert and note if this
6682 * was a new reinsert.
6684 chg
= mdi_pi_device_insert(psearch
);
6685 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
6686 "pathinfo %s device_reinsert%s",
6687 mdi_pi_spathname(psearch
),
6688 chg
? "" : "ed already"));
6691 (void) mdi_pi_online(psearch
,
6695 * Report client reinsert and note if
6696 * this was a new reinsert.
6698 chg
= ndi_devi_device_insert(child
);
6699 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6700 "client devinfo %s@%s "
6701 "device_reinsert%s",
6702 name
? name
: "", addr
,
6703 chg
? "" : "ed already"));
6705 scsi_enumeration_failed(child
, se
,
6706 mdi_pi_spathname(psearch
),
6713 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6715 mdi_pi_spathname(psearch
)));
6723 /* If asked for path_instance, return it. */
6731 scsi_device_unconfig(dev_info_t
*self
, char *name
, char *addr
, int *circp
)
6733 dev_info_t
*child
= NULL
;
6734 mdi_pathinfo_t
*path
= NULL
;
6738 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6741 * We have a catch-22. We may have a demoted node that we need to find
6742 * and offline/remove. To find the node if it isn't demoted, we
6743 * use scsi_findchild. If it's demoted, we then use
6744 * ndi_devi_findchild_by_callback.
6746 (void) scsi_findchild(self
, name
, addr
, 0, &child
, &path
, NULL
);
6748 if ((child
== NULL
) && (path
== NULL
)) {
6749 child
= ndi_devi_findchild_by_callback(self
, name
, addr
,
6752 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6753 "devinfo %s@%s found by callback",
6754 name
? name
: "", addr
));
6755 ASSERT(ndi_flavor_get(child
) ==
6756 SCSA_FLAVOR_SCSI_DEVICE
);
6757 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
) {
6758 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6759 "devinfo %s@%s not SCSI_DEVICE flavored",
6760 name
? name
: "", addr
));
6767 ASSERT(child
&& (path
== NULL
));
6769 /* Don't unconfig probe nodes. */
6770 if (scsi_hba_devi_is_barrier(child
)) {
6771 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6772 "devinfo %s@%s is_barrier, skip",
6773 name
? name
: "", addr
));
6777 /* Attempt to offline/remove the devinfo node */
6778 if (ndi_devi_offline(child
,
6779 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
6780 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6781 "devinfo %s@%s offlined and removed",
6782 name
? name
: "", addr
));
6783 } else if (ndi_devi_device_remove(child
)) {
6784 /* Offline/remove failed, note new device_remove */
6785 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6786 "devinfo %s@%s offline failed, device_remove",
6787 name
? name
: "", addr
));
6790 ASSERT(path
&& (child
== NULL
));
6793 * Attempt to offline/remove the pathinfo node.
6795 * NOTE: mdi_pi_offline of last path will fail if the
6796 * device is open (i.e. the client can't be offlined).
6798 * NOTE: For mdi there is no REMOVE flag for mdi_pi_offline().
6799 * When mdi_pi_offline returns MDI_SUCCESS, we are responsible
6800 * for remove via mdi_pi_free().
6802 mdi_hold_path(path
);
6803 spathname
= mdi_pi_spathname(path
); /* valid after free */
6804 scsi_hba_devi_exit_phci(self
, *circp
);
6805 rval
= mdi_pi_offline(path
, 0);
6806 scsi_hba_devi_enter_phci(self
, circp
);
6808 /* Note new device_remove */
6809 if (mdi_pi_device_remove(path
))
6810 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6811 "pathinfo %s note device_remove", spathname
));
6813 mdi_rele_path(path
);
6814 if (rval
== MDI_SUCCESS
) {
6815 (void) mdi_pi_free(path
, 0);
6816 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6817 "pathinfo %s offlined, then freed", spathname
));
6820 ASSERT((path
== NULL
) && (child
== NULL
));
6822 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6823 "%s@%s not found", name
? name
: "", addr
));
6828 * configure the device at the specified "@addr" address.
6830 static struct scsi_device
*
6831 scsi_hba_bus_configone_addr(dev_info_t
*self
, char *addr
, scsi_enum_t se
)
6834 struct scsi_device
*sd
;
6836 scsi_hba_devi_enter(self
, &circ
);
6837 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, NULL
);
6838 scsi_hba_devi_exit(self
, circ
);
6843 * unconfigure the device at the specified "@addr" address.
6846 scsi_hba_bus_unconfigone_addr(dev_info_t
*self
, char *addr
)
6850 scsi_hba_devi_enter(self
, &circ
);
6851 (void) scsi_device_unconfig(self
, NULL
, addr
, &circ
);
6852 scsi_hba_devi_exit(self
, circ
);
6856 * The bus_config_all operations are multi-threaded for performance. A
6857 * separate thread per target and per LUN is used. The config handle is used
6858 * to coordinate all the threads at a given level and the config thread data
6859 * contains the required information for a specific thread to identify what it
6860 * is processing and the handle under which this is being processed.
6863 /* multi-threaded config handle */
6864 struct scsi_hba_mte_h
{
6865 dev_info_t
*h_self
; /* initiator port */
6871 /* target of 'self' config thread data */
6872 struct scsi_hba_mte_td
{
6873 struct scsi_hba_mte_h
*td_h
;
6874 char *td_taddr
; /* target port */
6879 /* Invoke callback on a vector of taddrs from multiple threads */
6881 scsi_hba_thread_taddrs(dev_info_t
*self
, char **taddrs
, int mt
,
6882 scsi_enum_t se
, void (*callback
)(void *arg
))
6884 struct scsi_hba_mte_h
*h
; /* HBA header */
6885 struct scsi_hba_mte_td
*td
; /* target data */
6888 /* allocate and initialize the handle */
6889 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
6890 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
6891 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
6894 /* loop over all the targets */
6895 for (taddr
= taddrs
; *taddr
; taddr
++) {
6896 /* allocate a thread data structure for target */
6897 td
= kmem_alloc(sizeof (*td
), KM_SLEEP
);
6899 td
->td_taddr
= *taddr
;
6903 /* process the target */
6904 mutex_enter(&h
->h_lock
);
6906 mutex_exit(&h
->h_lock
);
6908 if (mt
& SCSI_ENUMERATION_MT_TARGET_DISABLE
)
6909 callback((void *)td
);
6911 (void) thread_create(NULL
, 0, callback
, (void *)td
,
6912 0, &p0
, TS_RUN
, minclsyspri
);
6915 /* wait for all the target threads to complete */
6916 mutex_enter(&h
->h_lock
);
6917 while (h
->h_thr_count
> 0)
6918 cv_wait(&h
->h_cv
, &h
->h_lock
);
6919 mutex_exit(&h
->h_lock
);
6921 /* free the handle */
6922 cv_destroy(&h
->h_cv
);
6923 mutex_destroy(&h
->h_lock
);
6924 kmem_free(h
, sizeof (*h
));
6928 /* lun/secondary function of lun0 config thread data */
6929 struct scsi_hba_mte_ld
{
6930 struct scsi_hba_mte_h
*ld_h
;
6931 char *ld_taddr
; /* target port */
6932 scsi_lun64_t ld_lun64
; /* lun */
6933 int ld_sfunc
; /* secondary function */
6938 * Enumerate the LUNs and secondary functions of the specified target. The
6939 * target portion of the "@addr" is already represented as a string in the
6940 * thread data, we add a ",lun" representation to this and perform a
6941 * bus_configone byte of enumeration on that "@addr".
6944 scsi_hba_enum_lsf_of_tgt_thr(void *arg
)
6946 struct scsi_hba_mte_ld
*ld
= (struct scsi_hba_mte_ld
*)arg
;
6947 struct scsi_hba_mte_h
*h
= ld
->ld_h
;
6948 dev_info_t
*self
= h
->h_self
;
6949 char addr
[SCSI_MAXNAMELEN
];
6951 /* make string form of "@taddr,lun[,sfunc]" and see if it exists */
6952 if (ld
->ld_sfunc
== -1)
6953 (void) snprintf(addr
, sizeof (addr
),
6954 "%s,%" PRIx64
, ld
->ld_taddr
, ld
->ld_lun64
);
6956 (void) snprintf(addr
, sizeof (addr
),
6957 "%s,%" PRIx64
",%x",
6958 ld
->ld_taddr
, ld
->ld_lun64
, ld
->ld_sfunc
);
6960 /* configure device at that unit-address address */
6961 (void) scsi_hba_bus_configone_addr(self
, addr
, ld
->ld_se
);
6963 /* signal completion of this LUN thread to the target */
6964 mutex_enter(&h
->h_lock
);
6965 if (--h
->h_thr_count
== 0)
6966 cv_broadcast(&h
->h_cv
);
6967 mutex_exit(&h
->h_lock
);
6969 /* free config thread data */
6970 kmem_free(ld
, sizeof (*ld
));
6973 /* Format of SCSI REPORT_LUNS report */
6974 typedef struct scsi_lunrpt
{
6975 uchar_t lunrpt_len_msb
; /* # LUNs being reported */
6976 uchar_t lunrpt_len_mmsb
;
6977 uchar_t lunrpt_len_mlsb
;
6978 uchar_t lunrpt_len_lsb
;
6979 uchar_t lunrpt_reserved
[4];
6980 scsi_lun_t lunrpt_luns
[1]; /* LUNs, variable size */
6984 * scsi_device_reportluns()
6986 * Callers of this routine should ensure that the 'sd0' scsi_device structure
6987 * and 'pi' path_instance specified are associated with a responding LUN0.
6988 * This should not be called for SCSI-1 devices.
6990 * To get a LUN report, we must allocate a buffer. To know how big to make the
6991 * buffer, we must know the number of LUNs. To know the number of LUNs, we must
6992 * get a LUN report. We first issue a SCMD_REPORT_LUNS command using a
6993 * reasonably sized buffer that's big enough to report all LUNs for most
6994 * typical devices. If it turns out that we needed a bigger buffer, we attempt
6995 * to allocate a buffer of sufficient size, and reissue the command. If the
6996 * first command succeeds, but the second fails, we return whatever we were
6997 * able to get the first time. We return enough information for the caller to
6998 * tell whether he got all the LUNs or only a subset.
7000 * If successful, we allocate an array of scsi_lun_t to hold the results. The
7001 * caller must kmem_free(*lunarrayp, *sizep) when finished with it. Upon
7002 * successful return return value is NDI_SUCCESS and:
7004 * *lunarrayp points to the allocated array,
7005 * *nlunsp is the number of valid LUN entries in the array,
7006 * *tlunsp is the total number of LUNs in the target,
7007 * *sizep is the size of the lunarrayp array, which must be freed.
7009 * If the *nlunsp is less than *tlunsp, then we were only able to retrieve a
7010 * subset of the total set of LUNs in the target.
7013 scsi_device_reportluns(struct scsi_device
*sd0
, char *taddr
, int pi
,
7014 scsi_lun_t
**lunarrayp
, uint32_t *nlunsp
, uint32_t *tlunsp
, size_t *sizep
)
7016 struct buf
*lunrpt_bp
;
7017 struct scsi_pkt
*lunrpt_pkt
;
7018 scsi_lunrpt_t
*lunrpt
;
7020 uint32_t tluns
, nluns
;
7021 int default_maxluns
= scsi_lunrpt_default_max
;
7024 ASSERT(sd0
&& lunarrayp
&& nlunsp
&& tlunsp
&& sizep
);
7027 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7028 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7029 * of a child of the 'self' pHCI we are enumerating.
7031 child
= sd0
->sd_dev
;
7033 /* first try, look for up to scsi_lunrpt_default_max LUNs */
7034 nluns
= default_maxluns
;
7036 again
: bsize
= sizeof (struct scsi_lunrpt
) +
7037 ((nluns
- 1) * sizeof (struct scsi_lun
));
7039 lunrpt_bp
= scsi_alloc_consistent_buf(&sd0
->sd_address
,
7040 (struct buf
*)NULL
, bsize
, B_READ
, SLEEP_FUNC
, NULL
);
7041 if (lunrpt_bp
== NULL
) {
7042 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed alloc"));
7046 lunrpt_pkt
= scsi_init_pkt(&sd0
->sd_address
,
7047 (struct scsi_pkt
*)NULL
, lunrpt_bp
, CDB_GROUP5
,
7048 sizeof (struct scsi_arq_status
), 0, PKT_CONSISTENT
,
7050 if (lunrpt_pkt
== NULL
) {
7051 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed init"));
7052 scsi_free_consistent_buf(lunrpt_bp
);
7056 (void) scsi_setup_cdb((union scsi_cdb
*)lunrpt_pkt
->pkt_cdbp
,
7057 SCMD_REPORT_LUNS
, 0, bsize
, 0);
7059 lunrpt_pkt
->pkt_time
= scsi_lunrpt_timeout
;
7062 * When sd0 is a vHCI scsi device, we need reportlun to be issued
7063 * against a specific LUN0 path_instance that we are enumerating.
7065 lunrpt_pkt
->pkt_path_instance
= pi
;
7066 lunrpt_pkt
->pkt_flags
|= FLAG_PKT_PATH_INSTANCE
;
7069 * NOTE: scsi_poll may not allow HBA specific recovery from TRAN_BUSY.
7071 if (scsi_poll(lunrpt_pkt
) < 0) {
7072 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "reportlun not supported"));
7073 scsi_destroy_pkt(lunrpt_pkt
);
7074 scsi_free_consistent_buf(lunrpt_bp
);
7075 return (NDI_FAILURE
);
7078 scsi_destroy_pkt(lunrpt_pkt
);
7080 lunrpt
= (scsi_lunrpt_t
*)lunrpt_bp
->b_un
.b_addr
;
7082 /* Compute the total number of LUNs in the target */
7083 tluns
= (((uint_t
)lunrpt
->lunrpt_len_msb
<< 24) |
7084 ((uint_t
)lunrpt
->lunrpt_len_mmsb
<< 16) |
7085 ((uint_t
)lunrpt
->lunrpt_len_mlsb
<< 8) |
7086 ((uint_t
)lunrpt
->lunrpt_len_lsb
)) >> 3;
7089 /* Illegal response -- this target is broken */
7090 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "illegal tluns of zero"));
7091 scsi_free_consistent_buf(lunrpt_bp
);
7092 return (DDI_NOT_WELL_FORMED
);
7095 if (tluns
> nluns
) {
7096 /* have more than we allocated space for */
7097 if (nluns
== default_maxluns
) {
7098 /* first time around, reallocate larger */
7099 scsi_free_consistent_buf(lunrpt_bp
);
7104 /* uh oh, we got a different tluns the second time! */
7105 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
7106 "tluns changed from %d to %d", nluns
, tluns
));
7112 * lunrpt_bp is the buffer we're using;
7113 * tluns is the total number of LUNs the target says it has;
7114 * nluns is the number of LUNs we were able to get into the buffer.
7116 * Copy the data out of scarce iopb memory into regular kmem.
7117 * The caller must kmem_free(*lunarrayp, *sizep) when finished with it.
7119 *lunarrayp
= (scsi_lun_t
*)kmem_alloc(
7120 nluns
* sizeof (scsi_lun_t
), KM_SLEEP
);
7121 if (*lunarrayp
== NULL
) {
7122 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "NULL lunarray"));
7123 scsi_free_consistent_buf(lunrpt_bp
);
7127 *sizep
= nluns
* sizeof (scsi_lun_t
);
7130 bcopy((void *)&lunrpt
->lunrpt_luns
, (void *)*lunarrayp
, *sizep
);
7131 scsi_free_consistent_buf(lunrpt_bp
);
7132 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
7133 "@%s,0 path %d: %d/%d luns", taddr
, pi
, nluns
, tluns
));
7134 return (NDI_SUCCESS
);
7138 * Enumerate all the LUNs and secondary functions of the specified 'taddr'
7139 * target port as accessed via 'self' pHCI. Note that sd0 may be associated
7140 * with a child of the vHCI instead of 'self' - in this case the 'pi'
7141 * path_instance is used to ensure that the SCMD_REPORT_LUNS command is issued
7142 * through the 'self' pHCI path.
7144 * We multi-thread across all the LUNs and secondary functions and enumerate
7145 * them. Which LUNs exist is based on SCMD_REPORT_LUNS data.
7147 * The scsi_device we are called with should be for LUN0 and has been probed.
7149 * This function is structured so that an HBA that has a different target
7150 * addressing structure can still use this function to enumerate the its
7151 * LUNs if it uses "taddr,lun" for its LUN space.
7153 * We make assumptions about other LUNs associated with the target:
7155 * For SCSI-2 and SCSI-3 target we will issue the SCSI report_luns
7156 * command. If this fails or we have a SCSI-1 then the number of
7157 * LUNs is determined based on SCSI_OPTIONS_NLUNS. For a SCSI-1
7158 * target we never probe above LUN 8, even if SCSI_OPTIONS_NLUNS
7159 * indicates we should.
7161 * HBA drivers wanting a different set of assumptions should implement their
7162 * own LUN enumeration code.
7165 scsi_hba_enum_lsf_of_t(struct scsi_device
*sd0
,
7166 dev_info_t
*self
, char *taddr
, int pi
, int mt
, scsi_enum_t se
)
7169 scsi_hba_tran_t
*tran
;
7170 impl_scsi_tgtmap_t
*tgtmap
;
7173 damap_t
*lundam
= NULL
;
7174 struct scsi_hba_mte_h
*h
;
7175 struct scsi_hba_mte_ld
*ld
;
7177 scsi_lun_t
*lunp
= NULL
;
7186 * If LUN0 failed then we have no other LUNs.
7188 * NOTE: We need sd_inq to be valid to check ansi version. Since
7189 * scsi_unprobe is now a noop (sd_inq freeded in
7190 * scsi_busctl_uninitchild) sd_inq remains valid even if a target
7191 * driver detach(9E) occurs, resulting in a scsi_unprobe call
7192 * (sd_uninit_prevent keeps sd_inq valid by failing any
7193 * device_uninitchild attempts).
7195 ASSERT(sd0
&& sd0
->sd_uninit_prevent
&& sd0
->sd_dev
&& sd0
->sd_inq
);
7196 if ((sd0
== NULL
) || (sd0
->sd_dev
== NULL
) || (sd0
->sd_inq
== NULL
)) {
7197 SCSI_HBA_LOG((_LOG(1), NULL
, sd0
? sd0
->sd_dev
: NULL
,
7198 "not setup correctly:%s%s%s",
7199 (sd0
== NULL
) ? " device" : "",
7200 (sd0
&& (sd0
->sd_dev
== NULL
)) ? " dip" : "",
7201 (sd0
&& (sd0
->sd_inq
== NULL
)) ? " inq" : ""));
7202 return (DDI_FAILURE
);
7206 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7207 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7208 * of a child of the 'self' pHCI we are enumerating.
7210 child
= sd0
->sd_dev
;
7212 /* Determine if we are reporting lun observations into lunmap. */
7213 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7214 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7216 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
7217 tgtid
= damap_lookup(tgtdam
, taddr
);
7218 if (tgtid
!= NODAM
) {
7219 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
7220 damap_id_rele(tgtdam
, tgtid
);
7226 /* If using lunmap, start the observation */
7227 scsi_lunmap_set_begin(self
, lundam
);
7229 /* allocate and initialize the LUN handle */
7230 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
7231 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
7232 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
7236 /* See if SCMD_REPORT_LUNS works for SCSI-2 and beyond */
7237 aver
= sd0
->sd_inq
->inq_ansi
;
7238 if ((aver
>= SCSI_VERSION_2
) && (scsi_device_reportluns(sd0
,
7239 taddr
, pi
, &lunp
, &nluns
, &tluns
, &size
) == NDI_SUCCESS
)) {
7241 ASSERT(lunp
&& (size
> 0) && (nluns
> 0) && (tluns
> 0));
7243 /* loop over the reported LUNs */
7244 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7245 "@%s,0 path %d: enumerating %d reported lun%s", taddr
, pi
,
7246 nluns
, nluns
> 1 ? "s" : ""));
7248 for (lun
= 0; lun
< nluns
; lun
++) {
7249 lun64
= scsi_lun_to_lun64(lunp
[lun
]);
7252 if (scsi_lunmap_set_add(self
, lundam
,
7253 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7254 SCSI_HBA_LOG((_LOG_NF(WARN
),
7255 "@%s,%" PRIx64
" failed to create",
7262 /* allocate a thread data structure for LUN */
7263 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7265 ld
->ld_taddr
= taddr
;
7266 ld
->ld_lun64
= lun64
;
7270 /* process the LUN */
7271 mutex_enter(&h
->h_lock
);
7273 mutex_exit(&h
->h_lock
);
7275 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7276 scsi_hba_enum_lsf_of_tgt_thr(
7279 (void) thread_create(NULL
, 0,
7280 scsi_hba_enum_lsf_of_tgt_thr
,
7281 (void *)ld
, 0, &p0
, TS_RUN
,
7286 /* free the LUN array allocated by scsi_device_reportluns */
7287 kmem_free(lunp
, size
);
7289 /* Determine the number of LUNs to enumerate. */
7290 maxluns
= scsi_get_scsi_maxluns(sd0
);
7292 /* Couldn't get SCMD_REPORT_LUNS data */
7293 if (aver
>= SCSI_VERSION_3
) {
7294 scsi_enumeration_failed(child
, se
, taddr
, "report_lun");
7297 * Based on calling context tunable, only enumerate one
7298 * lun (lun0) if scsi_device_reportluns() fails on a
7299 * SCSI_VERSION_3 or greater device.
7301 if (scsi_lunrpt_failed_do1lun
& (1 << se
))
7305 /* loop over possible LUNs, skipping LUN0 */
7307 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7308 "@%s,0 path %d: enumerating luns 1-%d", taddr
, pi
,
7311 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7312 "@%s,0 path %d: enumerating just lun0", taddr
, pi
));
7314 for (lun64
= 0; lun64
< maxluns
; lun64
++) {
7316 if (scsi_lunmap_set_add(self
, lundam
,
7317 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7318 SCSI_HBA_LOG((_LOG_NF(WARN
),
7319 "@%s,%" PRIx64
" failed to create",
7326 /* allocate a thread data structure for LUN */
7327 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7329 ld
->ld_taddr
= taddr
;
7330 ld
->ld_lun64
= lun64
;
7334 /* process the LUN */
7335 mutex_enter(&h
->h_lock
);
7337 mutex_exit(&h
->h_lock
);
7338 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7339 scsi_hba_enum_lsf_of_tgt_thr(
7342 (void) thread_create(NULL
, 0,
7343 scsi_hba_enum_lsf_of_tgt_thr
,
7344 (void *)ld
, 0, &p0
, TS_RUN
,
7351 * If we have an embedded service as a secondary function on LUN0 and
7352 * the primary LUN0 function is different than the secondary function
7353 * then enumerate the secondary function. The sfunc value is the dtype
7354 * associated with the embedded service.
7356 * inq_encserv: enclosure service and our dtype is not DTYPE_ESI
7357 * or DTYPE_UNKNOWN then create a separate DTYPE_ESI node for
7358 * enclosure service access.
7360 ASSERT(sd0
->sd_inq
);
7361 if (sd0
->sd_inq
->inq_encserv
&&
7362 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_UNKNOWN
) &&
7363 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_ESI
) &&
7364 ((sd0
->sd_inq
->inq_ansi
>= SCSI_VERSION_3
))) {
7366 if (scsi_lunmap_set_add(self
, lundam
,
7367 taddr
, 0, DTYPE_ESI
) != DDI_SUCCESS
) {
7368 SCSI_HBA_LOG((_LOG_NF(WARN
),
7369 "@%s,0,%x failed to create",
7373 /* allocate a thread data structure for sfunc */
7374 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7376 ld
->ld_taddr
= taddr
;
7378 ld
->ld_sfunc
= DTYPE_ESI
;
7381 /* process the LUN */
7382 mutex_enter(&h
->h_lock
);
7384 mutex_exit(&h
->h_lock
);
7385 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7386 scsi_hba_enum_lsf_of_tgt_thr((void *)ld
);
7388 (void) thread_create(NULL
, 0,
7389 scsi_hba_enum_lsf_of_tgt_thr
, (void *)ld
,
7390 0, &p0
, TS_RUN
, minclsyspri
);
7395 * Future: Add secondary function support for:
7396 * inq_mchngr (DTYPE_CHANGER)
7397 * inq_sccs (DTYPE_ARRAY_CTRL)
7401 /* If using lunmap, end the observation */
7402 scsi_lunmap_set_end(self
, lundam
);
7404 /* wait for all the LUN threads of this target to complete */
7405 mutex_enter(&h
->h_lock
);
7406 while (h
->h_thr_count
> 0)
7407 cv_wait(&h
->h_cv
, &h
->h_lock
);
7408 mutex_exit(&h
->h_lock
);
7410 /* free the target handle */
7411 cv_destroy(&h
->h_cv
);
7412 mutex_destroy(&h
->h_lock
);
7413 kmem_free(h
, sizeof (*h
));
7416 return (DDI_SUCCESS
);
7420 * Enumerate LUN0 and all other LUNs and secondary functions associated with
7421 * the specified target address.
7423 * Return NDI_SUCCESS if we might have created a new node.
7424 * Return NDI_FAILURE if we definitely did not create a new node.
7427 scsi_hba_bus_config_taddr(dev_info_t
*self
, char *taddr
, int mt
, scsi_enum_t se
)
7429 char addr
[SCSI_MAXNAMELEN
];
7430 struct scsi_device
*sd
;
7435 /* See if LUN0 of the specified target exists. */
7436 (void) snprintf(addr
, sizeof (addr
), "%s,0", taddr
);
7438 scsi_hba_devi_enter(self
, &circ
);
7439 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, &pi
);
7443 * LUN0 exists, enumerate all the other LUNs.
7445 * With vHCI enumeration, when 'self' is a pHCI the sd
7446 * scsi_device may be associated with the vHCI 'client'.
7447 * In this case 'pi' is the path_instance needed to
7448 * continue enumeration communication LUN0 via 'self'
7449 * pHCI and specific 'taddr' target address.
7451 * We prevent the removal of LUN0 until we are done with
7452 * prevent/allow because we must exit the parent for
7453 * multi-threaded scsi_hba_enum_lsf_of_t().
7455 * NOTE: scsi_unprobe is a noop, sd->sd_inq is valid until
7456 * device_uninitchild - so sd_uninit_prevent keeps sd_inq valid
7457 * by failing any device_uninitchild attempts.
7460 sd
->sd_uninit_prevent
++;
7461 scsi_hba_devi_exit(self
, circ
);
7463 (void) scsi_hba_enum_lsf_of_t(sd
, self
, taddr
, pi
, mt
, se
);
7465 scsi_hba_devi_enter(self
, &circ
);
7466 sd
->sd_uninit_prevent
--;
7469 scsi_hba_devi_exit(self
, circ
);
7473 /* Config callout from scsi_hba_thread_taddrs */
7475 scsi_hba_taddr_config_thr(void *arg
)
7477 struct scsi_hba_mte_td
*td
= (struct scsi_hba_mte_td
*)arg
;
7478 struct scsi_hba_mte_h
*h
= td
->td_h
;
7480 (void) scsi_hba_bus_config_taddr(h
->h_self
, td
->td_taddr
,
7481 td
->td_mt
, td
->td_se
);
7483 /* signal completion of this target thread to the HBA */
7484 mutex_enter(&h
->h_lock
);
7485 if (--h
->h_thr_count
== 0)
7486 cv_broadcast(&h
->h_cv
);
7487 mutex_exit(&h
->h_lock
);
7489 /* free config thread data */
7490 kmem_free(td
, sizeof (*td
));
7494 * Enumerate all the children of the specified SCSI parallel interface (spi).
7495 * An HBA associated with a non-parallel scsi bus should be using another bus
7496 * level enumeration implementation (possibly their own) and calling
7497 * scsi_hba_bus_config_taddr to do enumeration of devices associated with a
7498 * particular target address.
7500 * On an spi bus the targets are sequentially enumerated based on the
7501 * width of the bus. We also take care to try to skip the HBAs own initiator
7502 * id. See scsi_hba_enum_lsf_of_t() for LUN and secondary function enumeration.
7504 * Return NDI_SUCCESS if we might have created a new node.
7505 * Return NDI_FAILURE if we definitely did not create a new node.
7507 * Note: At some point we may want to expose this interface in transport.h
7508 * if we find an hba that implements bus_config but still uses spi-like target
7512 scsi_hba_bus_configall_spi(dev_info_t
*self
, int mt
)
7523 * Find the number of targets supported on the bus. Look at the per
7524 * bus scsi-options property on the HBA node and check its
7525 * SCSI_OPTIONS_WIDE setting.
7527 options
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7528 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-options", -1);
7529 if ((options
!= -1) && ((options
& SCSI_OPTIONS_WIDE
) == 0))
7530 ntargets
= NTARGETS
; /* 8 */
7532 ntargets
= NTARGETS_WIDE
; /* 16 */
7535 * Find the initiator-id for the HBA so we can skip that. We get the
7536 * cached value on the HBA node, established in scsi_hba_attach_setup.
7537 * If we were unable to determine the id then we rely on the HBA to
7538 * fail gracefully when asked to enumerate itself.
7540 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7541 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-initiator-id", -1);
7542 if (id
> ntargets
) {
7543 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
7544 "'scsi-initiator-id' bogus for %d target bus: %d",
7548 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7549 "enumerating targets 0-%d skip %d", ntargets
, id
));
7551 /* form vector of target addresses */
7552 taddrs
= kmem_zalloc(sizeof (char *) * (ntargets
+ 1), KM_SLEEP
);
7553 for (tgt
= 0, taddr
= taddrs
; tgt
< ntargets
; tgt
++) {
7554 /* skip initiator */
7558 /* convert to string and enumerate the target address */
7559 tbuf
= kmem_alloc(((tgt
/16) + 1) + 1, KM_SLEEP
);
7560 (void) sprintf(tbuf
, "%x", tgt
);
7561 ASSERT(strlen(tbuf
) == ((tgt
/16) + 1));
7565 /* null terminate vector of target addresses */
7568 /* configure vector of target addresses */
7569 scsi_hba_thread_taddrs(self
, taddrs
, mt
, SE_BUSCONFIG
,
7570 scsi_hba_taddr_config_thr
);
7572 /* free vector of target addresses */
7573 for (taddr
= taddrs
; *taddr
; taddr
++)
7574 kmem_free(*taddr
, strlen(*taddr
) + 1);
7575 kmem_free(taddrs
, sizeof (char *) * (ntargets
+ 1));
7576 return (NDI_SUCCESS
);
7580 * Transport independent bus_configone BUS_CONFIG_ONE implementation. Takes
7581 * same arguments, minus op, as scsi_hba_bus_config(), tran_bus_config(),
7582 * and scsi_hba_bus_config_spi().
7585 scsi_hba_bus_configone(dev_info_t
*self
, uint_t flags
, char *arg
,
7586 dev_info_t
**childp
)
7593 char nameaddr
[SCSI_MAXNAMELEN
];
7594 extern int i_ndi_make_spec_children(dev_info_t
*, uint_t
);
7595 struct scsi_device
*sd0
, *sd
;
7599 /* parse_name modifies arg1, we must duplicate "name@addr" */
7600 (void) strcpy(nameaddr
, arg
);
7601 i_ddi_parse_name(nameaddr
, &name
, &addr
, NULL
);
7603 /* verify the form of the node - we need an @addr */
7604 if ((name
== NULL
) || (addr
== NULL
) ||
7605 (*name
== '\0') || (*addr
== '\0')) {
7607 * OBP may create ill formed template/stub/wild-card
7608 * nodes (no @addr) for legacy driver loading methods -
7611 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "%s ill formed", arg
));
7612 return (NDI_FAILURE
);
7616 * Check to see if this is a non-scsi flavor configuration operation.
7618 if (strcmp(name
, "smp") == 0) {
7620 * Configure the child, and if we're successful return with
7623 return (smp_hba_bus_config(self
, addr
, childp
));
7627 * The framework does not ensure the creation of driver.conf
7628 * nodes prior to calling a nexus bus_config. For legacy
7629 * support of driver.conf file nodes we want to create our
7630 * driver.conf file children now so that we can detect if we
7631 * are being asked to bus_configone one of these nodes.
7633 * Needing driver.conf file nodes prior to bus config is unique
7634 * to scsi_enumeration mixed mode (legacy driver.conf and
7635 * dynamic SID node) support. There is no general need for the
7636 * framework to make driver.conf children prior to bus_config.
7638 * We enter our HBA (self) prior to scsi_device_config, and
7639 * pass it our circ. The scsi_device_config may exit the
7640 * HBA around scsi_probe() operations to allow for parallelism.
7641 * This is done after the probe node "@addr" is available as a
7642 * barrier to prevent parallel probes of the same device. The
7643 * probe node is also configured in a way that it can't be
7644 * removed by the framework until we are done with it.
7646 * NOTE: The framework is currently preventing many parallel
7647 * sibling operations (such as attaches), so the parallelism
7648 * we are providing is of marginal use until that is improved.
7649 * The most logical way to solve this would be to have separate
7650 * target and lun nodes. This would be a large change in the
7651 * format of /devices paths and is not being pursued at this
7652 * time. The need for parallelism will become more of an issue
7653 * with top-down attach for mpxio/vhci and for iSCSI support.
7654 * We may want to eventually want a dual mode implementation,
7655 * where the HBA determines if we should construct separate
7656 * target and lun devinfo nodes.
7658 scsi_hba_devi_enter(self
, &circ
);
7659 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s config_one", name
, addr
));
7660 (void) i_ndi_make_spec_children(self
, flags
);
7663 * For bus_configone, we make sure that we can find LUN0
7664 * first. This allows the delayed probe/barrier deletion for a
7665 * non-existent LUN0 (if enabled in scsi_device_config) to
7666 * cover all LUNs on the target. This is done to minimize the
7667 * number of independent target selection timeouts that occur
7668 * when a target with many LUNs is no longer accessible
7669 * (powered off). This removes the need for target driver
7670 * probe cache implementations.
7672 * This optimization may not be desirable in a pure bridge
7673 * environment where targets on the other side of the bridge
7674 * show up as LUNs to the host. If we ever need to support
7675 * such a configuration then we should consider implementing a
7676 * SCSI_OPTIONS_ILUN0 bit.
7678 * NOTE: we are *not* applying any target limitation filtering
7679 * to bus_configone, which means that we are relying on the
7680 * HBA tran_tgt_init entry point invoked by scsi_busctl_initchild
7683 sd0
= (struct scsi_device
*)-1;
7684 lcp
= strchr(addr
, ','); /* "addr,lun[,sfunc]" */
7687 * With "tgt,lun[,sfunc]" addressing, multiple addressing levels
7688 * have been compressed into single devinfo node unit-address.
7689 * This presents a mismatch - there is no bus_config to discover
7690 * LUNs below a specific target, the only choice is to
7691 * BUS_CONFIG_ALL the HBA. To support BUS_CONFIG_ALL_LUNS below
7692 * a specific target, a bus_configone with lun address of "*"
7693 * triggers lun discovery below a target.
7695 if (*(lcp
+ 1) == '*') {
7696 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7697 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7698 "scsi-enumeration", scsi_enumeration
);
7699 mt
|= scsi_hba_log_mt_disable
;
7701 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7702 "%s@%s lun enumeration triggered", name
, addr
));
7703 *lcp
= '\0'; /* turn ',' into '\0' */
7704 scsi_hba_devi_exit(self
, circ
);
7705 (void) scsi_hba_bus_config_taddr(self
, addr
,
7707 return (NDI_FAILURE
);
7710 /* convert hex lun number from ascii */
7711 lun64
= scsi_addr_to_lun64(lcp
+ 1);
7713 if ((lun64
!= 0) && (lun64
!= SCSI_LUN64_ILLEGAL
)) {
7715 * configure ",0" lun first, saving off
7716 * original lun characters.
7722 sd0
= scsi_device_config(self
,
7723 NULL
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7725 /* restore original lun */
7730 * Apply maxlun filtering.
7732 * Future: We still have the kludged
7733 * scsi_check_ss2_LUN_limit() filtering off
7734 * scsi_probe() to catch bogus driver.conf
7737 if (sd0
&& (lun64
< SCSI_32LUNS_PER_TARGET
) &&
7738 (lun64
>= scsi_get_scsi_maxluns(sd0
))) {
7740 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7741 "%s@%s filtered", name
, addr
));
7743 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7744 "%s@%s lun 0 %s", name
, addr
,
7745 sd0
? "worked" : "failed"));
7750 * configure the requested device if LUN0 exists or we were
7751 * unable to determine the lun format to determine if LUN0
7755 sd
= scsi_device_config(self
,
7756 name
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7759 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7760 "%s@%s no lun 0 or filtered lun", name
, addr
));
7764 * We know what we found, to reduce overhead we finish BUS_CONFIG_ONE
7765 * processing without calling back to the frameworks
7766 * ndi_busop_bus_config (unless we goto framework below).
7768 * If the reference is to a driver name and we created a generic name
7769 * (bound to that driver) we will still succeed. This is important
7770 * for correctly resolving old drivername references to device that now
7771 * uses a generic names across the transition to generic naming. This
7772 * is effectively an internal implementation of the NDI_DRIVERNAME flag.
7774 * We also need to special case the resolve_pathname OBP boot-device
7775 * case (modrootloaded == 0) where reference is to a generic name but
7776 * we created a legacy driver name node by returning just returning
7779 if (sd
&& sd
->sd_dev
&&
7780 ((strcmp(ddi_node_name(sd
->sd_dev
), name
) == 0) ||
7781 (strcmp(ddi_driver_name(sd
->sd_dev
), name
) == 0) ||
7782 (modrootloaded
== 0)) &&
7783 (ndi_devi_online(sd
->sd_dev
,
7784 flags
& NDI_NO_EVENT
) == NDI_SUCCESS
)) {
7786 /* device attached, return devinfo node with hold */
7788 *childp
= sd
->sd_dev
;
7789 ndi_hold_devi(sd
->sd_dev
);
7792 * In the process of failing we may have added nodes to the HBA
7793 * (self), clearing DEVI_MADE_CHILDREN. To reduce the overhead
7794 * associated with the frameworks reaction to this we clear the
7797 mutex_enter(&DEVI(self
)->devi_lock
);
7798 DEVI(self
)->devi_flags
&= ~DEVI_MADE_CHILDREN
;
7799 mutex_exit(&DEVI(self
)->devi_lock
);
7803 * The framework may still be able to succeed with
7804 * with its GENERIC_PROP code.
7806 scsi_hba_devi_exit(self
, circ
);
7807 if (flags
& NDI_DRV_CONF_REPROBE
)
7808 flags
|= NDI_CONFIG_REPROBE
;
7809 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7810 return (ndi_busop_bus_config(self
, flags
, BUS_CONFIG_ONE
,
7811 (void *)arg
, childp
, 0));
7814 scsi_hba_devi_exit(self
, circ
);
7819 * Perform SCSI Parallel Interconnect bus_config
7822 scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
7823 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7829 * Enumerate scsi target devices: See if we are doing generic dynamic
7830 * enumeration: if driver.conf has not specified the 'scsi-enumeration'
7831 * knob then use the global scsi_enumeration knob.
7833 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7834 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7835 "scsi-enumeration", scsi_enumeration
);
7836 mt
|= scsi_hba_log_mt_disable
;
7838 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0) {
7840 * Static driver.conf file enumeration:
7842 * Force reprobe for BUS_CONFIG_ONE or when manually
7843 * reconfiguring via devfsadm(1m) to emulate deferred attach.
7844 * Reprobe only discovers driver.conf enumerated nodes, more
7845 * dynamic implementations probably require their own
7848 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
7849 flags
|= NDI_CONFIG_REPROBE
;
7850 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7851 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
7854 if (scsi_hba_bus_config_debug
)
7855 flags
|= NDI_DEVI_DEBUG
;
7858 * Generic spi dynamic bus config enumeration to discover and enumerate
7859 * the target device nodes we are looking for.
7862 case BUS_CONFIG_ONE
: /* enumerate the named child */
7863 ret
= scsi_hba_bus_configone(self
, flags
, (char *)arg
, childp
);
7866 case BUS_CONFIG_ALL
: /* enumerate all children on the bus */
7867 case BUS_CONFIG_DRIVER
: /* enumerate all children that bind to driver */
7868 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7869 "BUS_CONFIG_%s mt %x",
7870 (op
== BUS_CONFIG_ALL
) ? "ALL" : "DRIVER", mt
));
7873 * Enumerate targets on SCSI parallel interconnect and let the
7874 * framework finish the operation (attach the nodes).
7876 if ((ret
= scsi_hba_bus_configall_spi(self
, mt
)) == NDI_SUCCESS
)
7877 ret
= ndi_busop_bus_config(self
, flags
, op
,
7889 * Perform SCSI Parallel Interconnect bus_unconfig
7892 scsi_hba_bus_unconfig_spi(dev_info_t
*self
, uint_t flags
,
7893 ddi_bus_config_op_t op
, void *arg
)
7900 * See if we are doing generic dynamic enumeration: if driver.conf has
7901 * not specified the 'scsi-enumeration' knob then use the global
7902 * scsi_enumeration knob.
7904 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7905 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7906 "scsi-enumeration", scsi_enumeration
);
7907 mt
|= scsi_hba_log_mt_disable
;
7909 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0)
7910 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
7912 if (scsi_hba_bus_config_debug
)
7913 flags
|= NDI_DEVI_DEBUG
;
7915 scsi_hba_devi_enter(self
, &circ
);
7917 case BUS_UNCONFIG_ONE
:
7918 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7919 "unconfig one: %s", (char *)arg
));
7923 case BUS_UNCONFIG_ALL
:
7924 case BUS_UNCONFIG_DRIVER
:
7933 /* Perform the generic default bus unconfig */
7934 if (ret
== NDI_SUCCESS
)
7935 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
7937 scsi_hba_devi_exit(self
, circ
);
7943 scsi_hba_bus_config_tgtmap(dev_info_t
*self
, uint_t flags
,
7944 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7946 scsi_hba_tran_t
*tran
;
7947 impl_scsi_tgtmap_t
*tgtmap
;
7948 uint64_t tsa
= 0; /* clock64_t */
7952 int ret
= NDI_FAILURE
;
7954 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
7955 (op
!= BUS_CONFIG_DRIVER
))
7958 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7959 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7963 * MPXIO is never a sure thing (and we have mixed children), so
7964 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
7965 * search for both devinfo and pathinfo children.
7967 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
7968 * devinfo/pathinfo children in parallel (instead of old way of
7969 * looking for one form of child and then doing "fallback" to
7970 * look for other form of child).
7972 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7975 * If bus_config occurred within the map create-to-hotplug_sync window,
7976 * we need the framework to wait for children that are physicaly
7977 * present at map create time to show up (via tgtmap hotplug config).
7979 * The duration of this window is specified by the HBA driver at
7980 * scsi_hba_tgtmap_create(9F) time (during attach(9E)). Its
7981 * 'csync_usec' value is selected based on how long it takes the HBA
7982 * driver to get from map creation to initial observation for something
7983 * already plugged in. Estimate high, a low estimate can result in
7984 * devices not showing up correctly on first reference. The call to
7985 * ndi_busop_bus_config needs a timeout value large enough so that
7986 * the map sync call further down is not a noop (i.e. done against
7987 * an empty map when something is infact plugged in). With
7988 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
7989 * soon as the desired device is enumerated via hotplug - so we are
7990 * not committed to waiting the entire time.
7992 * We are typically outside the window, so timeout is 0.
7994 sync_usec
= tgtmap
->tgtmap_create_csync_usec
;
7995 if (tgtmap
->tgtmap_create_window
) {
7996 tsa
= ddi_get_lbolt64() - tgtmap
->tgtmap_create_time
;
7997 if (tsa
< drv_usectohz(sync_usec
)) {
7998 tsa
= drv_usectohz(sync_usec
) - tsa
;
7999 ret
= ndi_busop_bus_config(self
,
8000 flags
, op
, arg
, childp
, (clock_t)tsa
);
8002 tsa
= 0; /* passed window */
8004 /* First one out closes the window. */
8005 tgtmap
->tgtmap_create_window
= 0;
8006 } else if (op
== BUS_CONFIG_ONE
)
8007 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8009 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
8010 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
8011 goto out
; /* performance path */
8014 * We sync if we were in the window, on the first bus_config_one, and
8015 * every bus_config_all (or bus_config_driver).
8017 if (tsa
|| (tgtmap
->tgtmap_sync_cnt
== 0) ||
8018 (op
!= BUS_CONFIG_ONE
)) {
8020 * Sync current observations in the map and look again. We
8021 * place an upper bound on the amount of time we will wait for
8022 * sync to complete to avoid a bad device causing this
8023 * busconfig operation to hang.
8025 * We are typically stable, so damap_sync returns immediately.
8027 * Max time to wait for sync is settle_usec per possible device.
8029 tgtmap
->tgtmap_sync_cnt
++;
8030 maxdev
= damap_size(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8031 maxdev
= (maxdev
> scsi_hba_map_settle_f
) ? maxdev
:
8032 scsi_hba_map_settle_f
;
8033 sync_usec
= maxdev
* tgtmap
->tgtmap_settle_usec
;
8034 synced
= scsi_tgtmap_sync((scsi_hba_tgtmap_t
*)tgtmap
,
8037 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8038 "tgtmap_sync timeout"));
8042 if (op
== BUS_CONFIG_ONE
)
8043 ret
= scsi_hba_bus_configone(self
, flags
, arg
, childp
);
8045 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8049 if (ret
!= NDI_SUCCESS
) {
8050 if (scsi_hba_bus_config_failure_msg
||
8051 scsi_hba_bus_config_failure_dbg
) {
8052 scsi_hba_bus_config_failure_msg
--;
8053 printf("%s%d: bus_config_tgtmap %p failure on %s: "
8055 ddi_driver_name(self
), ddi_get_instance(self
),
8057 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8060 if (scsi_hba_bus_config_failure_dbg
) {
8061 scsi_hba_bus_config_failure_dbg
--;
8062 debug_enter("config_tgtmap failure");
8064 } else if (scsi_hba_bus_config_success_msg
||
8065 scsi_hba_bus_config_success_dbg
) {
8066 scsi_hba_bus_config_success_msg
--;
8067 printf("%s%d: bus_config_tgtmap %p success on %s: %d %d\n",
8068 ddi_driver_name(self
), ddi_get_instance(self
),
8070 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8072 if (scsi_hba_bus_config_success_dbg
) {
8073 scsi_hba_bus_config_success_dbg
--;
8074 debug_enter("config_tgtmap success");
8082 scsi_hba_bus_unconfig_tgtmap(dev_info_t
*self
, uint_t flags
,
8083 ddi_bus_config_op_t op
, void *arg
)
8085 int ret
= NDI_FAILURE
;
8088 case BUS_UNCONFIG_ONE
:
8089 case BUS_UNCONFIG_DRIVER
:
8090 case BUS_UNCONFIG_ALL
:
8097 if (ret
== NDI_SUCCESS
) {
8098 flags
&= ~NDI_DEVI_REMOVE
;
8099 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8105 scsi_hba_bus_config_iportmap(dev_info_t
*self
, uint_t flags
,
8106 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8108 scsi_hba_tran_t
*tran
;
8109 impl_scsi_iportmap_t
*iportmap
;
8112 uint64_t tsa
= 0; /* clock64_t */
8115 int ret
= NDI_FAILURE
;
8117 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
8118 (op
!= BUS_CONFIG_DRIVER
))
8121 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8122 iportmap
= (impl_scsi_iportmap_t
*)tran
->tran_iportmap
;
8126 * MPXIO is never a sure thing (and we have mixed children), so
8127 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
8128 * search for both devinfo and pathinfo children.
8130 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
8131 * devinfo/pathinfo children in parallel (instead of old way of
8132 * looking for one form of child and then doing "fallback" to
8133 * look for other form of child).
8135 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
8138 * If bus_config occurred within the map create-to-hotplug_sync window,
8139 * we need the framework to wait for children that are physicaly
8140 * present at map create time to show up (via iportmap hotplug config).
8142 * The duration of this window is specified by the HBA driver at
8143 * scsi_hba_iportmap_create(9F) time (during attach(9E)). Its
8144 * 'csync_usec' value is selected based on how long it takes the HBA
8145 * driver to get from map creation to initial observation for something
8146 * already plugged in. Estimate high, a low estimate can result in
8147 * devices not showing up correctly on first reference. The call to
8148 * ndi_busop_bus_config needs a timeout value large enough so that
8149 * the map sync call further down is not a noop (i.e. done against
8150 * an empty map when something is infact plugged in). With
8151 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
8152 * soon as the desired device is enumerated via hotplug - so we are
8153 * not committed to waiting the entire time.
8155 * We are typically outside the window, so timeout is 0.
8157 sync_usec
= iportmap
->iportmap_create_csync_usec
;
8158 if (iportmap
->iportmap_create_window
) {
8159 tsa
= ddi_get_lbolt64() - iportmap
->iportmap_create_time
;
8160 if (tsa
< drv_usectohz(sync_usec
)) {
8161 tsa
= drv_usectohz(sync_usec
) - tsa
;
8162 ret
= ndi_busop_bus_config(self
,
8163 flags
, op
, arg
, childp
, (clock_t)tsa
);
8165 tsa
= 0; /* passed window */
8167 /* First one out closes the window. */
8168 iportmap
->iportmap_create_window
= 0;
8169 } else if (op
== BUS_CONFIG_ONE
)
8170 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8172 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
8173 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
8174 goto out
; /* performance path */
8177 * We sync if we were in the window, on the first bus_config_one, and
8178 * every bus_config_all (or bus_config_driver).
8180 if (tsa
|| (iportmap
->iportmap_sync_cnt
== 0) ||
8181 (op
!= BUS_CONFIG_ONE
)) {
8183 * Sync current observations in the map and look again. We
8184 * place an upper bound on the amount of time we will wait for
8185 * sync to complete to avoid a bad device causing this
8186 * busconfig operation to hang.
8188 * We are typically stable, so damap_sync returns immediately.
8190 * Max time to wait for sync is settle_usec times settle factor.
8192 iportmap
->iportmap_sync_cnt
++;
8193 synced
= damap_sync(iportmap
->iportmap_dam
, sync_usec
);
8195 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8196 "iportmap_sync timeout"));
8200 if (op
== BUS_CONFIG_ONE
) {
8201 /* create the iport node child */
8202 scsi_hba_devi_enter(self
, &circ
);
8203 if ((child
= scsi_hba_bus_config_port(self
, (char *)arg
,
8204 SE_BUSCONFIG
)) != NULL
) {
8206 ndi_hold_devi(child
);
8211 scsi_hba_devi_exit(self
, circ
);
8213 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8217 if (ret
!= NDI_SUCCESS
) {
8218 if (scsi_hba_bus_config_failure_msg
||
8219 scsi_hba_bus_config_failure_dbg
) {
8220 scsi_hba_bus_config_failure_msg
--;
8221 printf("%s%d: bus_config_iportmap %p failure on %s: "
8223 ddi_driver_name(self
), ddi_get_instance(self
),
8225 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8228 if (scsi_hba_bus_config_failure_dbg
) {
8229 scsi_hba_bus_config_failure_dbg
--;
8230 debug_enter("config_iportmap failure");
8232 } else if (scsi_hba_bus_config_success_msg
||
8233 scsi_hba_bus_config_success_dbg
) {
8234 scsi_hba_bus_config_success_msg
--;
8235 printf("%s%d: bus_config_iportmap %p success on %s: %d %d\n",
8236 ddi_driver_name(self
), ddi_get_instance(self
),
8238 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8240 if (scsi_hba_bus_config_success_dbg
) {
8241 scsi_hba_bus_config_success_dbg
--;
8242 debug_enter("config_iportmap success");
8250 scsi_hba_bus_unconfig_iportmap(dev_info_t
*self
, uint_t flags
,
8251 ddi_bus_config_op_t op
, void *arg
)
8253 flags
&= ~NDI_DEVI_REMOVE
;
8254 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8258 * SCSI HBA bus config enumeration entry point. Called via the bus_ops
8259 * bus_config entry point for all SCSA HBA drivers.
8261 * o If an HBA implements its own bus_config via tran_bus_config then we
8262 * invoke it. An HBA that implements its own tran_bus_config entry point
8263 * may still call back into common SCSA code bus_config code for:
8265 * o SPI bus_config (scsi_hba_bus_spi)
8266 * o LUN and secondary function enumeration (scsi_hba_enum_lsf_of_t()).
8267 * o configuration of a specific device (scsi_device_config).
8268 * o determining 1275 SCSI nodename and compatible property
8269 * (scsi_hba_nodename_compatible_get/_free).
8271 * o Otherwise we implement a SCSI parallel interface (spi) bus config.
8273 * Return NDI_SUCCESS if we might have created a new node.
8274 * Return NDI_FAILURE if we definitely did not create a new node.
8277 scsi_hba_bus_config(dev_info_t
*self
, uint_t flags
,
8278 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8280 scsi_hba_tran_t
*tran
;
8283 /* make sure that we will not disappear */
8284 ASSERT(DEVI(self
)->devi_ref
);
8286 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8288 /* NULL tran driver.conf config (used by cmdk). */
8289 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
8290 flags
|= NDI_CONFIG_REPROBE
;
8291 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
8294 /* Check if self is HBA-only node. */
8295 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8296 /* The bus_config request is to configure iports below HBA. */
8300 * Sparc's 'boot-device' OBP property value lacks an /iport@X/
8301 * component. Prior to the mount of root, we drive a disk@
8302 * BUS_CONFIG_ONE operatino down a level to resolve an
8303 * OBP 'boot-device' path.
8305 * Future: Add (modrootloaded == 0) below, and insure that
8306 * all attempts bus_conf of 'bo_name' (in OBP form) occur
8307 * prior to 'modrootloaded = 1;' assignment in vfs_mountroot.
8309 if ((op
== BUS_CONFIG_ONE
) &&
8310 (strncmp((char *)arg
, "disk@", strlen("disk@")) == 0)) {
8311 return (scsi_hba_bus_config_prom_node(self
,
8312 flags
, arg
, childp
));
8316 if (tran
->tran_iportmap
) {
8317 /* config based on scsi_hba_iportmap API */
8318 ret
= scsi_hba_bus_config_iportmap(self
,
8319 flags
, op
, arg
, childp
);
8321 /* config based on 'iport_register' API */
8322 ret
= scsi_hba_bus_config_iports(self
,
8323 flags
, op
, arg
, childp
);
8328 /* Check to see how the iport/HBA does target/lun bus config. */
8329 if (tran
->tran_bus_config
) {
8330 /* HBA config based on Sun-private/legacy tran_bus_config */
8331 ret
= tran
->tran_bus_config(self
, flags
, op
, arg
, childp
);
8332 } else if (tran
->tran_tgtmap
) {
8333 /* SCSAv3 config based on scsi_hba_tgtmap_*() API */
8334 ret
= scsi_hba_bus_config_tgtmap(self
, flags
, op
, arg
, childp
);
8336 /* SCSA config based on SCSI Parallel Interconnect */
8337 ret
= scsi_hba_bus_config_spi(self
, flags
, op
, arg
, childp
);
8343 * Called via the bus_ops bus_unconfig entry point for SCSI HBA drivers.
8346 scsi_hba_bus_unconfig(dev_info_t
*self
, uint_t flags
,
8347 ddi_bus_config_op_t op
, void *arg
)
8350 scsi_hba_tran_t
*tran
;
8353 tran
= ddi_get_driver_private(self
);
8355 /* NULL tran driver.conf unconfig (used by cmdk). */
8356 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8360 * Purge barrier/probe node children. We do this prior to
8361 * tran_bus_unconfig in case the unconfig implementation calls back
8362 * into the common code at a different enumeration level, such a
8363 * scsi_device_config, which still creates barrier/probe nodes.
8365 scsi_hba_devi_enter(self
, &circ
);
8366 scsi_hba_barrier_purge(self
);
8367 scsi_hba_devi_exit(self
, circ
);
8369 /* DEBUG: for testing, allow bus_unconfig do drive removal. */
8370 if (scsi_hba_bus_unconfig_remove
)
8371 flags
|= NDI_DEVI_REMOVE
;
8373 /* Check if self is HBA-only node. */
8374 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8375 /* The bus_config request is to unconfigure iports below HBA. */
8376 if (tran
->tran_iportmap
) {
8377 /* SCSAv3 unconfig based on scsi_hba_iportmap API */
8378 ret
= scsi_hba_bus_unconfig_iportmap(self
,
8380 } else if (tran
->tran_bus_unconfig
) {
8381 /* HBA unconfig based on Sun-private/legacy API */
8382 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8384 /* Standard framework unconfig. */
8385 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8390 /* Check to see how the iport/HBA does target/lun bus unconfig. */
8391 if (tran
->tran_bus_unconfig
) {
8392 /* HBA unconfig based on Sun-private/legacy tran_bus_unconfig */
8393 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8394 } else if (tran
->tran_tgtmap
) {
8395 /* SCSAv3 unconfig based on scsi_hba_tgtmap_*() API */
8396 ret
= scsi_hba_bus_unconfig_tgtmap(self
, flags
, op
, arg
);
8398 /* SCSA unconfig based on SCSI Parallel Interconnect */
8399 ret
= scsi_hba_bus_unconfig_spi(self
, flags
, op
, arg
);
8405 scsi_tgtmap_scsi_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8407 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8408 dev_info_t
*self
= tran
->tran_iport_dip
;
8409 impl_scsi_tgtmap_t
*tgtmap
;
8413 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8414 tgtaddr
= damap_id2addr(mapp
, tgtid
);
8416 if (scsi_lunmap_create(self
, tgtmap
, tgtaddr
) != DDI_SUCCESS
) {
8417 SCSI_HBA_LOG((_LOG_NF(WARN
),
8418 "failed to create lunmap for %s", tgtaddr
));
8421 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8422 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8424 mt
|= scsi_hba_log_mt_disable
;
8426 cfg_status
= scsi_hba_bus_config_taddr(self
, tgtaddr
, mt
, SE_HP
);
8427 if (cfg_status
!= NDI_SUCCESS
) {
8428 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s config status %d",
8429 damap_name(mapp
), tgtaddr
, cfg_status
));
8430 scsi_lunmap_destroy(self
, tgtmap
, tgtaddr
);
8431 return (DAM_FAILURE
);
8434 return (DAM_SUCCESS
);
8439 scsi_tgtmap_scsi_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8441 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8442 dev_info_t
*self
= tran
->tran_iport_dip
;
8443 impl_scsi_tgtmap_t
*tgtmap
;
8446 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8447 tgt_addr
= damap_id2addr(mapp
, tgtid
);
8449 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
),
8451 scsi_lunmap_destroy(self
, tgtmap
, tgt_addr
);
8452 return (DAM_SUCCESS
);
8456 scsi_tgtmap_smp_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8458 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8459 dev_info_t
*self
= tran
->tran_iport_dip
;
8462 addr
= damap_id2addr(mapp
, tgtid
);
8463 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8465 return ((smp_hba_bus_config_taddr(self
, addr
) == NDI_SUCCESS
) ?
8466 DAM_SUCCESS
: DAM_FAILURE
);
8470 scsi_tgtmap_smp_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8472 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8473 dev_info_t
*self
= tran
->tran_iport_dip
;
8476 char nameaddr
[SCSI_MAXNAMELEN
];
8479 addr
= damap_id2addr(mapp
, tgtid
);
8480 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8482 (void) snprintf(nameaddr
, sizeof (nameaddr
), "smp@%s", addr
);
8483 scsi_hba_devi_enter(self
, &circ
);
8484 if ((child
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
8485 scsi_hba_devi_exit(self
, circ
);
8486 return (DAM_SUCCESS
);
8489 if (ndi_devi_offline(child
,
8490 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
8491 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8492 "devinfo smp@%s offlined and removed", addr
));
8493 } else if (ndi_devi_device_remove(child
)) {
8494 /* Offline/remove failed, note new device_remove */
8495 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8496 "devinfo smp@%s offline failed, device_remove",
8499 scsi_hba_devi_exit(self
, circ
);
8500 return (DAM_SUCCESS
);
8505 scsi_tgtmap_smp_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8508 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8509 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8511 if (tgtmap
->tgtmap_activate_cb
) {
8512 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8513 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8516 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8517 tgt_addr
, SCSI_TGT_SMP_DEVICE
, tgt_privp
);
8523 scsi_tgtmap_smp_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8524 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8526 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8527 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8528 boolean_t tgtmap_rereport
;
8529 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8531 if (tgtmap
->tgtmap_deactivate_cb
) {
8532 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8533 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8534 tgt_addr
, damap_rsn
));
8536 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8537 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8538 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8539 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8540 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8541 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8543 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8544 "%s @%s deactivated with unknown rsn",
8545 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8550 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8551 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8552 SCSI_TGT_SMP_DEVICE
, tgt_privp
, tgtmap_rsn
);
8554 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8555 (tgtmap_rereport
== B_FALSE
)) {
8556 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8557 "%s enumeration failed, no more retries until "
8558 "config change occurs", tgt_addr
));
8565 scsi_tgtmap_scsi_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8568 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8569 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8571 if (tgtmap
->tgtmap_activate_cb
) {
8572 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8573 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8576 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8577 tgt_addr
, SCSI_TGT_SCSI_DEVICE
, tgt_privp
);
8583 scsi_tgtmap_scsi_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8584 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8586 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8587 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8588 boolean_t tgtmap_rereport
;
8589 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8591 if (tgtmap
->tgtmap_deactivate_cb
) {
8592 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8593 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8594 tgt_addr
, damap_rsn
));
8596 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8597 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8598 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8599 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8600 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8601 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8603 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8604 "%s @%s deactivated with unknown rsn", damap_name(
8605 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8610 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8611 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8612 SCSI_TGT_SCSI_DEVICE
, tgt_privp
, tgtmap_rsn
);
8614 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8615 (tgtmap_rereport
== B_FALSE
)) {
8616 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8617 "%s enumeration failed, no more retries until "
8618 "config change occurs", tgt_addr
));
8625 scsi_hba_tgtmap_create(dev_info_t
*self
, scsi_tgtmap_mode_t mode
,
8626 int csync_usec
, int settle_usec
, void *tgtmap_priv
,
8627 scsi_tgt_activate_cb_t activate_cb
, scsi_tgt_deactivate_cb_t deactivate_cb
,
8628 scsi_hba_tgtmap_t
**handle
)
8630 scsi_hba_tran_t
*tran
;
8633 impl_scsi_tgtmap_t
*tgtmap
;
8634 damap_rptmode_t rpt_style
;
8635 char *scsi_binding_set
;
8638 if (self
== NULL
|| csync_usec
== 0 ||
8639 settle_usec
== 0 || handle
== NULL
)
8640 return (DDI_FAILURE
);
8644 if (scsi_hba_iport_unit_address(self
) == NULL
)
8645 return (DDI_FAILURE
);
8648 case SCSI_TM_FULLSET
:
8649 rpt_style
= DAMAP_REPORT_FULLSET
;
8651 case SCSI_TM_PERADDR
:
8652 rpt_style
= DAMAP_REPORT_PERADDR
;
8655 return (DDI_FAILURE
);
8658 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
8661 return (DDI_FAILURE
);
8663 tgtmap
= kmem_zalloc(sizeof (*tgtmap
), KM_SLEEP
);
8664 tgtmap
->tgtmap_tran
= tran
;
8665 tgtmap
->tgtmap_activate_cb
= activate_cb
;
8666 tgtmap
->tgtmap_deactivate_cb
= deactivate_cb
;
8667 tgtmap
->tgtmap_mappriv
= tgtmap_priv
;
8669 tgtmap
->tgtmap_create_window
= 1; /* start with window */
8670 tgtmap
->tgtmap_create_time
= ddi_get_lbolt64();
8671 tgtmap
->tgtmap_create_csync_usec
= csync_usec
;
8672 tgtmap
->tgtmap_settle_usec
= settle_usec
;
8673 tgtmap
->tgtmap_sync_cnt
= 0;
8675 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8676 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8677 scsi_enumeration
) & SCSI_ENUMERATION_MT_TARGET_DISABLE
) ?
8678 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
8680 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.scsi",
8681 ddi_driver_name(self
), ddi_get_instance(self
));
8682 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8683 if (damap_create(context
, rpt_style
, optflags
, settle_usec
,
8684 tgtmap
, scsi_tgtmap_scsi_activate
, scsi_tgtmap_scsi_deactivate
,
8685 tran
, scsi_tgtmap_scsi_config
, scsi_tgtmap_scsi_unconfig
,
8686 &mapp
) != DAM_SUCCESS
) {
8687 kmem_free(tgtmap
, sizeof (*tgtmap
));
8688 return (DDI_FAILURE
);
8690 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
] = mapp
;
8692 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.smp",
8693 ddi_driver_name(self
), ddi_get_instance(self
));
8694 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8695 if (damap_create(context
, rpt_style
, optflags
,
8696 settle_usec
, tgtmap
, scsi_tgtmap_smp_activate
,
8697 scsi_tgtmap_smp_deactivate
,
8698 tran
, scsi_tgtmap_smp_config
, scsi_tgtmap_smp_unconfig
,
8699 &mapp
) != DAM_SUCCESS
) {
8700 damap_destroy(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8701 kmem_free(tgtmap
, sizeof (*tgtmap
));
8702 return (DDI_FAILURE
);
8704 tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
] = mapp
;
8706 tran
->tran_tgtmap
= (scsi_hba_tgtmap_t
*)tgtmap
;
8707 *handle
= (scsi_hba_tgtmap_t
*)tgtmap
;
8710 * We have now set tran_tgtmap, marking the tran as using tgtmap
8711 * enumeration services. To prevent the generation of legacy spi
8712 * 'binding-set' compatible forms, remove the 'scsi-binding-set'
8715 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
8716 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
8717 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
8718 if (strcmp(scsi_binding_set
, scsi_binding_set_spi
) == 0)
8719 (void) ndi_prop_remove(DDI_DEV_T_NONE
, self
,
8720 "scsi-binding-set");
8721 ddi_prop_free(scsi_binding_set
);
8723 return (DDI_SUCCESS
);
8727 scsi_hba_tgtmap_destroy(scsi_hba_tgtmap_t
*handle
)
8729 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8730 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8733 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8734 if (tgtmap
->tgtmap_dam
[i
]) {
8735 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8736 "%s", damap_name(tgtmap
->tgtmap_dam
[i
])));
8737 damap_destroy(tgtmap
->tgtmap_dam
[i
]);
8740 kmem_free(tgtmap
, sizeof (*tgtmap
));
8743 /* return 1 if all maps ended up syned */
8745 scsi_tgtmap_sync(scsi_hba_tgtmap_t
*handle
, int sync_usec
)
8747 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8748 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8753 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8754 if (tgtmap
->tgtmap_dam
[i
]) {
8755 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync begin",
8756 damap_name(tgtmap
->tgtmap_dam
[i
])));
8757 synced
= damap_sync(tgtmap
->tgtmap_dam
[i
], sync_usec
);
8758 all_synced
&= synced
;
8759 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync end %d",
8760 damap_name(tgtmap
->tgtmap_dam
[i
]), synced
));
8764 return (all_synced
);
8767 /* return 1 if all maps ended up empty */
8769 scsi_tgtmap_is_empty(scsi_hba_tgtmap_t
*handle
)
8771 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8772 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8777 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8778 if (tgtmap
->tgtmap_dam
[i
]) {
8779 empty
= damap_is_empty(tgtmap
->tgtmap_dam
[i
]);
8781 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s is_empty %d",
8782 damap_name(tgtmap
->tgtmap_dam
[i
]), empty
));
8790 scsi_tgtmap_beginf(scsi_hba_tgtmap_t
*handle
, boolean_t do_begin
)
8792 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8793 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8795 int rv
= DAM_SUCCESS
;
8798 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8799 if (tgtmap
->tgtmap_dam
[i
] == NULL
) {
8803 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8804 if (do_begin
== B_TRUE
) {
8805 if (i
== SCSI_TGT_SCSI_DEVICE
) {
8807 * In scsi_device context, so we have the
8808 * 'context' string, diagnose the case where
8809 * the tgtmap caller is failing to make
8810 * forward progress, i.e. the caller is never
8811 * completing an observation by calling
8812 * scsi_hbg_tgtmap_set_end. If this occurs,
8813 * the solaris target/lun state may be out
8814 * of sync with hardware.
8816 if (tgtmap
->tgtmap_reports
++ >=
8817 scsi_hba_tgtmap_reports_max
) {
8818 tgtmap
->tgtmap_noisy
++;
8819 if (tgtmap
->tgtmap_noisy
== 1) {
8820 SCSI_HBA_LOG((_LOG(WARN
),
8822 "%s: failing tgtmap begin",
8828 rv
= damap_addrset_begin(tgtmap
->tgtmap_dam
[i
]);
8830 rv
= damap_addrset_flush(tgtmap
->tgtmap_dam
[i
]);
8833 if (rv
!= DAM_SUCCESS
) {
8834 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8836 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8840 return ((rv
== DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8845 scsi_hba_tgtmap_set_begin(scsi_hba_tgtmap_t
*handle
)
8847 return (scsi_tgtmap_beginf(handle
, B_TRUE
));
8851 scsi_hba_tgtmap_set_flush(scsi_hba_tgtmap_t
*handle
)
8853 return (scsi_tgtmap_beginf(handle
, B_FALSE
));
8857 scsi_hba_tgtmap_set_add(scsi_hba_tgtmap_t
*handle
,
8858 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8860 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8861 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8863 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8864 return (DDI_FAILURE
);
8866 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8867 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8869 return ((damap_addrset_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
,
8870 NULL
, NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8875 scsi_hba_tgtmap_set_end(scsi_hba_tgtmap_t
*handle
, uint_t flags
)
8877 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8878 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8880 int rv
= DDI_SUCCESS
;
8883 tgtmap
->tgtmap_reports
= tgtmap
->tgtmap_noisy
= 0;
8885 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8886 if (tgtmap
->tgtmap_dam
[i
] == NULL
)
8888 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8889 if (damap_addrset_end(
8890 tgtmap
->tgtmap_dam
[i
], 0) != DAM_SUCCESS
) {
8891 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8896 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8902 scsi_hba_tgtmap_tgt_add(scsi_hba_tgtmap_t
*handle
,
8903 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8906 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8907 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8909 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8910 return (DDI_FAILURE
);
8912 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8913 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8915 return ((damap_addr_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
, NULL
,
8916 NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8920 scsi_hba_tgtmap_tgt_remove(scsi_hba_tgtmap_t
*handle
,
8921 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
)
8923 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8924 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8926 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8927 return (DDI_FAILURE
);
8929 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8930 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8932 return ((damap_addr_del(tgtmap
->tgtmap_dam
[tgt_type
],
8933 tgt_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8937 scsi_hba_tgtmap_lookup(scsi_hba_tgtmap_t
*handle
,
8938 char *tgt_addr
, scsi_tgtmap_tgt_type_t
*r_type
)
8940 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8941 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8945 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8946 tgtid
= damap_lookup(tgtmap
->tgtmap_dam
[i
], tgt_addr
);
8947 if (tgtid
!= NODAM
) {
8949 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8950 "%s @%s found: type %d",
8951 damap_name(tgtmap
->tgtmap_dam
[i
]), tgt_addr
, i
));
8952 damap_id_rele(tgtmap
->tgtmap_dam
[i
], tgtid
);
8953 return (DDI_SUCCESS
);
8957 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8958 "%s%d.tgtmap @%s not found",
8959 ddi_driver_name(self
), ddi_get_instance(self
), tgt_addr
));
8960 return (DDI_FAILURE
);
8964 * Return the unit-address of an 'iport' node, or NULL for non-iport node.
8967 scsi_hba_iport_unit_address(dev_info_t
*self
)
8970 * NOTE: Since 'self' could be a SCSA iport node or a SCSA HBA node,
8971 * we can't use SCSA flavors: the flavor of a SCSA HBA node is not
8972 * established/owned by SCSA, it is established by the nexus that
8973 * created the SCSA HBA node (PCI) as a child.
8975 * NOTE: If we want to support a node_name other than "iport" for
8976 * an iport node then we can add support for a "scsa-iport-node-name"
8977 * property on the SCSA HBA node. A SCSA HBA driver would set this
8978 * property on the SCSA HBA node prior to using the iport API.
8980 if (strcmp(ddi_node_name(self
), "iport") == 0)
8981 return (ddi_get_name_addr(self
));
8987 * Define a SCSI initiator port (bus/channel) for an HBA card that needs to
8988 * support multiple SCSI ports, but only has a single HBA devinfo node. This
8989 * function should be called from the HBA's attach(9E) implementation (when
8990 * processing the HBA devinfo node attach) after the number of SCSI ports on
8991 * the card is known or when the HBA driver DR handler detects a new port.
8992 * The function returns 0 on failure and 1 on success.
8994 * The implementation will add the port value into the "scsi-iports" property
8995 * value maintained on the HBA node as. These properties are used by the generic
8996 * scsi bus_config implementation to dynamicaly enumerate the specified iport
8997 * children. The enumeration code will, on demand, create the appropriate
8998 * iport children with a SCSI_ADDR_PROP_IPORTUA unit address. This node will
8999 * bind to the same driver as the HBA node itself. This means that an HBA
9000 * driver that uses iports should expect probe(9E), attach(9E), and detach(9E)
9001 * calls on the iport children of the HBA. If configuration for all ports was
9002 * already done during HBA node attach, the driver should just return
9003 * DDI_SUCCESS when confronted with an iport node.
9005 * A maximum of 32 iport ports are supported per HBA devinfo node.
9007 * A NULL "port" can be used to indicate that the framework should enumerate
9008 * target children on the HBA node itself, in addition to enumerating target
9009 * children on any iport nodes declared. There are two reasons that an HBA may
9010 * wish to have target children enumerated on both the HBA node and iport
9013 * o If, in the past, HBA hardware had only a single physical port but now
9014 * supports multiple physical ports, the updated driver that supports
9015 * multiple physical ports may want to avoid /devices path upgrade issues
9016 * by enumerating the first physical port under the HBA instead of as a
9019 * o Some hardware RAID HBA controllers (mlx, chs, etc) support multiple
9020 * SCSI physical ports configured so that various physical devices on
9021 * the physical ports are amalgamated into virtual devices on a virtual
9022 * port. Amalgamated physical devices no longer appear to the host OS
9023 * on the physical ports, but other non-amalgamated devices may still be
9024 * visible on the physical ports. These drivers use a model where the
9025 * physical ports are iport nodes and the HBA node is the virtual port to
9026 * the configured virtual devices.
9029 scsi_hba_iport_register(dev_info_t
*self
, char *port
)
9031 unsigned int ports
= 0;
9033 char **iports
, **newiports
;
9037 return (DDI_FAILURE
);
9039 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9040 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9043 if (ports
>= SCSI_HBA_MAX_IPORTS
) {
9044 ddi_prop_free(iports
);
9045 return (DDI_FAILURE
);
9048 if (rval
== DDI_PROP_SUCCESS
) {
9049 for (i
= 0; i
< ports
; i
++) {
9050 if (strcmp(port
, iports
[i
]) == 0) {
9051 /* iport already registered */
9052 ddi_prop_free(iports
);
9053 return (DDI_SUCCESS
);
9058 newiports
= kmem_alloc((sizeof (char *) * (ports
+ 1)), KM_SLEEP
);
9060 for (i
= 0; i
< ports
; i
++) {
9061 newiports
[i
] = strdup(iports
[i
]);
9063 newiports
[ports
] = strdup(port
);
9066 if (ddi_prop_update_string_array(DDI_DEV_T_NONE
, self
,
9067 "scsi-iports", newiports
, ports
) != DDI_PROP_SUCCESS
) {
9068 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
9069 "failed to establish %s %s",
9070 SCSI_ADDR_PROP_IPORTUA
, port
));
9076 /* If there is iport exist, free property */
9078 ddi_prop_free(iports
);
9079 for (i
= 0; i
< ports
; i
++) {
9080 strfree(newiports
[i
]);
9082 kmem_free(newiports
, (sizeof (char *)) * ports
);
9088 * Check if the HBA has any scsi_hba_iport_register()ed children.
9091 scsi_hba_iport_exist(dev_info_t
*self
)
9093 unsigned int ports
= 0;
9097 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9098 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9101 if (rval
!= DDI_PROP_SUCCESS
)
9104 /* If there is now at least 1 iport, then iports is valid */
9109 ddi_prop_free(iports
);
9115 scsi_hba_iport_find(dev_info_t
*self
, char *portnm
)
9119 unsigned int num_iports
= 0;
9120 int rval
= DDI_FAILURE
;
9122 dev_info_t
*child
= NULL
;
9124 /* check to see if this is an HBA that defined scsi iports */
9125 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9126 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9129 if (rval
!= DDI_SUCCESS
) {
9132 ASSERT(num_iports
> 0);
9134 /* check to see if this port was registered */
9135 for (i
= 0; i
< num_iports
; i
++) {
9136 if (strcmp(iports
[i
], portnm
) == 0)
9140 if (i
== num_iports
) {
9145 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9146 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s", portnm
);
9147 rval
= ndi_devi_config_one(self
, addr
, &child
, NDI_NO_EVENT
);
9148 kmem_free(addr
, SCSI_MAXNAMELEN
);
9150 if (rval
!= DDI_SUCCESS
) {
9154 ddi_prop_free(iports
);
9159 * Search/create the specified iport node
9162 scsi_hba_bus_config_port(dev_info_t
*self
, char *nameaddr
, scsi_enum_t se
)
9164 dev_info_t
*child
; /* iport child of HBA node */
9165 scsi_hba_tran_t
*tran
;
9170 * See if the iport node already exists.
9172 addr
= nameaddr
+ strlen("iport@");
9173 if (child
= ndi_devi_findchild(self
, nameaddr
)) {
9174 if (ndi_devi_device_isremoved(child
)) {
9175 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
9176 if (ndi_devi_device_insert(child
))
9177 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
9178 "devinfo iport@%s device_reinsert",
9188 * If config based on scsi_hba_iportmap API, only allow create
9191 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
9193 if (tran
->tran_iportmap
&& (se
!= SE_HP
))
9196 /* allocate and initialize a new "iport" node */
9197 ndi_devi_alloc_sleep(self
, "iport",
9198 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
9202 * Set the flavor of the child to be IPORT flavored
9204 ndi_flavor_set(child
, SCSA_FLAVOR_IPORT
);
9207 * Add the SCSI_ADDR_PROP_IPORTUA addressing property for this child.
9208 * This property is used to identify a iport node, and to represent the
9209 * nodes @addr form via node properties.
9211 * Add "compatible" property to the "scsi-iport" node to cause it bind
9212 * to the same driver as the HBA driver. Use the "driver" name
9213 * instead of the "binding name" to distinguish from hw node.
9215 * Give the HBA a chance, via tran_set_name_prop, to set additional
9216 * iport node properties or to change the "compatible" binding
9217 * prior to init_child.
9219 * NOTE: the order of these operations is important so that
9220 * scsi_hba_iport works when called.
9222 compat
= (char *)ddi_driver_name(self
);
9223 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
9224 SCSI_ADDR_PROP_IPORTUA
, addr
) != DDI_PROP_SUCCESS
) ||
9225 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, child
,
9226 "compatible", &compat
, 1) != DDI_PROP_SUCCESS
) ||
9227 ddi_pathname_obp_set(child
, NULL
) != DDI_SUCCESS
) {
9228 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s failed dynamic decoration",
9230 (void) ddi_remove_child(child
, 0);
9234 * Online/attach in order to get events so devfsadm will
9235 * create public names.
9237 ndi_hold_devi(child
);
9238 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
9239 ndi_rele_devi(child
);
9240 ndi_prop_remove_all(child
);
9241 (void) ndi_devi_free(child
);
9244 ndi_rele_devi(child
);
9252 * Future: When iportmap boot support is added, consider rewriting this to
9253 * perform a scsi_hba_bus_config(BUS_CONFIG_ALL) on self (HBA) followed by
9254 * a scsi_hba_bus_config(BUS_CONFIG_ONE) on each child of self (each iport).
9258 scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
9259 void *arg
, dev_info_t
**childp
)
9263 int ret
= NDI_FAILURE
;
9264 unsigned int num_iports
= 0;
9265 dev_info_t
*pdip
= NULL
;
9268 /* check to see if this is an HBA that defined scsi iports */
9269 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9270 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9273 if (ret
!= DDI_SUCCESS
) {
9277 ASSERT(num_iports
> 0);
9279 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9283 scsi_hba_devi_enter(self
, &circ
);
9285 /* create iport nodes for each scsi port/bus */
9286 for (i
= 0; i
< num_iports
; i
++) {
9287 bzero(addr
, SCSI_MAXNAMELEN
);
9288 /* Prepend the iport name */
9289 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9291 if (pdip
= scsi_hba_bus_config_port(self
, addr
, SE_BUSCONFIG
)) {
9292 if (ndi_busop_bus_config(self
, NDI_NO_EVENT
,
9293 BUS_CONFIG_ONE
, addr
, &pdip
, 0) !=
9298 * Try to configure child under iport see wehter
9299 * request node is the child of the iport node
9301 if (ndi_devi_config_one(pdip
, arg
, childp
,
9302 NDI_NO_EVENT
) == NDI_SUCCESS
) {
9309 scsi_hba_devi_exit(self
, circ
);
9311 kmem_free(addr
, SCSI_MAXNAMELEN
);
9313 ddi_prop_free(iports
);
9320 * Perform iport port/bus bus_config.
9323 scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
9324 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
9326 char *nameaddr
, *addr
;
9329 int ret
= NDI_FAILURE
;
9330 unsigned int num_iports
= 0;
9332 /* check to see if this is an HBA that defined scsi iports */
9333 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9334 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9337 if (ret
!= DDI_SUCCESS
) {
9341 ASSERT(num_iports
> 0);
9343 scsi_hba_devi_enter(self
, &circ
);
9346 case BUS_CONFIG_ONE
:
9347 /* return if this operation is not against an iport node */
9348 nameaddr
= (char *)arg
;
9349 if ((nameaddr
== NULL
) ||
9350 (strncmp(nameaddr
, "iport@", strlen("iport@")) != 0)) {
9352 scsi_hba_devi_exit(self
, circ
);
9353 ddi_prop_free(iports
);
9357 /* parse the port number from "iport@%s" */
9358 addr
= nameaddr
+ strlen("iport@");
9360 /* check to see if this port was registered */
9361 for (i
= 0; i
< num_iports
; i
++) {
9362 if (strcmp((iports
[i
]), addr
) == 0)
9366 if (i
== num_iports
) {
9371 /* create the iport node child */
9372 if (scsi_hba_bus_config_port(self
, nameaddr
, SE_BUSCONFIG
)) {
9377 case BUS_CONFIG_ALL
:
9378 case BUS_CONFIG_DRIVER
:
9379 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9380 /* create iport nodes for each scsi port/bus */
9381 for (i
= 0; i
< num_iports
; i
++) {
9382 bzero(addr
, SCSI_MAXNAMELEN
);
9383 /* Prepend the iport name */
9384 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9386 (void) scsi_hba_bus_config_port(self
, addr
,
9390 kmem_free(addr
, SCSI_MAXNAMELEN
);
9394 if (ret
== NDI_SUCCESS
) {
9397 * Mask NDI_PROMNAME since PROM doesn't have iport
9400 flags
&= (~NDI_PROMNAME
);
9402 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
9403 ret
= ndi_busop_bus_config(self
, flags
, op
,
9406 scsi_hba_devi_exit(self
, circ
);
9408 ddi_prop_free(iports
);
9414 scsi_iportmap_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9416 dev_info_t
*self
= (dev_info_t
*)arg
;
9418 char nameaddr
[SCSI_MAXNAMELEN
];
9422 scsi_hba_devi_enter(self
, &circ
);
9424 iport_addr
= damap_id2addr(mapp
, tgtid
);
9425 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9426 "%s @%s", damap_name(mapp
), iport_addr
));
9428 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", iport_addr
);
9429 childp
= scsi_hba_bus_config_port(self
, nameaddr
, SE_HP
);
9430 scsi_hba_devi_exit(self
, circ
);
9431 return (childp
!= NULL
? DAM_SUCCESS
: DAM_FAILURE
);
9435 scsi_iportmap_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9437 dev_info_t
*self
= arg
;
9438 dev_info_t
*childp
; /* iport child of HBA node */
9441 char nameaddr
[SCSI_MAXNAMELEN
];
9442 scsi_hba_tran_t
*tran
;
9444 addr
= damap_id2addr(mapp
, tgtid
);
9445 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
9447 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", addr
);
9448 scsi_hba_devi_enter(self
, &circ
);
9449 if ((childp
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
9450 scsi_hba_devi_exit(self
, circ
);
9451 return (DAM_FAILURE
);
9454 tran
= ddi_get_driver_private(childp
);
9457 ndi_hold_devi(childp
);
9458 scsi_hba_devi_exit(self
, circ
);
9461 * A begin/end (clear) against the iport's
9462 * tgtmap will trigger unconfigure of all
9463 * targets on the iport.
9465 * Future: This bit of code only works if the
9466 * target map reporting style is are full
9467 * reports and not per-address. Maybe we
9468 * should plan on handling this by
9469 * auto-unconfiguration when destroying the
9472 (void) scsi_hba_tgtmap_set_begin(tran
->tran_tgtmap
);
9473 (void) scsi_hba_tgtmap_set_end(tran
->tran_tgtmap
, 0);
9475 /* wait for unconfigure */
9476 (void) scsi_tgtmap_sync(tran
->tran_tgtmap
, 0);
9477 empty
= scsi_tgtmap_is_empty(tran
->tran_tgtmap
);
9479 scsi_hba_devi_enter(self
, &circ
);
9480 ndi_rele_devi(childp
);
9482 /* If begin/end/sync ends in empty map, offline/remove. */
9484 if (ndi_devi_offline(childp
,
9485 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
9486 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9487 "devinfo iport@%s offlined and removed",
9489 } else if (ndi_devi_device_remove(childp
)) {
9490 /* Offline/rem failed, note new device_remove */
9491 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9492 "devinfo iport@%s offline failed, "
9493 "device_remove", addr
));
9496 scsi_hba_devi_exit(self
, circ
);
9497 return (empty
? DAM_SUCCESS
: DAM_FAILURE
);
9502 scsi_hba_iportmap_create(dev_info_t
*self
, int csync_usec
, int settle_usec
,
9503 scsi_hba_iportmap_t
**handle
)
9505 scsi_hba_tran_t
*tran
;
9508 impl_scsi_iportmap_t
*iportmap
;
9510 if (self
== NULL
|| csync_usec
== 0 ||
9511 settle_usec
== 0 || handle
== NULL
)
9512 return (DDI_FAILURE
);
9516 if (scsi_hba_iport_unit_address(self
) != NULL
)
9517 return (DDI_FAILURE
);
9519 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
9522 return (DDI_FAILURE
);
9524 (void) snprintf(context
, sizeof (context
), "%s%d.iportmap",
9525 ddi_driver_name(self
), ddi_get_instance(self
));
9527 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
9528 settle_usec
, NULL
, NULL
, NULL
, self
,
9529 scsi_iportmap_config
, scsi_iportmap_unconfig
, &mapp
) !=
9531 return (DDI_FAILURE
);
9533 iportmap
= kmem_zalloc(sizeof (*iportmap
), KM_SLEEP
);
9534 iportmap
->iportmap_hba_dip
= self
;
9535 iportmap
->iportmap_dam
= mapp
;
9537 iportmap
->iportmap_create_window
= 1; /* start with window */
9538 iportmap
->iportmap_create_time
= ddi_get_lbolt64();
9539 iportmap
->iportmap_create_csync_usec
= csync_usec
;
9540 iportmap
->iportmap_settle_usec
= settle_usec
;
9541 iportmap
->iportmap_sync_cnt
= 0;
9543 tran
->tran_iportmap
= (scsi_hba_iportmap_t
*)iportmap
;
9544 *handle
= (scsi_hba_iportmap_t
*)iportmap
;
9546 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s", damap_name(mapp
)));
9547 return (DDI_SUCCESS
);
9551 scsi_hba_iportmap_destroy(scsi_hba_iportmap_t
*handle
)
9553 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9554 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9556 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9557 "%s", damap_name(iportmap
->iportmap_dam
)));
9559 damap_destroy(iportmap
->iportmap_dam
);
9560 kmem_free(iportmap
, sizeof (*iportmap
));
9564 scsi_hba_iportmap_iport_add(scsi_hba_iportmap_t
*handle
,
9565 char *iport_addr
, void *iport_priv
)
9567 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9568 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9570 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9571 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9573 return ((damap_addr_add(iportmap
->iportmap_dam
, iport_addr
, NULL
,
9574 NULL
, iport_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9578 scsi_hba_iportmap_iport_remove(scsi_hba_iportmap_t
*handle
,
9581 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9582 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9584 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9585 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9587 return ((damap_addr_del(iportmap
->iportmap_dam
,
9588 iport_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9592 scsi_hba_iportmap_lookup(scsi_hba_iportmap_t
*handle
,
9595 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9596 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9599 iportid
= damap_lookup(iportmap
->iportmap_dam
, iport_addr
);
9600 if (iportid
!= NODAM
) {
9601 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9603 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9604 damap_id_rele(iportmap
->iportmap_dam
, iportid
);
9605 return (DDI_SUCCESS
);
9608 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9610 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9611 return (DDI_FAILURE
);
9616 scsi_lunmap_config(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9618 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9619 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9620 dev_info_t
*self
= tran
->tran_iport_dip
;
9623 addr
= damap_id2addr(lundam
, lunid
);
9624 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9625 "%s @%s", damap_name(lundam
), addr
));
9626 if (scsi_hba_bus_configone_addr(self
, addr
, SE_HP
) != NULL
)
9627 return (DAM_SUCCESS
);
9629 return (DAM_FAILURE
);
9633 scsi_lunmap_unconfig(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9635 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9636 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9637 dev_info_t
*self
= tran
->tran_iport_dip
;
9640 addr
= damap_id2addr(lundam
, lunid
);
9641 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
),
9644 scsi_hba_bus_unconfigone_addr(self
, addr
);
9645 return (DAM_SUCCESS
);
9649 scsi_lunmap_create(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9657 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9658 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9660 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9661 tgtid
= damap_lookup(tgtdam
, taddr
);
9662 if (tgtid
== NODAM
) {
9663 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9664 "target %s not found", context
));
9665 return (DDI_FAILURE
);
9668 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
9670 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9671 "lunmap %s already created", context
));
9672 damap_id_rele(tgtdam
, tgtid
);
9673 return (DDI_FAILURE
);
9676 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
9677 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
9678 scsi_enumeration
) & SCSI_ENUMERATION_MT_LUN_DISABLE
) ?
9679 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
9681 /* NOTE: expected ref at tgtid/taddr: 2: caller + lookup. */
9682 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 2);
9683 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s creat, id %d ref %d",
9684 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9687 if (damap_create(context
, DAMAP_REPORT_FULLSET
, optflags
, 1,
9688 NULL
, NULL
, NULL
, tgtmap
, scsi_lunmap_config
, scsi_lunmap_unconfig
,
9689 &lundam
) != DAM_SUCCESS
) {
9690 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9691 "%s create failed, id %d ref %d",
9692 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9693 damap_id_rele(tgtdam
, tgtid
);
9694 return (DDI_FAILURE
);
9698 * Return with damap_id_hold at tgtid/taddr from damap_lookup to
9699 * account for damap_id_prv_set below.
9701 damap_id_priv_set(tgtdam
, tgtid
, lundam
);
9702 return (DDI_SUCCESS
);
9706 scsi_lunmap_destroy(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9713 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9714 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9716 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9717 tgtid
= damap_lookup(tgtdam
, taddr
);
9718 if (tgtid
== NODAM
) {
9719 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9720 "target %s not found", context
));
9724 lundam
= (damap_t
*)damap_id_priv_get(tgtdam
, tgtid
);
9725 if (lundam
== NULL
) {
9726 damap_id_rele(tgtdam
, tgtid
); /* from damap_lookup */
9727 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9728 "lunmap %s already destroyed", context
));
9732 /* NOTE: expected ref at tgtid/taddr: 3: priv_set + caller + lookup. */
9733 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 3);
9734 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s, id %d ref %d",
9735 damap_name(lundam
), tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9738 * A begin/end (clear) against a target's lunmap will trigger
9739 * unconfigure of all LUNs on the target.
9741 scsi_lunmap_set_begin(self
, lundam
);
9742 scsi_lunmap_set_end(self
, lundam
);
9744 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9745 "%s sync begin", damap_name(lundam
)));
9747 (void) damap_sync(lundam
, 0); /* wait for unconfigure */
9749 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9750 "%s sync end", damap_name(lundam
)));
9752 damap_id_priv_set(tgtdam
, tgtid
, NULL
);
9754 /* release hold established by damap_lookup above */
9755 damap_id_rele(tgtdam
, tgtid
);
9757 /* release hold established since scsi_lunmap_create() */
9758 damap_id_rele(tgtdam
, tgtid
);
9760 damap_destroy(lundam
);
9764 scsi_lunmap_set_begin(dev_info_t
*self
, damap_t
*lundam
)
9766 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9768 (void) damap_addrset_begin(lundam
);
9772 scsi_lunmap_set_add(dev_info_t
*self
, damap_t
*lundam
,
9773 char *taddr
, scsi_lun64_t lun64
, int sfunc
)
9775 char ua
[SCSI_MAXNAMELEN
];
9777 /* make unit address string form of "@taddr,lun[,sfunc]" */
9779 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
, taddr
, lun64
);
9781 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
",%x",
9782 taddr
, lun64
, sfunc
);
9784 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
), ua
));
9786 return ((damap_addrset_add(lundam
, ua
, NULL
, NULL
,
9787 NULL
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9791 scsi_lunmap_set_end(dev_info_t
*self
, damap_t
*lundam
)
9793 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9795 (void) damap_addrset_end(lundam
, 0);
9799 scsi_lunmap_lookup(dev_info_t
*self
, damap_t
*lundam
, char *addr
)
9803 if ((lunid
= damap_lookup(lundam
, addr
)) != NODAM
) {
9804 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9805 "%s @%s found", damap_name(lundam
), addr
));
9806 damap_id_rele(lundam
, lunid
);
9807 return (DDI_SUCCESS
);
9810 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9811 "%s @%s not found", damap_name(lundam
), addr
));
9812 return (DDI_FAILURE
);
9816 * phymap implementation
9818 * We manage the timed aggregation of phys into a phy map * by creating a
9819 * SAS port construct (based upon 'name' of "local,remote" SAS addresses)
9820 * upon the first link up. As time goes on additional phys may join that port.
9821 * After an appropriate amount of settle time, we trigger the activation
9822 * callback which will then take the resultant bit mask of phys (phymask) in
9823 * the SAS port and use that to call back to the callback function
9824 * provided by the additional caller.
9826 * We cross check to make sure that phys only exist in one SAS port at a
9827 * time by having soft state for each phy point back to the created
9830 * NOTE: Make SAS_PHY_UA_LEN max(SAS_PHY_PHYMASK_LEN, SAS_PHY_NAME_LEN)
9831 * so we have enough space if sas_phymap_bitset2phymaskua phymask address
9832 * is already in use, and we end up using port name as unit address.
9834 #define SAS_PHY_NAME_FMT "%" PRIx64 ",%" PRIx64
9835 #define SAS_PHY_NAME_LEN (16 + 1 + 16 + 1)
9836 #define SAS_PHY_NPHY (SAS2_PHYNUM_MAX + 1)
9837 #define SAS_PHY_PHYMASK_LEN ((roundup(SAS_PHY_NPHY, 4)) / 4)
9838 #if (SAS_PHY_PHYMASK_LEN > SAS_PHY_NAME_LEN)
9839 #define SAS_PHY_UA_LEN SAS_PHY_PHYMASK_LEN
9841 #define SAS_PHY_UA_LEN SAS_PHY_NAME_LEN
9843 typedef struct impl_sas_physet
{ /* needed for name2phys destroy */
9844 struct impl_sas_physet
*physet_next
;
9846 bitset_t
*physet_phys
;
9847 } impl_sas_physet_t
;
9848 typedef struct impl_sas_phymap
{
9849 dev_info_t
*phymap_self
;
9851 kmutex_t phymap_lock
;
9852 damap_t
*phymap_dam
;
9853 void *phymap_phy2name
;
9854 ddi_soft_state_bystr
*phymap_name2phys
; /* bitset */
9855 ddi_soft_state_bystr
*phymap_name2ua
;
9856 ddi_soft_state_bystr
*phymap_ua2name
;
9858 /* Noisy phy information - ensure forward progress for noisy phys */
9859 int phymap_phy_max
; /* max phy# */
9860 int phymap_reports
; /* per period */
9861 int phymap_reports_max
; /* scales */
9862 int phymap_phys_noisy
; /* detected */
9864 /* These are for callbacks to the consumer. */
9865 sas_phymap_activate_cb_t phymap_acp
;
9866 sas_phymap_deactivate_cb_t phymap_dcp
;
9867 void *phymap_private
;
9869 struct impl_sas_physet
*phymap_physets
;
9870 } impl_sas_phymap_t
;
9872 /* Detect noisy phy: max changes per stabilization period per phy. */
9873 static int sas_phymap_phy_max_factor
= 16;
9876 * Convert bitset into a unit-address string. The maximum string length would
9877 * be the maximum number of phys, rounded up by 4 and divided by 4.
9880 sas_phymap_bitset2phymaskua(bitset_t
*phys
, char *buf
)
9887 bit
= roundup(SAS_PHY_NPHY
, 4);
9894 if (bitset_in_set(phys
, bit
)) {
9899 if (cur
|| ptr
!= buf
) {
9900 *ptr
++ = "0123456789abcdef"[cur
];
9913 sas_phymap_config(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
9915 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
9916 char *context
= damap_name(phymap
->phymap_dam
);
9925 mutex_enter(&phymap
->phymap_lock
);
9926 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
9928 /* Get the name ("local,remote" address string) from damap. */
9929 damn
= damap_id2addr(phydam
, phyid
);
9931 /* Get the bitset of phys currently forming the port. */
9932 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, damn
);
9934 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: no phys",
9936 mutex_exit(&phymap
->phymap_lock
);
9937 return (DAM_FAILURE
);
9940 /* allocate, get, and initialize name index of name2ua map */
9941 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2ua
, damn
) !=
9943 SCSI_HBA_LOG((_LOG_NF(WARN
),
9944 "%s: %s: failed name2ua alloc", context
, damn
));
9945 mutex_exit(&phymap
->phymap_lock
);
9946 return (DAM_FAILURE
);
9948 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
9949 SCSI_HBA_LOG((_LOG_NF(WARN
),
9950 "%s: %s: no name2ua", context
, damn
));
9951 mutex_exit(&phymap
->phymap_lock
);
9952 return (DAM_FAILURE
);
9954 sas_phymap_bitset2phymaskua(phys
, ua
); /* set ua */
9956 /* see if phymask ua index already allocated in ua2name map */
9957 if (name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
)) {
9959 * The 'phymask' sas_phymap_bitset2phymaskua ua is
9960 * already in use. This means that original phys have
9961 * formed into a new port, and that the original port
9962 * still exists (it has migrated to some completely
9963 * different set of phys). In this corner-case we use
9964 * "local,remote" name as a 'temporary' unit address.
9965 * Reset ua in name2ua map.
9967 (void) strlcpy(ua
, damn
, SAS_PHY_NAME_LEN
);
9968 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9970 /* The "local,remote" ua should be new... */
9971 SCSI_HBA_LOG((_LOG_NF(WARN
),
9972 "%s: %s ua already configured",
9974 mutex_exit(&phymap
->phymap_lock
);
9975 return (DAM_SUCCESS
);
9979 /* allocate, get, and init ua index of ua2name map */
9980 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_ua2name
, ua
) !=
9982 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9983 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: failed ua2name alloc",
9985 mutex_exit(&phymap
->phymap_lock
);
9986 return (DAM_FAILURE
);
9988 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9990 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9991 SCSI_HBA_LOG((_LOG_NF(WARN
),
9992 "%s: %s: no ua2name", context
, ua
));
9993 mutex_exit(&phymap
->phymap_lock
);
9994 return (DAM_FAILURE
);
9997 /* set name in ua2name map */
9998 (void) strlcpy(name
, damn
, SAS_PHY_NAME_LEN
);
10000 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10001 "%s: %s: ua %s: activate", context
, damn
, ua
));
10003 if (phymap
->phymap_acp
) {
10005 * drop our lock and invoke the activation callback
10007 mutex_exit(&phymap
->phymap_lock
);
10009 (phymap
->phymap_acp
)(phymap
->phymap_private
, ua
, &ua_priv
);
10010 mutex_enter(&phymap
->phymap_lock
);
10011 damap_id_priv_set(phydam
, phyid
, ua_priv
);
10013 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10014 "%s: %s: ua %s: activate complete", context
, damn
, ua
));
10015 mutex_exit(&phymap
->phymap_lock
);
10016 return (DAM_SUCCESS
);
10021 sas_phymap_unconfig(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
10023 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
10024 char *context
= damap_name(phymap
->phymap_dam
);
10031 mutex_enter(&phymap
->phymap_lock
);
10032 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
10034 /* Get the name ("local,remote" address string) from damap. */
10035 damn
= damap_id2addr(phydam
, phyid
);
10037 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
10038 SCSI_HBA_LOG((_LOG_NF(WARN
),
10039 "%s: %s: no name2ua", context
, damn
));
10040 mutex_exit(&phymap
->phymap_lock
);
10041 return (DAM_FAILURE
);
10044 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10045 "%s: %s: ua %s: deactivate", context
, damn
, ua
));
10046 if (phymap
->phymap_dcp
) {
10047 ua_priv
= damap_id_priv_get(phydam
, phyid
);
10048 mutex_exit(&phymap
->phymap_lock
);
10049 (phymap
->phymap_dcp
)(phymap
->phymap_private
, ua
, ua_priv
);
10050 mutex_enter(&phymap
->phymap_lock
);
10052 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10053 "%s: %s: ua %s: deactivate complete", context
, damn
, ua
));
10055 /* delete ua<->name mappings */
10056 ddi_soft_state_bystr_free(phymap
->phymap_ua2name
, ua
);
10057 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
10058 mutex_exit(&phymap
->phymap_lock
);
10059 return (DAM_SUCCESS
);
10063 sas_phymap_create(dev_info_t
*self
, int settle_usec
,
10064 sas_phymap_mode_t mode
, void *mode_argument
, void *phymap_priv
,
10065 sas_phymap_activate_cb_t activate_cb
,
10066 sas_phymap_deactivate_cb_t deactivate_cb
,
10067 sas_phymap_t
**handlep
)
10069 _NOTE(ARGUNUSED(mode_argument
));
10071 impl_sas_phymap_t
*phymap
;
10073 if (self
== NULL
|| settle_usec
== 0 || handlep
== NULL
)
10074 return (DDI_FAILURE
);
10076 if (mode
!= PHYMAP_MODE_SIMPLE
)
10077 return (DDI_FAILURE
);
10079 phymap
= kmem_zalloc(sizeof (*phymap
), KM_SLEEP
);
10080 phymap
->phymap_self
= self
;
10081 phymap
->phymap_reports_max
= 1 * sas_phymap_phy_max_factor
;
10082 phymap
->phymap_acp
= activate_cb
;
10083 phymap
->phymap_dcp
= deactivate_cb
;
10084 phymap
->phymap_private
= phymap_priv
;
10085 mutex_init(&phymap
->phymap_lock
, NULL
, MUTEX_DRIVER
, NULL
);
10087 (void) snprintf(context
, sizeof (context
), "%s%d.phymap",
10088 ddi_driver_name(self
), ddi_get_instance(self
));
10089 SCSI_HBA_LOG((_LOGPHY
, self
, NULL
, "%s", context
));
10091 if (ddi_soft_state_init(&phymap
->phymap_phy2name
,
10092 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10094 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2phys
,
10095 sizeof (bitset_t
), SAS_PHY_NPHY
) != 0)
10098 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2ua
,
10099 SAS_PHY_UA_LEN
, SAS_PHY_NPHY
) != 0)
10101 if (ddi_soft_state_bystr_init(&phymap
->phymap_ua2name
,
10102 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10105 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
10106 settle_usec
, NULL
, NULL
, NULL
,
10107 phymap
, sas_phymap_config
, sas_phymap_unconfig
,
10108 &phymap
->phymap_dam
) != DAM_SUCCESS
)
10112 *handlep
= (sas_phymap_t
*)phymap
;
10113 return (DDI_SUCCESS
);
10115 fail
: sas_phymap_destroy((sas_phymap_t
*)phymap
);
10117 return (DDI_FAILURE
);
10121 sas_phymap_destroy(sas_phymap_t
*handle
)
10123 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10125 struct impl_sas_physet
*physet
, *nphyset
;
10129 context
= phymap
->phymap_dam
?
10130 damap_name(phymap
->phymap_dam
) : "unknown";
10131 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s", context
));
10133 if (phymap
->phymap_dam
)
10134 damap_destroy(phymap
->phymap_dam
);
10136 /* free the bitsets of allocated physets */
10137 for (physet
= phymap
->phymap_physets
; physet
; physet
= nphyset
) {
10138 nphyset
= physet
->physet_next
;
10139 phys
= physet
->physet_phys
;
10140 name
= physet
->physet_name
;
10145 ddi_soft_state_bystr_free(
10146 phymap
->phymap_name2phys
, name
);
10149 kmem_free(physet
, sizeof (*physet
));
10152 /* free the maps */
10153 if (phymap
->phymap_ua2name
)
10154 ddi_soft_state_bystr_fini(&phymap
->phymap_ua2name
);
10155 if (phymap
->phymap_name2ua
)
10156 ddi_soft_state_bystr_fini(&phymap
->phymap_name2ua
);
10158 if (phymap
->phymap_name2phys
)
10159 ddi_soft_state_bystr_fini(&phymap
->phymap_name2phys
);
10160 if (phymap
->phymap_phy2name
)
10161 ddi_soft_state_fini(&phymap
->phymap_phy2name
);
10163 mutex_destroy(&phymap
->phymap_lock
);
10164 kmem_free(phymap
, sizeof (*phymap
));
10169 sas_phymap_phy_add(sas_phymap_t
*handle
,
10170 int phy
, uint64_t local
, uint64_t remote
)
10172 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10173 char *context
= damap_name(phymap
->phymap_dam
);
10174 char port
[SAS_PHY_NAME_LEN
];
10176 int phy2name_allocated
= 0;
10178 struct impl_sas_physet
*physet
;
10181 /* Create the SAS port name from the local and remote addresses. */
10182 (void) snprintf(port
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10185 mutex_enter(&phymap
->phymap_lock
);
10186 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: add phy %d",
10187 context
, port
, phy
));
10189 /* Check for conflict in phy2name map */
10190 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10192 if (strcmp(name
, port
) != 0)
10193 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10194 "already in %s", context
, port
, phy
, name
));
10196 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10197 "duplicate add", context
, port
, phy
));
10198 mutex_exit(&phymap
->phymap_lock
);
10199 return (DDI_FAILURE
);
10202 /* allocate, get, and initialize phy index of phy2name map */
10203 if (ddi_soft_state_zalloc(
10204 phymap
->phymap_phy2name
, phy
) != DDI_SUCCESS
) {
10205 SCSI_HBA_LOG((_LOG_NF(WARN
),
10206 "%s: %s: failed phy2name alloc", context
, port
));
10209 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10210 if (name
== NULL
) {
10211 SCSI_HBA_LOG((_LOG_NF(WARN
),
10212 "%s: %s: no phy2name", context
, port
));
10215 phy2name_allocated
= 1;
10216 (void) strlcpy(name
, port
, SAS_PHY_NAME_LEN
); /* set name */
10218 /* Find/alloc, initialize name index of name2phys map */
10219 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10220 if (phys
== NULL
) {
10221 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2phys
,
10222 name
) != DDI_SUCCESS
) {
10223 SCSI_HBA_LOG((_LOG_NF(WARN
),
10224 "%s: %s: failed name2phys alloc", context
, name
));
10227 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10228 if (phys
== NULL
) {
10229 SCSI_HBA_LOG((_LOG_NF(WARN
),
10230 "%s: %s: no name2phys", context
, name
));
10234 /* Initialize bitset of phys. */
10236 bitset_resize(phys
, SAS_PHY_NPHY
);
10238 /* Keep a list of information for destroy. */
10239 physet
= kmem_zalloc(sizeof (*physet
), KM_SLEEP
);
10240 physet
->physet_name
= strdup(name
);
10241 physet
->physet_phys
= phys
;
10242 physet
->physet_next
= phymap
->phymap_physets
;
10243 phymap
->phymap_physets
= physet
;
10247 /* Reflect 'add' in phys bitset. */
10248 if (bitset_atomic_test_and_add(phys
, phy
) < 0) {
10249 /* It is an error if the phy was already recorded. */
10250 SCSI_HBA_LOG((_LOG_NF(WARN
),
10251 "%s: %s: phy bit %d already in port", context
, name
, phy
));
10256 * Check to see if we have a new phy_max for this map, and if so
10257 * scale phymap_reports_max to the new number of phys.
10259 if (phy
> phymap
->phymap_phy_max
) {
10260 phymap
->phymap_phy_max
= phy
+ 1;
10261 phymap
->phymap_reports_max
= phymap
->phymap_phy_max
*
10262 sas_phymap_phy_max_factor
;
10266 * If we have not reached phymap_reports_max, start/restart the
10267 * activate timer. Otherwise, if phymap->phymap_reports add/rem reports
10268 * ever exceeds phymap_reports_max due to noisy phys, then report the
10269 * noise and force stabilization by stopping reports into the damap.
10271 * The first config/unconfig callout out of the damap will reset
10272 * phymap->phymap_reports.
10275 if (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
) {
10276 if (damap_addr_add(phymap
->phymap_dam
, name
,
10277 NULL
, NULL
, NULL
) == DAM_SUCCESS
) {
10278 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10279 "%s: %s: damap_addr_add", context
, name
));
10281 SCSI_HBA_LOG((_LOG_NF(WARN
),
10282 "%s: %s: damap_addr_add failed", context
, name
));
10286 phymap
->phymap_phys_noisy
++;
10287 if (phymap
->phymap_phys_noisy
== 1)
10288 SCSI_HBA_LOG((_LOG_NF(WARN
),
10289 "%s: %s: noisy phys", context
, name
));
10291 mutex_exit(&phymap
->phymap_lock
);
10294 fail
: if (phy2name_allocated
)
10295 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
);
10296 mutex_exit(&phymap
->phymap_lock
);
10297 return (DDI_FAILURE
);
10301 sas_phymap_phy_rem(sas_phymap_t
*handle
, int phy
)
10303 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10304 char *context
= damap_name(phymap
->phymap_dam
);
10307 int rv
= DDI_FAILURE
;
10311 mutex_enter(&phymap
->phymap_lock
);
10312 phymap
->phymap_reports
++;
10314 /* Find and free phy index of phy2name map */
10315 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10316 if (name
== NULL
) {
10317 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: rem phy %d: never added",
10321 /* NOTE: always free phy index of phy2name map before return... */
10323 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: rem phy %d",
10324 context
, name
, phy
));
10326 /* Get bitset of phys currently associated with named port. */
10327 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10328 if (phys
== NULL
) {
10329 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: name2phys failed",
10334 /* Reflect 'rem' in phys bitset. */
10335 if (bitset_atomic_test_and_del(phys
, phy
) < 0) {
10336 /* It is an error if the phy wasn't one of the port's phys. */
10337 SCSI_HBA_LOG((_LOG_NF(WARN
),
10338 "%s: %s: phy bit %d not in port", context
, name
, phy
));
10342 /* If this was the last phy in the port, start the deactivate timer. */
10343 if (bitset_is_null(phys
) &&
10344 (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
)) {
10345 if (damap_addr_del(phymap
->phymap_dam
, name
) == DAM_SUCCESS
) {
10346 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10347 "%s: %s: damap_addr_del", context
, name
));
10349 SCSI_HBA_LOG((_LOG_NF(WARN
),
10350 "%s: %s: damap_addr_del failure", context
, name
));
10356 /* free phy index of phy2name map */
10358 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
); /* free */
10359 mutex_exit(&phymap
->phymap_lock
);
10364 sas_phymap_lookup_ua(sas_phymap_t
*handle
, uint64_t local
, uint64_t remote
)
10366 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10367 char *context
= damap_name(phymap
->phymap_dam
);
10368 char name
[SAS_PHY_NAME_LEN
];
10373 (void) snprintf(name
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10376 mutex_enter(&phymap
->phymap_lock
);
10377 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10378 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10379 "%s: %s: ua %s", context
, name
, ua
? ua
: "NULL"));
10380 mutex_exit(&phymap
->phymap_lock
);
10385 sas_phymap_lookup_uapriv(sas_phymap_t
*handle
, char *ua
)
10387 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10388 char *context
= damap_name(phymap
->phymap_dam
);
10391 void *ua_priv
= NULL
;
10395 mutex_enter(&phymap
->phymap_lock
);
10396 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10398 phyid
= damap_lookup(phymap
->phymap_dam
, name
);
10399 if (phyid
!= NODAM
) {
10400 ua_priv
= damap_id_priv_get(phymap
->phymap_dam
, phyid
);
10401 damap_id_rele(phymap
->phymap_dam
, phyid
);
10405 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10406 "%s: %s: ua %s ua_priv %p", context
, name
,
10407 ua
? ua
: "NULL", ua_priv
));
10408 mutex_exit(&phymap
->phymap_lock
);
10413 sas_phymap_uahasphys(sas_phymap_t
*handle
, char *ua
)
10415 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10420 mutex_enter(&phymap
->phymap_lock
);
10421 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10423 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10425 n
= bitset_is_null(phys
) ? 0 : 1;
10427 mutex_exit(&phymap
->phymap_lock
);
10431 sas_phymap_phys_t
*
10432 sas_phymap_ua2phys(sas_phymap_t
*handle
, char *ua
)
10434 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10437 bitset_t
*cphys
= NULL
;
10439 mutex_enter(&phymap
->phymap_lock
);
10440 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10444 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10448 /* dup the phys and return */
10449 cphys
= kmem_alloc(sizeof (*cphys
), KM_SLEEP
);
10450 bitset_init(cphys
);
10451 bitset_resize(cphys
, SAS_PHY_NPHY
);
10452 bitset_copy(phys
, cphys
);
10454 fail
: mutex_exit(&phymap
->phymap_lock
);
10455 return ((sas_phymap_phys_t
*)cphys
);
10459 sas_phymap_phys_next(sas_phymap_phys_t
*phys
)
10461 bitset_t
*cphys
= (bitset_t
*)phys
;
10464 phy
= bitset_find(cphys
);
10466 bitset_del(cphys
, phy
);
10471 sas_phymap_phys_free(sas_phymap_phys_t
*phys
)
10473 bitset_t
*cphys
= (bitset_t
*)phys
;
10476 bitset_fini(cphys
);
10477 kmem_free(cphys
, sizeof (*cphys
));
10482 sas_phymap_phy2ua(sas_phymap_t
*handle
, int phy
)
10484 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10489 mutex_enter(&phymap
->phymap_lock
);
10490 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10493 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10497 /* dup the ua and return */
10500 fail
: mutex_exit(&phymap
->phymap_lock
);
10505 sas_phymap_ua_free(char *ua
)