4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
25 * Copyright (c) 2016 by Delphix. All rights reserved.
31 * Generic SCSI Host Bus Adapter interface implementation
33 #include <sys/scsi/scsi.h>
34 #include <sys/scsi/generic/sas.h>
36 #include <sys/disp.h> /* for minclsyspri */
37 #include <sys/ddi_impldefs.h>
38 #include <sys/ndi_impldefs.h>
39 #include <sys/sunndi.h>
41 #include <sys/sunmdi.h>
42 #include <sys/mdi_impldefs.h>
43 #include <sys/callb.h>
45 #include <sys/damap.h>
47 #include <sys/sunldi.h>
48 #include <sys/fm/protocol.h>
50 extern struct scsi_pkt
*scsi_init_cache_pkt(struct scsi_address
*,
51 struct scsi_pkt
*, struct buf
*, int, int, int, int,
52 int (*)(caddr_t
), caddr_t
);
53 extern void scsi_free_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
54 extern void scsi_cache_dmafree(struct scsi_address
*, struct scsi_pkt
*);
55 extern void scsi_sync_cache_pkt(struct scsi_address
*, struct scsi_pkt
*);
56 extern int modrootloaded
;
59 * Round up all allocations so that we can guarantee
60 * long-long alignment. This is the same alignment
61 * provided by kmem_alloc().
63 #define ROUNDUP(x) (((x) + 0x07) & ~0x07)
65 /* Magic number to track correct allocations in wrappers */
66 #define PKT_WRAPPER_MAGIC 0xa110ced /* alloced correctly */
68 kmutex_t scsi_flag_nointr_mutex
;
69 kcondvar_t scsi_flag_nointr_cv
;
70 kmutex_t scsi_log_mutex
;
72 /* asynchronous probe barrier deletion data structures */
73 static kmutex_t scsi_hba_barrier_mutex
;
74 static kcondvar_t scsi_hba_barrier_cv
;
75 static struct scsi_hba_barrier
{
76 struct scsi_hba_barrier
*barrier_next
;
77 clock_t barrier_endtime
;
78 dev_info_t
*barrier_probe
;
79 } *scsi_hba_barrier_list
;
80 static int scsi_hba_devi_is_barrier(dev_info_t
*probe
);
81 static void scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
);
82 static void scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
);
83 static int scsi_hba_remove_node(dev_info_t
*child
);
84 static void scsi_hba_barrier_daemon(void *arg
);
86 /* LUN-change ASC/ASCQ processing data structures (stage1 and stage2) */
87 static kmutex_t scsi_lunchg1_mutex
;
88 static kcondvar_t scsi_lunchg1_cv
;
89 static struct scsi_pkt
*scsi_lunchg1_list
;
90 static void scsi_lunchg1_daemon(void *arg
);
91 static kmutex_t scsi_lunchg2_mutex
;
92 static kcondvar_t scsi_lunchg2_cv
;
93 static struct scsi_lunchg2
{
94 struct scsi_lunchg2
*lunchg2_next
;
97 static void scsi_lunchg2_daemon(void *arg
);
99 static int scsi_findchild(dev_info_t
*self
, char *name
, char *addr
,
100 int init
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
);
102 /* return value defines for scsi_findchild */
103 #define CHILD_TYPE_NONE 0
104 #define CHILD_TYPE_DEVINFO 1
105 #define CHILD_TYPE_PATHINFO 2
108 * Enumeration code path currently being followed. SE_BUSCONFIG results in
109 * DEVI_SID_NODEID, and SE_HP (hotplug) results in DEVI_SID_HP_NODEID.
111 * Since hotplug enumeration is based on information obtained from hardware
112 * (tgtmap/report_lun) the type/severity of enumeration error messages is
113 * sometimes based SE_HP (indirectly via ndi_dev_is_hotplug_node()). By
114 * convention, these messages are all produced by scsi_enumeration_failed().
116 typedef enum { SE_BUSCONFIG
= 0, SE_HP
= 1 } scsi_enum_t
;
118 /* compatible properties of driver to use during probe/enumeration operations */
119 static char *compatible_probe
= "scsa,probe";
120 static char *compatible_nodev
= "scsa,nodev";
121 static char *scsi_probe_ascii
[] = SCSIPROBE_ASCII
;
123 /* number of LUNs we attempt to get on the first SCMD_REPORT_LUNS command */
124 int scsi_lunrpt_default_max
= 256;
125 int scsi_lunrpt_timeout
= 3; /* seconds */
128 * Only enumerate one lun if reportluns fails on a SCSI_VERSION_3 device
129 * (tunable based on calling context).
131 int scsi_lunrpt_failed_do1lun
= (1 << SE_HP
);
133 /* 'scsi-binding-set' value for legacy enumerated 'spi' transports */
134 char *scsi_binding_set_spi
= "spi";
136 /* enable NDI_DEVI_DEBUG for bus_[un]config operations */
137 int scsi_hba_bus_config_debug
= 0;
139 /* DEBUG: enable NDI_DEVI_REMOVE for bus_unconfig of dynamic node */
140 int scsi_hba_bus_unconfig_remove
= 0;
142 /* number of probe serilization messages */
143 int scsi_hba_wait_msg
= 5;
146 * Establish the timeout used to cache (in the probe node) the fact that the
147 * device does not exist. This replaces the target specific probe cache.
149 int scsi_hba_barrier_timeout
= (60); /* seconds */
152 int scsi_hba_bus_config_failure_msg
= 0;
153 int scsi_hba_bus_config_failure_dbg
= 0;
154 int scsi_hba_bus_config_success_msg
= 0;
155 int scsi_hba_bus_config_success_dbg
= 0;
159 * Structure for scsi_hba_iportmap_* implementation/wrap.
161 typedef struct impl_scsi_iportmap
{
162 dev_info_t
*iportmap_hba_dip
;
163 damap_t
*iportmap_dam
;
164 int iportmap_create_window
;
165 uint64_t iportmap_create_time
; /* clock64_t */
166 int iportmap_create_csync_usec
;
167 int iportmap_settle_usec
;
168 int iportmap_sync_cnt
;
169 } impl_scsi_iportmap_t
;
172 * Structure for scsi_hba_tgtmap_* implementation/wrap.
174 * Every call to scsi_hba_tgtmap_set_begin will increment tgtmap_reports,
175 * and a call to scsi_hba_tgtmap_set_end will reset tgtmap_reports to zero.
176 * If, in scsi_hba_tgtmap_set_begin, we detect a tgtmap_reports value of
177 * scsi_hba_tgtmap_reports_max we produce a message to indicate that
178 * the caller is never completing an observation (i.e. we are not making
179 * any forward progress). If this message occurs, it indicates that the
180 * solaris hotplug ramifications at the target and lun level are no longer
183 * NOTE: LUNMAPSIZE OK for now, but should be dynamic in reportlun code.
185 typedef struct impl_scsi_tgtmap
{
186 scsi_hba_tran_t
*tgtmap_tran
;
187 int tgtmap_reports
; /* _begin, no _end */
189 scsi_tgt_activate_cb_t tgtmap_activate_cb
;
190 scsi_tgt_deactivate_cb_t tgtmap_deactivate_cb
;
191 void *tgtmap_mappriv
;
192 damap_t
*tgtmap_dam
[SCSI_TGT_NTYPES
];
193 int tgtmap_create_window
;
194 uint64_t tgtmap_create_time
; /* clock64_t */
195 int tgtmap_create_csync_usec
;
196 int tgtmap_settle_usec
;
198 } impl_scsi_tgtmap_t
;
199 #define LUNMAPSIZE 256 /* 256 LUNs/target */
201 /* Produce warning if number of begins without an end exceed this value */
202 int scsi_hba_tgtmap_reports_max
= 256;
204 static int scsi_tgtmap_sync(scsi_hba_tgtmap_t
*, int);
206 /* Default settle_usec damap_sync factor */
207 int scsi_hba_map_settle_f
= 10;
210 /* Prototype for static dev_ops devo_*() functions */
211 static int scsi_hba_info(
213 ddi_info_cmd_t infocmd
,
217 /* Prototypes for static bus_ops bus_*() functions */
218 static int scsi_hba_bus_ctl(
225 static int scsi_hba_map_fault(
236 static int scsi_hba_get_eventcookie(
240 ddi_eventcookie_t
*eventp
);
242 static int scsi_hba_add_eventcall(
245 ddi_eventcookie_t event
,
248 ddi_eventcookie_t event
,
252 ddi_callback_id_t
*cb_id
);
254 static int scsi_hba_remove_eventcall(
256 ddi_callback_id_t id
);
258 static int scsi_hba_post_event(
261 ddi_eventcookie_t event
,
264 static int scsi_hba_bus_config(
267 ddi_bus_config_op_t op
,
269 dev_info_t
**childp
);
271 static int scsi_hba_bus_unconfig(
274 ddi_bus_config_op_t op
,
277 static int scsi_hba_fm_init_child(
281 ddi_iblock_cookie_t
*ibc
);
283 static int scsi_hba_bus_power(
286 pm_bus_power_op_t op
,
290 /* bus_ops vector for SCSI HBA's. */
291 static struct bus_ops scsi_hba_busops
= {
293 nullbusmap
, /* bus_map */
294 NULL
, /* bus_get_intrspec */
295 NULL
, /* bus_add_intrspec */
296 NULL
, /* bus_remove_intrspec */
297 scsi_hba_map_fault
, /* bus_map_fault */
298 NULL
, /* bus_dma_map */
299 ddi_dma_allochdl
, /* bus_dma_allochdl */
300 ddi_dma_freehdl
, /* bus_dma_freehdl */
301 ddi_dma_bindhdl
, /* bus_dma_bindhdl */
302 ddi_dma_unbindhdl
, /* bus_unbindhdl */
303 ddi_dma_flush
, /* bus_dma_flush */
304 ddi_dma_win
, /* bus_dma_win */
305 ddi_dma_mctl
, /* bus_dma_ctl */
306 scsi_hba_bus_ctl
, /* bus_ctl */
307 ddi_bus_prop_op
, /* bus_prop_op */
308 scsi_hba_get_eventcookie
, /* bus_get_eventcookie */
309 scsi_hba_add_eventcall
, /* bus_add_eventcall */
310 scsi_hba_remove_eventcall
, /* bus_remove_eventcall */
311 scsi_hba_post_event
, /* bus_post_event */
312 NULL
, /* bus_intr_ctl */
313 scsi_hba_bus_config
, /* bus_config */
314 scsi_hba_bus_unconfig
, /* bus_unconfig */
315 scsi_hba_fm_init_child
, /* bus_fm_init */
316 NULL
, /* bus_fm_fini */
317 NULL
, /* bus_fm_access_enter */
318 NULL
, /* bus_fm_access_exit */
319 scsi_hba_bus_power
/* bus_power */
322 /* cb_ops for hotplug :devctl and :scsi support */
323 static struct cb_ops scsi_hba_cbops
= {
326 nodev
, /* strategy */
331 scsi_hba_ioctl
, /* ioctl */
336 ddi_prop_op
, /* prop_op */
338 D_NEW
|D_MP
|D_HOTPLUG
, /* cb_flag */
340 nodev
, /* int (*cb_aread)() */
341 nodev
/* int (*cb_awrite)() */
344 /* Prototypes for static scsi_hba.c/SCSA private lunmap interfaces */
345 static int scsi_lunmap_create(
347 impl_scsi_tgtmap_t
*tgtmap
,
349 static void scsi_lunmap_destroy(
351 impl_scsi_tgtmap_t
*tgtmap
,
353 static void scsi_lunmap_set_begin(
356 static int scsi_lunmap_set_add(
360 scsi_lun64_t lun_num
,
362 static void scsi_lunmap_set_end(
366 /* Prototypes for static misc. scsi_hba.c private bus_config interfaces */
367 static int scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
368 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
369 static int scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
370 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
);
371 static dev_info_t
*scsi_hba_bus_config_port(dev_info_t
*self
,
372 char *nameaddr
, scsi_enum_t se
);
375 static int scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
376 void *arg
, dev_info_t
**childp
);
381 * SCSI_HBA_LOG is used for all messages. A logging level is specified when
382 * generating a message. Some levels correspond directly to cmn_err levels,
383 * some are associated with increasing levels diagnostic/debug output (LOG1-4),
384 * and others are associated with specific levels of interface (LOGMAP).
385 * For _LOG() messages, a __func__ prefix will identify the function origin
386 * of the message. For _LOG_NF messages, there is no function prefix or
387 * self/child context. Filtering of messages is provided based on logging
388 * level, but messages with cmn_err logging level and messages generated
389 * generated with _LOG_NF() are never filtered.
391 * For debugging, more complete information can be displayed with each message
392 * (full device path and pointer values) by adjusting scsi_hba_log_info.
395 #define SCSI_HBA_LOGCONT CE_CONT
396 #define SCSI_HBA_LOGNOTE CE_NOTE
397 #define SCSI_HBA_LOGWARN CE_WARN
398 #define SCSI_HBA_LOGPANIC CE_PANIC
399 #define SCSI_HBA_LOGIGNORE CE_IGNORE
400 #define SCSI_HBA_LOG_CE_MASK 0x0000000F /* no filter for these levels */
401 #define SCSI_HBA_LOG1 0x00000010 /* DIAG1 level enable */
402 #define SCSI_HBA_LOG2 0x00000020 /* DIAG2 level enable */
403 #define SCSI_HBA_LOG3 0x00000040 /* DIAG3 level enable */
404 #define SCSI_HBA_LOG4 0x00000080 /* DIAG4 level enable */
405 #define SCSI_HBA_LOGMAPPHY 0x00000100 /* MAPPHY level enable */
406 #define SCSI_HBA_LOGMAPIPT 0x00000200 /* MAPIPT level enable */
407 #define SCSI_HBA_LOGMAPTGT 0x00000400 /* MAPTGT level enable */
408 #define SCSI_HBA_LOGMAPLUN 0x00000800 /* MAPLUN level enable */
409 #define SCSI_HBA_LOGMAPCFG 0x00001000 /* MAPCFG level enable */
410 #define SCSI_HBA_LOGMAPUNCFG 0x00002000 /* MAPUNCFG level enable */
411 #define SCSI_HBA_LOGTRACE 0x00010000 /* TRACE enable */
412 #if (CE_CONT | CE_NOTE | CE_WARN | CE_PANIC | CE_IGNORE) > SCSI_HBA_LOG_CE_MASK
413 Error
, problem with CE_ definitions
417 * Tunable log message augmentation and filters: filters do not apply to
418 * SCSI_HBA_LOG_CE_MASK level messages or LOG_NF() messages.
420 * An example set of /etc/system tunings to simplify debug a SCSA pHCI HBA
421 * driver called "pmcs", including "scsi_vhci" operation, by capturing
422 * log information in the system log might be:
424 * echo "set scsi:scsi_hba_log_filter_level=0x3ff0" >> /etc/system
425 * echo "set scsi:scsi_hba_log_filter_phci=\"pmcs\"" >> /etc/system
426 * echo "set scsi:scsi_hba_log_filter_vhci=\"scsi_vhci\"" >> /etc/system
428 * To capture information on just HBA-SCSAv3 *map operation, use
429 * echo "set scsi:scsi_hba_log_filter_level=0x3f10" >> /etc/system
431 * For debugging an HBA driver, you may also want to set:
433 * echo "set scsi:scsi_hba_log_align=1" >> /etc/system
434 * echo "set scsi:scsi_hba_log_mt_disable=0x6" >> /etc/system
435 * echo "set mtc_off=1" >> /etc/system
436 * echo "set mdi_mtc_off=1" >> /etc/system
437 * echo "set scsi:scsi_hba_log_fcif=0" >> /etc/system
439 int scsi_hba_log_filter_level
=
442 char *scsi_hba_log_filter_phci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
443 char *scsi_hba_log_filter_vhci
= "\0\0\0\0\0\0\0\0\0\0\0\0";
444 int scsi_hba_log_align
= 0; /* NOTE: will not cause truncation */
445 int scsi_hba_log_fcif
= '!'; /* "^!?" first char in format */
446 /* NOTE: iff level > SCSI_HBA_LOG1 */
447 /* '\0'0x00 -> console and system log */
448 /* '^' 0x5e -> console_only */
449 /* '!' 0x21 -> system log only */
450 /* '?' 0x2F -> See cmn_err(9F) */
451 int scsi_hba_log_info
= /* augmentation: extra info output */
452 (0 << 0) | /* 0x0001: process information */
453 (0 << 1) | /* 0x0002: full /devices path */
454 (0 << 2); /* 0x0004: devinfo pointer */
456 int scsi_hba_log_mt_disable
=
457 /* SCSI_ENUMERATION_MT_LUN_DISABLE | (ie 0x02) */
458 /* SCSI_ENUMERATION_MT_TARGET_DISABLE | (ie 0x04) */
461 /* static data for HBA logging subsystem */
462 static kmutex_t scsi_hba_log_mutex
;
463 static char scsi_hba_log_i
[512];
464 static char scsi_hba_log_buf
[512];
465 static char scsi_hba_fmt
[512];
467 /* Macros to use in scsi_hba.c source code below */
468 #define SCSI_HBA_LOG(x) scsi_hba_log x
469 #define _LOG(level) SCSI_HBA_LOG##level, __func__
470 #define _MAP(map) SCSI_HBA_LOGMAP##map, __func__
471 #define _LOG_NF(level) SCSI_HBA_LOG##level, NULL, NULL, NULL
472 #define _LOG_TRACE _LOG(TRACE)
473 #define _LOGLUN _MAP(LUN)
474 #define _LOGTGT _MAP(TGT)
475 #define _LOGIPT _MAP(IPT)
476 #define _LOGPHY _MAP(PHY)
477 #define _LOGCFG _MAP(CFG)
478 #define _LOGUNCFG _MAP(UNCFG)
482 scsi_hba_log(int level
, const char *func
, dev_info_t
*self
, dev_info_t
*child
,
483 const char *fmt
, ...)
492 /* derive self from child's parent */
493 if ((self
== NULL
) && child
)
494 self
= ddi_get_parent(child
);
496 /* no filtering of SCSI_HBA_LOG_CE_MASK or LOG_NF messages */
497 if (((level
& SCSI_HBA_LOG_CE_MASK
) != level
) && (func
!= NULL
)) {
498 /* scsi_hba_log_filter_level: filter on level as bitmask */
499 if ((level
& scsi_hba_log_filter_level
) == 0)
502 /* scsi_hba_log_filter_phci/vhci: on name of driver */
503 if (*scsi_hba_log_filter_phci
&&
505 (ddi_driver_name(self
) == NULL
) ||
506 strcmp(ddi_driver_name(self
), scsi_hba_log_filter_phci
))) {
507 /* does not match pHCI, check vHCI */
508 if (*scsi_hba_log_filter_vhci
&&
510 (ddi_driver_name(self
) == NULL
) ||
511 strcmp(ddi_driver_name(self
),
512 scsi_hba_log_filter_vhci
))) {
513 /* does not match vHCI */
519 /* passed filters, determine align */
520 align
= scsi_hba_log_align
;
522 /* shorten func for filtered output */
523 if (strncmp(func
, "scsi_hba_", 9) == 0)
525 if (strncmp(func
, "scsi_", 5) == 0)
528 /* don't align output that is never filtered */
532 /* determine the cmn_err form from the level */
533 clevel
= ((level
& SCSI_HBA_LOG_CE_MASK
) == level
) ? level
: CE_CONT
;
535 /* protect common buffers used to format output */
536 mutex_enter(&scsi_hba_log_mutex
);
538 /* skip special first characters, we add them back below */
540 if (*f
&& strchr("^!?", *f
))
543 (void) vsprintf(scsi_hba_log_buf
, f
, ap
);
546 /* augment message with 'information' */
547 info
= scsi_hba_log_i
;
549 if ((scsi_hba_log_info
& 0x0001) && curproc
&& PTOU(curproc
)->u_comm
) {
550 (void) sprintf(info
, "%s[%d]%p ",
551 PTOU(curproc
)->u_comm
, curproc
->p_pid
, (void *)curthread
);
552 info
+= strlen(info
);
555 if ((scsi_hba_log_info
& 0x0004) && (child
|| self
)) {
556 (void) sprintf(info
, "%p ",
557 (void *)(child
? child
: self
));
558 info
+= strlen(info
);
560 if (scsi_hba_log_info
& 0x0002) {
561 (void) ddi_pathname(child
? child
: self
, info
);
562 (void) strcat(info
, " ");
563 info
+= strlen(info
);
566 /* always provide 'default' information about self &child */
567 (void) sprintf(info
, "%s%d ", ddi_driver_name(self
),
568 ddi_get_instance(self
));
569 info
+= strlen(info
);
571 ua
= ddi_get_name_addr(child
);
572 (void) sprintf(info
, "%s@%s ",
573 ddi_node_name(child
), (ua
&& *ua
) ? ua
: "");
574 info
+= strlen(info
);
578 /* turn off alignment if truncation would occur */
579 if (align
&& ((strlen(func
) > 18) || (strlen(scsi_hba_log_i
) > 36)))
582 /* adjust for aligned output */
586 /* remove trailing blank with align output */
587 if ((info
!= scsi_hba_log_i
) && (*(info
-1) == '\b'))
591 /* special "first character in format" must be in format itself */
593 if (fmt
[0] && strchr("^!?", fmt
[0]))
595 else if (scsi_hba_log_fcif
&& (level
> SCSI_HBA_LOG1
))
596 *f
++ = (char)scsi_hba_log_fcif
; /* add global fcif */
598 (void) sprintf(f
, "%s", "%-18.18s: %36.36s: %s%s");
600 (void) sprintf(f
, "%s", func
? "%s: %s%s%s" : "%s%s%s");
603 cmn_err(clevel
, scsi_hba_fmt
, func
, scsi_hba_log_i
,
604 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
606 cmn_err(clevel
, scsi_hba_fmt
, scsi_hba_log_i
,
607 scsi_hba_log_buf
, clevel
== CE_CONT
? "\n" : "");
608 mutex_exit(&scsi_hba_log_mutex
);
611 int scsi_enumeration_failed_panic
= 0;
612 int scsi_enumeration_failed_hotplug
= 1;
615 scsi_enumeration_failed(dev_info_t
*child
, scsi_enum_t se
,
616 char *arg
, char *when
)
618 /* If 'se' is -1 the 'se' value comes from child. */
621 se
= ndi_dev_is_hotplug_node(child
) ? SE_HP
: SE_BUSCONFIG
;
624 if (scsi_enumeration_failed_panic
) {
625 /* set scsi_enumeration_failed_panic to debug */
626 SCSI_HBA_LOG((_LOG(PANIC
), NULL
, child
,
627 "%s%senumeration failed during %s",
628 arg
? arg
: "", arg
? " " : "", when
));
629 } else if (scsi_enumeration_failed_hotplug
&& (se
== SE_HP
)) {
630 /* set scsi_enumeration_failed_hotplug for console messages */
631 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
,
632 "%s%senumeration failed during %s",
633 arg
? arg
: "", arg
? " " : "", when
));
636 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
637 "%s%senumeration failed during %s",
638 arg
? arg
: "", arg
? " " : "", when
));
643 * scsi_hba version of [nm]di_devi_enter/[nm]di_devi_exit that detects if HBA
644 * is a PHCI, and chooses mdi/ndi locking implementation.
647 scsi_hba_devi_enter(dev_info_t
*self
, int *circp
)
650 mdi_devi_enter(self
, circp
);
652 ndi_devi_enter(self
, circp
);
656 scsi_hba_devi_tryenter(dev_info_t
*self
, int *circp
)
659 return (mdi_devi_tryenter(self
, circp
));
661 return (ndi_devi_tryenter(self
, circp
));
665 scsi_hba_devi_exit(dev_info_t
*self
, int circ
)
668 mdi_devi_exit(self
, circ
);
670 ndi_devi_exit(self
, circ
);
674 scsi_hba_devi_enter_phci(dev_info_t
*self
, int *circp
)
677 mdi_devi_enter_phci(self
, circp
);
681 scsi_hba_devi_exit_phci(dev_info_t
*self
, int circ
)
684 mdi_devi_exit_phci(self
, circ
);
688 scsi_hba_dev_is_sid(dev_info_t
*child
)
691 * Use ndi_dev_is_persistent_node instead of ddi_dev_is_sid to avoid
692 * any possible locking issues in mixed nexus devctl code (like usb).
694 return (ndi_dev_is_persistent_node(child
));
698 * Called from _init() when loading "scsi" module
701 scsi_initialize_hba_interface()
703 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
705 /* We need "scsiprobe" and "scsinodev" as an alias or a driver. */
706 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
) {
707 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
708 "driver alias, defaulting to 'nulldriver'",
711 /* If no "nulldriver" driver nothing will work... */
712 compatible_probe
= "nulldriver";
713 if (ddi_name_to_major(compatible_probe
) == DDI_MAJOR_T_NONE
)
714 SCSI_HBA_LOG((_LOG_NF(WARN
), "no probe '%s' driver, "
715 "system misconfigured", compatible_probe
));
717 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
) {
718 SCSI_HBA_LOG((_LOG_NF(WARN
), "failed to resolve '%s' "
719 "driver alias, defaulting to 'nulldriver'",
722 /* If no "nulldriver" driver nothing will work... */
723 compatible_nodev
= "nulldriver";
724 if (ddi_name_to_major(compatible_nodev
) == DDI_MAJOR_T_NONE
)
725 SCSI_HBA_LOG((_LOG_NF(WARN
), "no nodev '%s' driver, "
726 "system misconfigured", compatible_nodev
));
730 * Verify our special node name "probe" will not be used in other ways.
731 * Don't expect things to work if they are.
733 if (ddi_major_to_name(ddi_name_to_major("probe")))
734 SCSI_HBA_LOG((_LOG_NF(WARN
),
735 "driver already using special node name 'probe'"));
737 mutex_init(&scsi_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
738 mutex_init(&scsi_flag_nointr_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
739 cv_init(&scsi_flag_nointr_cv
, NULL
, CV_DRIVER
, NULL
);
740 mutex_init(&scsi_hba_log_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
742 /* initialize the asynchronous barrier deletion daemon */
743 mutex_init(&scsi_hba_barrier_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
744 cv_init(&scsi_hba_barrier_cv
, NULL
, CV_DRIVER
, NULL
);
745 (void) thread_create(NULL
, 0,
746 (void (*)())scsi_hba_barrier_daemon
, NULL
,
747 0, &p0
, TS_RUN
, minclsyspri
);
749 /* initialize lun change ASC/ASCQ processing daemon (stage1 & stage2) */
750 mutex_init(&scsi_lunchg1_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
751 cv_init(&scsi_lunchg1_cv
, NULL
, CV_DRIVER
, NULL
);
752 (void) thread_create(NULL
, 0,
753 (void (*)())scsi_lunchg1_daemon
, NULL
,
754 0, &p0
, TS_RUN
, minclsyspri
);
755 mutex_init(&scsi_lunchg2_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
756 cv_init(&scsi_lunchg2_cv
, NULL
, CV_DRIVER
, NULL
);
757 (void) thread_create(NULL
, 0,
758 (void (*)())scsi_lunchg2_daemon
, NULL
,
759 0, &p0
, TS_RUN
, minclsyspri
);
763 scsi_hba_pkt_constructor(void *buf
, void *arg
, int kmflag
)
765 struct scsi_pkt_cache_wrapper
*pktw
;
766 struct scsi_pkt
*pkt
;
767 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
772 * allocate a chunk of memory for the following:
776 * pkt_cdbp, if needed
777 * (pkt_private always null)
778 * pkt_scbp, if needed
780 pkt_len
= tran
->tran_hba_len
+ sizeof (struct scsi_pkt_cache_wrapper
);
781 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
782 pkt_len
+= DEFAULT_CDBLEN
;
783 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
784 pkt_len
+= DEFAULT_SCBLEN
;
789 ptr
+= sizeof (struct scsi_pkt_cache_wrapper
);
790 pkt
= &(pktw
->pcw_pkt
);
791 pkt
->pkt_ha_private
= (opaque_t
)ptr
;
793 pktw
->pcw_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
795 * keep track of the granularity at the time this handle was
798 pktw
->pcw_granular
= tran
->tran_dma_attr
.dma_attr_granular
;
800 if (ddi_dma_alloc_handle(tran
->tran_hba_dip
, &tran
->tran_dma_attr
,
801 kmflag
== KM_SLEEP
? SLEEP_FUNC
: NULL_FUNC
, NULL
,
802 &pkt
->pkt_handle
) != DDI_SUCCESS
) {
806 ptr
+= tran
->tran_hba_len
;
807 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) {
808 pkt
->pkt_cdbp
= (opaque_t
)ptr
;
809 ptr
+= DEFAULT_CDBLEN
;
811 pkt
->pkt_private
= NULL
;
812 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
813 pkt
->pkt_scbp
= (opaque_t
)ptr
;
814 if (tran
->tran_pkt_constructor
)
815 return ((*tran
->tran_pkt_constructor
)(pkt
, arg
, kmflag
));
820 #define P_TO_TRAN(pkt) ((pkt)->pkt_address.a_hba_tran)
823 scsi_hba_pkt_destructor(void *buf
, void *arg
)
825 struct scsi_pkt_cache_wrapper
*pktw
= buf
;
826 struct scsi_pkt
*pkt
= &(pktw
->pcw_pkt
);
827 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
829 ASSERT(pktw
->pcw_magic
== PKT_WRAPPER_MAGIC
);
830 ASSERT((pktw
->pcw_flags
& PCW_BOUND
) == 0);
831 if (tran
->tran_pkt_destructor
)
832 (*tran
->tran_pkt_destructor
)(pkt
, arg
);
834 /* make sure nobody messed with our pointers */
835 ASSERT(pkt
->pkt_ha_private
== (opaque_t
)((char *)pkt
+
836 sizeof (struct scsi_pkt_cache_wrapper
)));
837 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
) == 0) ||
838 (pkt
->pkt_scbp
== (opaque_t
)((char *)pkt
+
840 (((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ?
841 0 : DEFAULT_CDBLEN
) +
842 DEFAULT_PRIVLEN
+ sizeof (struct scsi_pkt_cache_wrapper
))));
843 ASSERT(((tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
) == 0) ||
844 (pkt
->pkt_cdbp
== (opaque_t
)((char *)pkt
+
846 sizeof (struct scsi_pkt_cache_wrapper
))));
847 ASSERT(pkt
->pkt_handle
);
848 ddi_dma_free_handle(&pkt
->pkt_handle
);
849 pkt
->pkt_handle
= NULL
;
850 pkt
->pkt_numcookies
= 0;
851 pktw
->pcw_total_xfer
= 0;
852 pktw
->pcw_totalwin
= 0;
853 pktw
->pcw_curwin
= 0;
857 * Called by an HBA from _init() to plumb in common SCSA bus_ops and
858 * cb_ops for the HBA's :devctl and :scsi minor nodes.
861 scsi_hba_init(struct modlinkage
*modlp
)
863 struct dev_ops
*hba_dev_ops
;
865 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
868 * Get a pointer to the dev_ops structure of the HBA and plumb our
869 * bus_ops vector into the HBA's dev_ops structure.
871 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
872 ASSERT(hba_dev_ops
->devo_bus_ops
== NULL
);
873 hba_dev_ops
->devo_bus_ops
= &scsi_hba_busops
;
876 * Plumb our cb_ops vector into the HBA's dev_ops structure to
877 * provide getinfo and hotplugging ioctl support if the HBA driver
878 * does not already provide this support.
880 if (hba_dev_ops
->devo_cb_ops
== NULL
) {
881 hba_dev_ops
->devo_cb_ops
= &scsi_hba_cbops
;
883 if (hba_dev_ops
->devo_cb_ops
->cb_open
== scsi_hba_open
) {
884 ASSERT(hba_dev_ops
->devo_cb_ops
->cb_close
== scsi_hba_close
);
885 hba_dev_ops
->devo_getinfo
= scsi_hba_info
;
891 * Called by an HBA attach(9E) to allocate a scsi_hba_tran(9S) structure. An
892 * HBA driver will then initialize the structure and then call
893 * scsi_hba_attach_setup(9F).
901 scsi_hba_tran_t
*tran
;
903 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
905 /* allocate SCSA flavors for self */
906 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
908 tran
= kmem_zalloc(sizeof (scsi_hba_tran_t
),
909 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
912 tran
->tran_interconnect_type
= INTERCONNECT_PARALLEL
;
915 * HBA driver called scsi_hba_tran_alloc(), so tran structure
916 * is proper size and unused/newer fields are zero.
918 * NOTE: We use SCSA_HBA_SCSA_TA as an obtuse form of
919 * versioning to detect old HBA drivers that do not use
920 * scsi_hba_tran_alloc, and would present garbage data
921 * (instead of valid/zero data) for newer tran fields.
923 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
;
930 * Called by an HBA to free a scsi_hba_tran structure
934 scsi_hba_tran_t
*tran
)
936 SCSI_HBA_LOG((_LOG_TRACE
, tran
->tran_hba_dip
, NULL
, __func__
));
938 kmem_free(tran
, sizeof (scsi_hba_tran_t
));
943 scsi_hba_tran_t
*tran
,
948 int ret
= DDI_FAILURE
;
950 tran_ext
= kmem_zalloc(length
,
951 (flags
& SCSI_HBA_CANSLEEP
) ? KM_SLEEP
: KM_NOSLEEP
);
952 if (tran_ext
!= NULL
) {
953 tran
->tran_extension
= tran_ext
;
961 scsi_hba_tran_t
*tran
,
964 if (tran
->tran_extension
!= NULL
) {
965 kmem_free(tran
->tran_extension
, length
);
966 tran
->tran_extension
= NULL
;
971 * Common nexus teardown code: used by both scsi_hba_detach() on SCSA HBA node
972 * and iport_postdetach_tran_scsi_device() on a SCSA HBA iport node (and for
973 * failure cleanup). Undo scsa_nexus_setup in reverse order.
975 * NOTE: Since we are in the Solaris IO framework, we can depend on
976 * undocumented cleanup operations performed by other parts of the framework:
977 * like detach_node() calling ddi_prop_remove_all() and
978 * ddi_remove_minor_node(,NULL).
981 scsa_nexus_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
984 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_FM
) {
986 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_FM
;
991 * Common nexus setup code: used by both scsi_hba_attach_setup() on SCSA HBA
992 * node and iport_preattach_tran_scsi_device() on a SCSA HBA iport node.
994 * This code makes no assumptions about tran use by scsi_device children.
997 scsa_nexus_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1003 * NOTE: SCSA maintains an 'fm-capable' domain, in tran_fm_capable,
1004 * that is not dependent (limited by) the capabilities of its parents.
1005 * For example a devinfo node in a branch that is not
1006 * DDI_FM_EREPORT_CAPABLE may report as capable, via tran_fm_capable,
1007 * to its scsi_device children.
1009 * Get 'fm-capable' property from driver.conf, if present. If not
1010 * present, default to the scsi_fm_capable global (which has
1011 * DDI_FM_EREPORT_CAPABLE set by default).
1013 if (tran
->tran_fm_capable
== DDI_FM_NOT_CAPABLE
)
1014 tran
->tran_fm_capable
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
1015 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1016 "fm-capable", scsi_fm_capable
);
1019 * If an HBA is *not* doing its own fma support by calling
1020 * ddi_fm_init() prior to scsi_hba_attach_setup(), we provide a minimal
1021 * common SCSA implementation so that scsi_device children can generate
1022 * ereports via scsi_fm_ereport_post(). We use ddi_fm_capable() to
1023 * detect an HBA calling ddi_fm_init() prior to scsi_hba_attach_setup().
1025 if (tran
->tran_fm_capable
&&
1026 (ddi_fm_capable(self
) == DDI_FM_NOT_CAPABLE
)) {
1028 * We are capable of something, pass our capabilities up the
1029 * tree, but use a local variable so our parent can't limit
1030 * our capabilities (we don't want our parent to clear
1031 * DDI_FM_EREPORT_CAPABLE).
1033 * NOTE: iblock cookies are not important because scsi HBAs
1034 * always interrupt below LOCK_LEVEL.
1036 capable
= tran
->tran_fm_capable
;
1037 ddi_fm_init(self
, &capable
, NULL
);
1040 * Set SCSI_HBA_SCSA_FM bit to mark us as using the common
1041 * minimal SCSA fm implementation - we called ddi_fm_init(),
1042 * so we are responsible for calling ddi_fm_fini() in
1043 * scsi_hba_detach().
1045 * NOTE: if ddi_fm_init fails to establish handle, SKIP cleanup.
1047 if (DEVI(self
)->devi_fmhdl
)
1048 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_FM
;
1051 /* If SCSA responsible for for minor nodes, create :devctl minor. */
1052 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1053 scsi_hba_open
) ? 1 : 0;
1054 if (scsa_minor
&& ((ddi_create_minor_node(self
, "devctl", S_IFCHR
,
1055 INST2DEVCTL(ddi_get_instance(self
)), DDI_NT_SCSI_NEXUS
, 0) !=
1057 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1058 "can't create :devctl minor node"));
1062 return (DDI_SUCCESS
);
1064 fail
: scsa_nexus_teardown(self
, tran
);
1065 return (DDI_FAILURE
);
1069 * Common tran teardown code: used by iport_postdetach_tran_scsi_device() on a
1070 * SCSA HBA iport node and (possibly) by scsi_hba_detach() on SCSA HBA node
1071 * (and for failure cleanup). Undo scsa_tran_setup in reverse order.
1073 * NOTE: Since we are in the Solaris IO framework, we can depend on
1074 * undocumented cleanup operations performed by other parts of the framework:
1075 * like detach_node() calling ddi_prop_remove_all() and
1076 * ddi_remove_minor_node(,NULL).
1079 scsa_tran_teardown(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1081 tran
->tran_iport_dip
= NULL
;
1083 /* Teardown pHCI registration */
1084 if (tran
->tran_hba_flags
& SCSI_HBA_SCSA_PHCI
) {
1085 (void) mdi_phci_unregister(self
, 0);
1086 tran
->tran_hba_flags
&= ~SCSI_HBA_SCSA_PHCI
;
1091 * Common tran setup code: used by iport_preattach_tran_scsi_device() on a
1092 * SCSA HBA iport node and (possibly) by scsi_hba_attach_setup() on SCSA HBA
1096 scsa_tran_setup(dev_info_t
*self
, scsi_hba_tran_t
*tran
)
1100 char *scsi_binding_set
;
1101 static const char *interconnect
[] = INTERCONNECT_TYPE_ASCII
;
1103 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1105 /* If SCSA responsible for for minor nodes, create ":scsi" */
1106 scsa_minor
= (ddi_get_driver(self
)->devo_cb_ops
->cb_open
==
1107 scsi_hba_open
) ? 1 : 0;
1108 if (scsa_minor
&& (ddi_create_minor_node(self
, "scsi", S_IFCHR
,
1109 INST2SCSI(ddi_get_instance(self
)),
1110 DDI_NT_SCSI_ATTACHMENT_POINT
, 0) != DDI_SUCCESS
)) {
1111 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1112 "can't create :scsi minor node"));
1117 * If the property does not already exist on self then see if we can
1118 * pull it from further up the tree and define it on self. If the
1119 * property does not exist above (including options.conf) then use the
1120 * default value specified (global variable). We pull things down from
1121 * above for faster "DDI_PROP_NOTPROM | DDI_PROP_DONTPASS" runtime
1124 * Future: Should we avoid creating properties when value == global?
1126 #define CONFIG_INT_PROP(s, p, dv) { \
1127 if ((ddi_prop_exists(DDI_DEV_T_ANY, s, \
1128 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, p) == 0) && \
1129 (ndi_prop_update_int(DDI_DEV_T_NONE, s, p, \
1130 ddi_prop_get_int(DDI_DEV_T_ANY, ddi_get_parent(s), \
1131 DDI_PROP_NOTPROM, p, dv)) != DDI_PROP_SUCCESS)) \
1132 SCSI_HBA_LOG((_LOG(WARN), NULL, s, \
1133 "can't create property '%s'", p)); \
1136 /* Decorate with scsi configuration properties */
1137 CONFIG_INT_PROP(self
, "scsi-enumeration", scsi_enumeration
);
1138 CONFIG_INT_PROP(self
, "scsi-options", scsi_options
);
1139 CONFIG_INT_PROP(self
, "scsi-reset-delay", scsi_reset_delay
);
1140 CONFIG_INT_PROP(self
, "scsi-watchdog-tick", scsi_watchdog_tick
);
1141 CONFIG_INT_PROP(self
, "scsi-selection-timeout", scsi_selection_timeout
);
1142 CONFIG_INT_PROP(self
, "scsi-tag-age-limit", scsi_tag_age_limit
);
1145 * Pull down the scsi-initiator-id from further up the tree, or as
1146 * defined by OBP. Place on node for faster access. NOTE: there is
1147 * some confusion about what the name of the property should be.
1149 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0, "initiator-id", -1);
1151 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
, 0,
1152 "scsi-initiator-id", -1);
1154 CONFIG_INT_PROP(self
, "scsi-initiator-id", id
);
1157 * If we are responsible for tran allocation, establish
1158 * 'initiator-interconnect-type'.
1160 if ((tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
) &&
1161 (tran
->tran_interconnect_type
> 0) &&
1162 (tran
->tran_interconnect_type
< INTERCONNECT_MAX
)) {
1163 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1164 "initiator-interconnect-type",
1165 (char *)interconnect
[tran
->tran_interconnect_type
])
1166 != DDI_PROP_SUCCESS
) {
1167 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1168 "failed to establish "
1169 "'initiator-interconnect-type'"));
1175 * The 'scsi-binding-set' property can be defined in driver.conf
1176 * files of legacy drivers on an as-needed basis. If 'scsi-binding-set'
1177 * is not driver.conf defined, and the HBA is not implementing its own
1178 * private bus_config, we define scsi-binding-set to the default
1179 * 'spi' legacy value.
1181 * NOTE: This default 'spi' value will be deleted if an HBA driver
1182 * ends up using the scsi_hba_tgtmap_create() enumeration services.
1184 * NOTE: If we were ever to decide to derive 'scsi-binding-set' from
1185 * the IEEE-1275 'device_type' property then this is where that code
1186 * should go - there is not enough consistency in 'device_type' to do
1187 * this correctly at this point in time.
1189 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
1190 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
1191 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
1192 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1193 "external 'scsi-binding-set' \"%s\"", scsi_binding_set
));
1194 ddi_prop_free(scsi_binding_set
);
1195 } else if (scsi_binding_set_spi
&&
1196 ((tran
->tran_bus_config
== NULL
) ||
1197 (tran
->tran_bus_config
== scsi_hba_bus_config_spi
))) {
1198 if (ndi_prop_update_string(DDI_DEV_T_NONE
, self
,
1199 "scsi-binding-set", scsi_binding_set_spi
) !=
1201 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1202 "failed to establish 'scsi_binding_set' default"));
1205 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1206 "default 'scsi-binding-set' \"%s\"", scsi_binding_set_spi
));
1208 SCSI_HBA_LOG((_LOG(2), NULL
, self
,
1209 "no 'scsi-binding-set'"));
1212 * If SCSI_HBA_TRAN_PHCI is set, take care of pHCI registration of the
1215 if ((tran
->tran_hba_flags
& SCSI_HBA_TRAN_PHCI
) &&
1216 (mdi_phci_register(MDI_HCI_CLASS_SCSI
, self
, 0) == MDI_SUCCESS
))
1217 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_PHCI
;
1219 /* NOTE: tran_hba_dip is for DMA operation at the HBA node level */
1220 tran
->tran_iport_dip
= self
; /* for iport association */
1221 return (DDI_SUCCESS
);
1223 fail
: scsa_tran_teardown(self
, tran
);
1224 return (DDI_FAILURE
);
1228 * Called by a SCSA HBA driver to attach an instance of the driver to
1229 * SCSA HBA node enumerated by PCI.
1232 scsi_hba_attach_setup(
1234 ddi_dma_attr_t
*hba_dma_attr
,
1235 scsi_hba_tran_t
*tran
,
1239 char cache_name
[96];
1241 SCSI_HBA_LOG((_LOG_TRACE
, self
, NULL
, __func__
));
1244 * Verify that we are a driver so other code does not need to
1245 * check for NULL ddi_get_driver() result.
1247 if (ddi_get_driver(self
) == NULL
)
1248 return (DDI_FAILURE
);
1251 * Verify that we are called on a SCSA HBA node (function enumerated
1252 * by PCI), not on an iport node.
1254 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1255 if (scsi_hba_iport_unit_address(self
))
1256 return (DDI_FAILURE
); /* self can't be an iport */
1258 /* Caller must provide the tran. */
1261 return (DDI_FAILURE
);
1264 * Verify correct scsi_hba_tran_t form:
1266 * o Both or none of tran_get_name/tran_get_addr.
1267 * NOTE: Older SCSA HBA drivers for SCSI transports with addressing
1268 * that did not fit the SPI "struct scsi_address" model were required
1269 * to implement tran_get_name and tran_get_addr. This is no longer
1270 * true - modern transport drivers should now use common SCSA
1271 * enumeration services. The SCSA enumeration code will represent
1272 * the unit-address using well-known address properties
1273 * (SCSI_ADDR_PROP_TARGET_PORT, SCSI_ADDR_PROP_LUN64) during
1274 * devinfo/pathinfo node creation. The HBA driver can obtain values
1275 * using scsi_device_prop_lookup_*() from its tran_tgt_init(9E).
1278 if ((tran
->tran_get_name
== NULL
) ^ (tran
->tran_get_bus_addr
== NULL
)) {
1279 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
1280 "should support both or neither: "
1281 "tran_get_name, tran_get_bus_addr"));
1282 return (DDI_FAILURE
);
1286 * Establish the devinfo context of this tran structure, preserving
1287 * knowledge of how the tran was allocated.
1289 tran
->tran_hba_dip
= self
; /* for DMA */
1290 tran
->tran_hba_flags
= (flags
& ~SCSI_HBA_SCSA_TA
) |
1291 (tran
->tran_hba_flags
& SCSI_HBA_SCSA_TA
);
1293 /* Establish flavor of transport (and ddi_get_driver_private()) */
1294 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
1297 * Note: We only need dma_attr_minxfer and dma_attr_burstsizes
1298 * from the DMA attributes. scsi_hba_attach(9f) only guarantees
1299 * that these two fields are initialized properly. If this
1300 * changes, be sure to revisit the implementation of
1301 * scsi_hba_attach(9F).
1303 (void) memcpy(&tran
->tran_dma_attr
, hba_dma_attr
,
1304 sizeof (ddi_dma_attr_t
));
1306 /* Create tran_setup_pkt(9E) kmem_cache. */
1307 if (tran
->tran_setup_pkt
) {
1308 ASSERT(tran
->tran_init_pkt
== NULL
);
1309 ASSERT(tran
->tran_destroy_pkt
== NULL
);
1310 if (tran
->tran_init_pkt
|| tran
->tran_destroy_pkt
)
1313 tran
->tran_init_pkt
= scsi_init_cache_pkt
;
1314 tran
->tran_destroy_pkt
= scsi_free_cache_pkt
;
1315 tran
->tran_sync_pkt
= scsi_sync_cache_pkt
;
1316 tran
->tran_dmafree
= scsi_cache_dmafree
;
1318 len
= sizeof (struct scsi_pkt_cache_wrapper
);
1319 len
+= ROUNDUP(tran
->tran_hba_len
);
1320 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CDB
)
1321 len
+= ROUNDUP(DEFAULT_CDBLEN
);
1322 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_SCB
)
1323 len
+= ROUNDUP(DEFAULT_SCBLEN
);
1325 (void) snprintf(cache_name
, sizeof (cache_name
),
1326 "pkt_cache_%s_%d", ddi_driver_name(self
),
1327 ddi_get_instance(self
));
1329 tran
->tran_pkt_cache_ptr
= kmem_cache_create(
1330 cache_name
, len
, 8, scsi_hba_pkt_constructor
,
1331 scsi_hba_pkt_destructor
, NULL
, tran
, NULL
, 0);
1334 /* Perform node setup independent of initiator role */
1335 if (scsa_nexus_setup(self
, tran
) != DDI_SUCCESS
)
1339 * The SCSI_HBA_HBA flag is passed to scsi_hba_attach_setup when the
1340 * HBA driver knows that *all* children of the SCSA HBA node will be
1341 * 'iports'. If the SCSA HBA node can have iport children and also
1342 * function as an initiator for xxx_device children then it should
1343 * not specify SCSI_HBA_HBA in its scsi_hba_attach_setup call. An
1344 * HBA driver that does not manage iports should not set SCSA_HBA_HBA.
1346 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
1348 * Set the 'ddi-config-driver-node' property on the nexus
1349 * node that notify attach_driver_nodes() to configure all
1350 * immediate children so that nodes which bind to the
1351 * same driver as parent are able to be added into per-driver
1354 if (ndi_prop_create_boolean(DDI_DEV_T_NONE
,
1355 self
, "ddi-config-driver-node") != DDI_PROP_SUCCESS
)
1358 if (scsa_tran_setup(self
, tran
) != DDI_SUCCESS
)
1362 return (DDI_SUCCESS
);
1364 fail
: (void) scsi_hba_detach(self
);
1365 return (DDI_FAILURE
);
1369 * Called by an HBA to detach an instance of the driver. This may be called
1370 * for SCSA HBA nodes and for SCSA iport nodes.
1373 scsi_hba_detach(dev_info_t
*self
)
1375 scsi_hba_tran_t
*tran
;
1377 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1378 if (scsi_hba_iport_unit_address(self
))
1379 return (DDI_FAILURE
); /* self can't be an iport */
1381 /* Check all error return conditions upfront */
1382 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1385 return (DDI_FAILURE
);
1387 ASSERT(tran
->tran_open_flag
== 0);
1388 if (tran
->tran_open_flag
)
1389 return (DDI_FAILURE
);
1391 if (!(tran
->tran_hba_flags
& SCSI_HBA_HBA
))
1392 scsa_tran_teardown(self
, tran
);
1393 scsa_nexus_teardown(self
, tran
);
1395 /* Teardown tran_setup_pkt(9E) kmem_cache. */
1396 if (tran
->tran_pkt_cache_ptr
) {
1397 kmem_cache_destroy(tran
->tran_pkt_cache_ptr
);
1398 tran
->tran_pkt_cache_ptr
= NULL
;
1401 (void) memset(&tran
->tran_dma_attr
, 0, sizeof (ddi_dma_attr_t
));
1403 /* Teardown flavor of transport (and ddi_get_driver_private()) */
1404 ndi_flavorv_set(self
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
1406 tran
->tran_hba_dip
= NULL
;
1408 return (DDI_SUCCESS
);
1413 * Called by an HBA from _fini()
1416 scsi_hba_fini(struct modlinkage
*modlp
)
1418 struct dev_ops
*hba_dev_ops
;
1420 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, NULL
, __func__
));
1422 /* Get the devops structure of this module and clear bus_ops vector. */
1423 hba_dev_ops
= ((struct modldrv
*)(modlp
->ml_linkage
[0]))->drv_dev_ops
;
1425 if (hba_dev_ops
->devo_cb_ops
== &scsi_hba_cbops
)
1426 hba_dev_ops
->devo_cb_ops
= NULL
;
1428 if (hba_dev_ops
->devo_getinfo
== scsi_hba_info
)
1429 hba_dev_ops
->devo_getinfo
= NULL
;
1431 hba_dev_ops
->devo_bus_ops
= (struct bus_ops
*)NULL
;
1435 * SAS specific functions
1438 smp_hba_tran_alloc(dev_info_t
*self
)
1440 /* allocate SCSA flavors for self */
1441 ndi_flavorv_alloc(self
, SCSA_NFLAVORS
);
1442 return (kmem_zalloc(sizeof (smp_hba_tran_t
), KM_SLEEP
));
1446 smp_hba_tran_free(smp_hba_tran_t
*tran
)
1448 kmem_free(tran
, sizeof (smp_hba_tran_t
));
1452 smp_hba_attach_setup(
1454 smp_hba_tran_t
*tran
)
1456 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1457 if (scsi_hba_iport_unit_address(self
))
1458 return (DDI_FAILURE
); /* self can't be an iport */
1461 * The owner of the this devinfo_t was responsible
1462 * for informing the framework already about
1463 * additional flavors.
1465 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, tran
);
1466 return (DDI_SUCCESS
);
1470 smp_hba_detach(dev_info_t
*self
)
1472 ASSERT(scsi_hba_iport_unit_address(self
) == NULL
);
1473 if (scsi_hba_iport_unit_address(self
))
1474 return (DDI_FAILURE
); /* self can't be an iport */
1476 ndi_flavorv_set(self
, SCSA_FLAVOR_SMP
, NULL
);
1477 return (DDI_SUCCESS
);
1481 * SMP child flavored functions
1484 smp_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1489 /* limit ndi_devi_findchild_by_callback to expected flavor */
1490 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1491 return (DDI_FAILURE
);
1493 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1494 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1495 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1496 (void) snprintf(addr
, maxlen
, "%s", tport
);
1497 ddi_prop_free(tport
);
1498 return (DDI_SUCCESS
);
1502 * NOTE: the following code should be deleted when mpt is changed to
1503 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1505 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1506 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1507 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1508 (void) snprintf(addr
, maxlen
, "w%s", wwn
);
1510 return (DDI_SUCCESS
);
1512 return (DDI_FAILURE
);
1516 smp_busctl_reportdev(dev_info_t
*child
)
1518 dev_info_t
*self
= ddi_get_parent(child
);
1522 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1523 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1524 SCSI_ADDR_PROP_TARGET_PORT
, &tport
) == DDI_SUCCESS
) {
1525 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: target-port %s",
1526 ddi_driver_name(child
), ddi_get_instance(child
),
1527 ddi_driver_name(self
), ddi_get_instance(self
), tport
));
1528 ddi_prop_free(tport
);
1529 return (DDI_SUCCESS
);
1533 * NOTE: the following code should be deleted when mpt is changed to
1534 * use SCSI_ADDR_PROP_TARGET_PORT instead of SMP_WWN.
1536 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
1537 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1538 SMP_WWN
, &wwn
) == DDI_SUCCESS
) {
1539 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: wwn %s",
1540 ddi_driver_name(child
), ddi_get_instance(child
),
1541 ddi_driver_name(self
), ddi_get_instance(self
), wwn
));
1543 return (DDI_SUCCESS
);
1545 return (DDI_FAILURE
);
1549 smp_busctl_initchild(dev_info_t
*child
)
1551 dev_info_t
*self
= ddi_get_parent(child
);
1552 smp_hba_tran_t
*tran
;
1554 char addr
[SCSI_MAXNAMELEN
];
1555 struct smp_device
*smp_sd
;
1558 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1561 return (DDI_FAILURE
);
1563 if (smp_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
1564 return (DDI_NOT_WELL_FORMED
);
1565 if (scsi_wwnstr_to_wwn(addr
, &wwn
))
1566 return (DDI_NOT_WELL_FORMED
);
1568 /* Prevent duplicate nodes. */
1569 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
1572 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SMP
);
1573 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SMP
) {
1574 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1575 "init failed: %s@%s: not SMP flavored",
1576 ddi_node_name(child
), addr
));
1577 return (DDI_FAILURE
);
1580 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1581 "init failed: %s@%s: detected duplicate %p",
1582 ddi_node_name(child
), addr
, (void *)dup
));
1583 return (DDI_FAILURE
);
1588 /* set the node @addr string */
1589 ddi_set_name_addr(child
, addr
);
1591 /* Allocate and initialize smp_device. */
1592 smp_sd
= kmem_zalloc(sizeof (struct smp_device
), KM_SLEEP
);
1593 smp_sd
->smp_sd_dev
= child
;
1594 smp_sd
->smp_sd_address
.smp_a_hba_tran
= tran
;
1595 bcopy(&wwn
, smp_sd
->smp_sd_address
.smp_a_wwn
, SAS_WWN_BYTE_SIZE
);
1597 ddi_set_driver_private(child
, smp_sd
);
1599 if (tran
->smp_tran_init
&& ((*tran
->smp_tran_init
)(self
, child
,
1600 tran
, smp_sd
) != DDI_SUCCESS
)) {
1601 kmem_free(smp_sd
, sizeof (struct smp_device
));
1602 scsi_enumeration_failed(child
, -1, NULL
, "smp_tran_init");
1603 ddi_set_driver_private(child
, NULL
);
1604 ddi_set_name_addr(child
, NULL
);
1605 return (DDI_FAILURE
);
1608 return (DDI_SUCCESS
);
1613 smp_busctl_uninitchild(dev_info_t
*child
)
1615 dev_info_t
*self
= ddi_get_parent(child
);
1616 struct smp_device
*smp_sd
= ddi_get_driver_private(child
);
1617 smp_hba_tran_t
*tran
;
1619 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SMP
);
1620 ASSERT(smp_sd
&& tran
);
1621 if ((smp_sd
== NULL
) || (tran
== NULL
))
1622 return (DDI_FAILURE
);
1624 if (tran
->smp_tran_free
)
1625 (*tran
->smp_tran_free
) (self
, child
, tran
, smp_sd
);
1627 kmem_free(smp_sd
, sizeof (*smp_sd
));
1628 ddi_set_driver_private(child
, NULL
);
1629 ddi_set_name_addr(child
, NULL
);
1630 return (DDI_SUCCESS
);
1633 /* Find an "smp" child at the specified address. */
1635 smp_findchild(dev_info_t
*self
, char *addr
)
1639 /* Search "smp" devinfo child at specified address. */
1640 ASSERT(self
&& DEVI_BUSY_OWNED(self
) && addr
);
1641 for (child
= ddi_get_child(self
); child
;
1642 child
= ddi_get_next_sibling(child
)) {
1643 /* skip non-"smp" nodes */
1644 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SMP
)
1647 /* Attempt initchild to establish unit-address */
1648 if (i_ddi_node_state(child
) < DS_INITIALIZED
)
1649 (void) ddi_initchild(self
, child
);
1651 /* Verify state and non-NULL unit-address. */
1652 if ((i_ddi_node_state(child
) < DS_INITIALIZED
) ||
1653 (ddi_get_name_addr(child
) == NULL
))
1656 /* Return "smp" child if unit-address matches. */
1657 if (strcmp(ddi_get_name_addr(child
), addr
) == 0)
1664 * Search for "smp" child of self at the specified address. If found, online
1665 * and return with a hold. Unlike general SCSI configuration, we can assume
1666 * the the device is actually there when we are called (i.e., device is
1667 * created by hotplug, not by bus_config).
1670 smp_hba_bus_config(dev_info_t
*self
, char *addr
, dev_info_t
**childp
)
1675 ASSERT(self
&& addr
&& childp
);
1678 /* Search for "smp" child. */
1679 scsi_hba_devi_enter(self
, &circ
);
1680 if ((child
= smp_findchild(self
, addr
)) == NULL
) {
1681 scsi_hba_devi_exit(self
, circ
);
1682 return (NDI_FAILURE
);
1685 /* Attempt online. */
1686 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
1687 scsi_hba_devi_exit(self
, circ
);
1688 return (NDI_FAILURE
);
1691 /* On success, return with active hold. */
1692 ndi_hold_devi(child
);
1693 scsi_hba_devi_exit(self
, circ
);
1695 return (NDI_SUCCESS
);
1700 /* Create "smp" child devinfo node at specified unit-address. */
1702 smp_hba_bus_config_taddr(dev_info_t
*self
, char *addr
)
1708 * NOTE: If we ever uses a generic node name (.vs. a driver name)
1709 * or define a 'compatible' property, this code will need to use
1710 * a 'probe' node (ala scsi_device support) to obtain identity
1711 * information from the device.
1714 /* Search for "smp" child. */
1715 scsi_hba_devi_enter(self
, &circ
);
1716 child
= smp_findchild(self
, addr
);
1718 /* Child exists, note if this was a new reinsert. */
1719 if (ndi_devi_device_insert(child
))
1720 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
1721 "devinfo smp@%s device_reinsert", addr
));
1723 scsi_hba_devi_exit(self
, circ
);
1724 return (NDI_SUCCESS
);
1727 /* Allocate "smp" child devinfo node and establish flavor of child. */
1728 ndi_devi_alloc_sleep(self
, "smp", DEVI_SID_HP_NODEID
, &child
);
1730 ndi_flavor_set(child
, SCSA_FLAVOR_SMP
);
1732 /* Add unit-address property to child. */
1733 if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
1734 SCSI_ADDR_PROP_TARGET_PORT
, addr
) != DDI_PROP_SUCCESS
) {
1735 (void) ndi_devi_free(child
);
1736 scsi_hba_devi_exit(self
, circ
);
1737 return (NDI_FAILURE
);
1740 /* Attempt to online the new "smp" node. */
1741 (void) ndi_devi_online(child
, 0);
1743 scsi_hba_devi_exit(self
, circ
);
1744 return (NDI_SUCCESS
);
1748 * Wrapper to scsi_ua_get which takes a devinfo argument instead of a
1749 * scsi_device structure.
1752 scsi_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
1754 struct scsi_device
*sd
;
1756 /* limit ndi_devi_findchild_by_callback to expected flavor */
1757 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
)
1758 return (DDI_FAILURE
);
1760 /* nodes are named by tran_get_name or default "tgt,lun" */
1761 sd
= ddi_get_driver_private(child
);
1762 if (sd
&& (scsi_ua_get(sd
, addr
, maxlen
) == 1))
1763 return (DDI_SUCCESS
);
1765 return (DDI_FAILURE
);
1769 scsi_busctl_reportdev(dev_info_t
*child
)
1771 dev_info_t
*self
= ddi_get_parent(child
);
1772 struct scsi_device
*sd
= ddi_get_driver_private(child
);
1773 scsi_hba_tran_t
*tran
;
1774 char ua
[SCSI_MAXNAMELEN
];
1775 char ra
[SCSI_MAXNAMELEN
];
1777 SCSI_HBA_LOG((_LOG_TRACE
, NULL
, child
, __func__
));
1779 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1781 if ((tran
== NULL
) || (sd
== NULL
))
1782 return (DDI_FAILURE
);
1784 /* get the unit_address and bus_addr information */
1785 if ((scsi_ua_get(sd
, ua
, sizeof (ua
)) == 0) ||
1786 (scsi_ua_get_reportdev(sd
, ra
, sizeof (ra
)) == 0)) {
1787 SCSI_HBA_LOG((_LOG(WARN
), NULL
, child
, "REPORTDEV failure"));
1788 return (DDI_FAILURE
);
1791 if (tran
->tran_get_name
== NULL
)
1792 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s",
1793 ddi_driver_name(child
), ddi_get_instance(child
),
1794 ddi_driver_name(self
), ddi_get_instance(self
), ra
));
1796 SCSI_HBA_LOG((_LOG_NF(CONT
),
1797 "?%s%d at %s%d: unit-address %s: %s",
1798 ddi_driver_name(child
), ddi_get_instance(child
),
1799 ddi_driver_name(self
), ddi_get_instance(self
), ua
, ra
));
1801 SCSI_HBA_LOG((_LOG_NF(CONT
),
1802 "?%s%d at %s%d: unit-address %s",
1803 ddi_driver_name(child
), ddi_get_instance(child
),
1804 ddi_driver_name(self
), ddi_get_instance(self
), ua
));
1806 return (DDI_SUCCESS
);
1811 * scsi_busctl_initchild is called to initialize the SCSA transport for
1812 * communication with a particular child scsi target device. Successful
1813 * initialization requires properties on the node which describe the address
1814 * of the target device. If the address of the target device can't be
1815 * determined from properties then DDI_NOT_WELL_FORMED is returned. Nodes that
1816 * are DDI_NOT_WELL_FORMED are considered an implementation artifact and
1817 * are hidden from devinfo snapshots by calling ndi_devi_set_hidden().
1818 * The child may be one of the following types of devinfo nodes:
1821 * OBP does not enumerate target devices attached a SCSI bus. These
1822 * template/stub/wild-card nodes are a legacy artifact for support of old
1823 * driver loading methods. Since they have no properties,
1824 * DDI_NOT_WELL_FORMED will be returned.
1827 * The node may be either a:
1828 * o probe/barrier SID node
1829 * o a dynamic SID target node
1831 * driver.conf node: The situation for this nexus is different than most.
1832 * Typically a driver.conf node definition is used to either define a
1833 * new child devinfo node or to further decorate (via merge) a SID
1834 * child with properties. In our case we use the nodes for *both*
1837 * In both the SID node and driver.conf node cases we must form the nodes
1838 * "@addr" from the well-known scsi(9P) device unit-address properties on
1841 * For HBA drivers that implement the deprecated tran_get_name interface,
1842 * "@addr" construction involves having that driver interpret properties via
1843 * scsi_busctl_ua -> scsi_ua_get -> tran_get_name: there is no
1844 * requirement for the property names to be well-known.
1846 * NOTE: We don't currently support "merge". When this support is added a
1847 * specific property, like "unit-address", should *always* identify a
1848 * driver.conf node that needs to be merged into a specific SID node. When
1849 * enumeration is enabled, a .conf node without the "unit-address" property
1850 * should be ignored. The best way to establish the "unit-address" property
1851 * would be to have the system assign parent= and unit-address= from an
1852 * instance=# driver.conf entry (by using the instance tree).
1855 scsi_busctl_initchild(dev_info_t
*child
)
1857 dev_info_t
*self
= ddi_get_parent(child
);
1859 scsi_hba_tran_t
*tran
;
1860 struct scsi_device
*sd
;
1861 scsi_hba_tran_t
*tran_clone
;
1866 int err
= DDI_FAILURE
;
1867 char addr
[SCSI_MAXNAMELEN
];
1869 ASSERT(DEVI_BUSY_OWNED(self
));
1870 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init begin"));
1873 * For a driver like fp with multiple upper-layer-protocols
1874 * it is possible for scsi_hba_init in _init to plumb SCSA
1875 * and have the load of fcp (which does scsi_hba_attach_setup)
1876 * to fail. In this case we may get here with a NULL hba.
1878 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
1880 return (DDI_NOT_WELL_FORMED
);
1883 * OBP may create template/stub/wild-card nodes for legacy driver
1884 * loading methods. These nodes have no properties, so we lack the
1885 * addressing properties to initchild them. Hide the node and return
1886 * DDI_NOT_WELL_FORMED.
1888 * Future: define/use a ndi_devi_has_properties(dip) type interface.
1890 * NOTE: It would be nice if we could delete these ill formed nodes by
1891 * implementing a DDI_NOT_WELL_FORMED_DELETE return code. This can't
1892 * be done until leadville debug code removes its dependencies
1893 * on the devinfo still being present after a failed ndi_devi_online.
1895 if ((DEVI(child
)->devi_hw_prop_ptr
== NULL
) &&
1896 (DEVI(child
)->devi_drv_prop_ptr
== NULL
) &&
1897 (DEVI(child
)->devi_sys_prop_ptr
== NULL
)) {
1898 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1899 "init failed: no properties"));
1900 ndi_devi_set_hidden(child
);
1901 return (DDI_NOT_WELL_FORMED
);
1904 /* get legacy SPI addressing properties */
1905 if ((tgt
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1906 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
1907 SCSI_ADDR_PROP_TARGET
, -1)) == -1) {
1910 * A driver.conf node for merging always has a target= property,
1911 * even if it is just a dummy that does not contain the real
1912 * target address. However drivers that register devids may
1913 * create stub driver.conf nodes without a target= property so
1914 * that pathological devid resolution works. Hide the stub
1915 * node and return DDI_NOT_WELL_FORMED.
1917 if (!scsi_hba_dev_is_sid(child
)) {
1918 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
1919 "init failed: stub .conf node"));
1920 ndi_devi_set_hidden(child
);
1921 return (DDI_NOT_WELL_FORMED
);
1924 lun
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1925 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_LUN
, 0);
1926 sfunc
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
1927 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, SCSI_ADDR_PROP_SFUNC
, -1);
1930 * The scsi_address structure may not specify all the addressing
1931 * information. For an old HBA that doesn't support tran_get_name
1932 * (most pre-SCSI-3 HBAs) the scsi_address structure is still used,
1933 * so the target property must exist and the LUN must be < 256.
1935 if ((tran
->tran_get_name
== NULL
) &&
1936 ((tgt
>= USHRT_MAX
) || (lun
>= 256))) {
1937 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
1938 "init failed: illegal/missing properties"));
1939 ndi_devi_set_hidden(child
);
1940 return (DDI_NOT_WELL_FORMED
);
1944 * We need to initialize a fair amount of our environment to invoke
1945 * tran_get_name (via scsi_busctl_ua and scsi_ua_get) to
1946 * produce the "@addr" name from addressing properties. Allocate and
1947 * initialize scsi device structure.
1949 sd
= kmem_zalloc(sizeof (struct scsi_device
), KM_SLEEP
);
1950 mutex_init(&sd
->sd_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
1952 sd
->sd_pathinfo
= NULL
;
1953 sd
->sd_uninit_prevent
= 0;
1954 ddi_set_driver_private(child
, sd
);
1956 if (tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
) {
1958 * For a SCSI_HBA_ADDR_COMPLEX transport we store a pointer to
1959 * scsi_device in the scsi_address structure. This allows an
1960 * HBA driver to find its per-scsi_device private data
1961 * (accessible to the HBA given just the scsi_address by using
1962 * scsi_address_device(9F)/scsi_device_hba_private_get(9F)).
1964 sd
->sd_address
.a
.a_sd
= sd
;
1968 * Initialize the scsi_address so that a SCSI-2 target driver
1969 * talking to a SCSI-2 device on a SCSI-3 bus (spi) continues
1970 * to work. We skew the secondary function value so that we
1971 * can tell from the address structure if we are processing
1972 * a secondary function request.
1974 sd
->sd_address
.a_target
= (ushort_t
)tgt
;
1975 sd
->sd_address
.a_lun
= (uchar_t
)lun
;
1977 sd
->sd_address
.a_sublun
= (uchar_t
)0;
1979 sd
->sd_address
.a_sublun
= (uchar_t
)sfunc
+ 1;
1982 * NOTE: Don't limit LUNs to scsi_options value because a
1983 * scsi_device discovered via SPI dynamic enumeration might
1984 * still support SCMD_REPORT_LUNS.
1988 * Deprecated: Use SCSI_HBA_ADDR_COMPLEX:
1989 * Clone transport structure if requested. Cloning allows
1990 * an HBA to maintain target-specific information if
1991 * necessary, such as target addressing information that
1992 * does not adhere to the scsi_address structure format.
1994 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
1995 tran_clone
= kmem_alloc(
1996 sizeof (scsi_hba_tran_t
), KM_SLEEP
);
1997 bcopy((caddr_t
)tran
,
1998 (caddr_t
)tran_clone
, sizeof (scsi_hba_tran_t
));
2003 ASSERT(tran
->tran_sd
== NULL
);
2007 /* establish scsi_address pointer to the HBA's tran structure */
2008 sd
->sd_address
.a_hba_tran
= tran
;
2011 * This is a grotty hack that allows direct-access (non-scsa) drivers
2012 * (like chs, ata, and mlx which all make cmdk children) to put its
2013 * own vector in the 'a_hba_tran' field. When all the drivers that do
2014 * this are fixed, please remove this hack.
2016 * NOTE: This hack is also shows up in the DEVP_TO_TRAN implementation
2017 * in scsi_confsubr.c.
2019 sd
->sd_tran_safe
= tran
;
2022 * If the class property is not already established, set it to "scsi".
2023 * This is done so that parent= driver.conf nodes have class.
2025 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2026 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "class",
2027 &class) == DDI_PROP_SUCCESS
) {
2028 ddi_prop_free(class);
2029 } else if (ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
2030 "class", "scsi") != DDI_PROP_SUCCESS
) {
2031 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: class"));
2032 ndi_devi_set_hidden(child
);
2033 err
= DDI_NOT_WELL_FORMED
;
2037 /* Establish the @addr name of the child. */
2039 if (scsi_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
) {
2041 * Some driver.conf files add bogus target properties (relative
2042 * to their nexus representation of target) to their stub
2043 * nodes, causing the check above to not filter them.
2045 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
2046 "init failed: scsi_busctl_ua call"));
2047 ndi_devi_set_hidden(child
);
2048 err
= DDI_NOT_WELL_FORMED
;
2051 if (*addr
== '\0') {
2052 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "init failed: ua"));
2053 ndi_devi_set_hidden(child
);
2054 err
= DDI_NOT_WELL_FORMED
;
2058 /* Prevent duplicate nodes. */
2059 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2062 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_SCSI_DEVICE
);
2063 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_SCSI_DEVICE
) {
2064 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2065 "init failed: %s@%s: not SCSI_DEVICE flavored",
2066 ddi_node_name(child
), addr
));
2070 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2071 "init failed: %s@%s: detected duplicate %p",
2072 ddi_node_name(child
), addr
, (void *)dup
));
2077 /* set the node @addr string */
2078 ddi_set_name_addr(child
, addr
);
2080 /* call HBA's target init entry point if it exists */
2081 if (tran
->tran_tgt_init
!= NULL
) {
2082 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "init tran_tgt_init"));
2083 sd
->sd_tran_tgt_free_done
= 0;
2084 if ((*tran
->tran_tgt_init
)
2085 (self
, child
, tran
, sd
) != DDI_SUCCESS
) {
2086 scsi_enumeration_failed(child
, -1, NULL
,
2092 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "init successful"));
2093 return (DDI_SUCCESS
);
2097 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2098 mutex_destroy(&sd
->sd_mutex
);
2099 kmem_free(sd
, sizeof (*sd
));
2100 ddi_set_driver_private(child
, NULL
);
2101 ddi_set_name_addr(child
, NULL
);
2103 return (err
); /* remove the node */
2107 scsi_busctl_uninitchild(dev_info_t
*child
)
2109 dev_info_t
*self
= ddi_get_parent(child
);
2110 struct scsi_device
*sd
= ddi_get_driver_private(child
);
2111 scsi_hba_tran_t
*tran
;
2112 scsi_hba_tran_t
*tran_clone
;
2114 ASSERT(DEVI_BUSY_OWNED(self
));
2116 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
2118 if ((tran
== NULL
) || (sd
== NULL
))
2119 return (DDI_FAILURE
);
2122 * We use sd_uninit_prevent to avoid uninitializing barrier/probe
2123 * nodes that are still in use. Since barrier/probe nodes are not
2124 * attached we can't prevent their state demotion via ndi_hold_devi.
2126 if (sd
->sd_uninit_prevent
) {
2127 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "uninit prevented"));
2128 return (DDI_FAILURE
);
2132 * Don't uninitialize a client node if it still has paths.
2134 if (MDI_CLIENT(child
) && mdi_client_get_path_count(child
)) {
2135 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
2136 "uninit prevented, client has paths"));
2137 return (DDI_FAILURE
);
2140 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit begin"));
2142 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
) {
2143 tran_clone
= sd
->sd_address
.a_hba_tran
;
2145 /* ... grotty hack, involving sd_tran_safe, continued. */
2146 if (tran_clone
!= sd
->sd_tran_safe
) {
2147 tran_clone
= sd
->sd_tran_safe
;
2150 * Complain so things get fixed and hack can, at
2151 * some point in time, be removed.
2153 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2154 "'%s' is corrupting a_hba_tran", sd
->sd_dev
?
2155 ddi_driver_name(sd
->sd_dev
) : "unknown_driver"));
2159 ASSERT(tran_clone
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
);
2160 ASSERT(tran_clone
->tran_sd
== sd
);
2164 ASSERT(tran
->tran_sd
== NULL
);
2168 * To simplify host adapter drivers we guarantee that multiple
2169 * tran_tgt_init(9E) calls of the same unit address are never
2170 * active at the same time. This requires that we always call
2171 * tran_tgt_free on probe/barrier nodes directly prior to
2174 * NOTE: To correctly support SCSI_HBA_TRAN_CLONE, we must use
2175 * the (possibly cloned) hba_tran pointer from the scsi_device
2176 * instead of hba_tran.
2178 if (tran
->tran_tgt_free
) {
2179 if (!sd
->sd_tran_tgt_free_done
) {
2180 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2181 "uninit tran_tgt_free"));
2182 (*tran
->tran_tgt_free
) (self
, child
, tran
, sd
);
2183 sd
->sd_tran_tgt_free_done
= 1;
2185 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2186 "uninit tran_tgt_free already done"));
2191 * If a inquiry data is still allocated (by scsi_probe()) we
2192 * free the allocation here. This keeps scsi_inq valid for the
2193 * same duration as the corresponding inquiry properties. It
2194 * also allows a tran_tgt_init() implementation that establishes
2195 * sd_inq to deal with deallocation in its tran_tgt_free
2196 * (setting sd_inq back to NULL) without upsetting the
2197 * framework. Moving the inquiry free here also allows setting
2198 * of sd_uninit_prevent to preserve the data for lun0 based
2199 * scsi_get_device_type_scsi_options() calls.
2202 kmem_free(sd
->sd_inq
, SUN_INQSIZE
);
2203 sd
->sd_inq
= (struct scsi_inquiry
*)NULL
;
2206 mutex_destroy(&sd
->sd_mutex
);
2208 kmem_free(tran_clone
, sizeof (scsi_hba_tran_t
));
2209 kmem_free(sd
, sizeof (*sd
));
2211 ddi_set_driver_private(child
, NULL
);
2212 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "uninit complete"));
2213 ddi_set_name_addr(child
, NULL
);
2214 return (DDI_SUCCESS
);
2218 iport_busctl_ua(dev_info_t
*child
, char *addr
, int maxlen
)
2222 /* limit ndi_devi_findchild_by_callback to expected flavor */
2223 if (ndi_flavor_get(child
) != SCSA_FLAVOR_IPORT
)
2224 return (DDI_FAILURE
);
2226 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2227 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2228 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
) {
2229 return (DDI_FAILURE
);
2232 (void) snprintf(addr
, maxlen
, "%s", iport_ua
);
2233 ddi_prop_free(iport_ua
);
2234 return (DDI_SUCCESS
);
2238 iport_busctl_reportdev(dev_info_t
*child
)
2240 dev_info_t
*self
= ddi_get_parent(child
);
2242 char *initiator_port
= NULL
;
2244 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2245 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2246 SCSI_ADDR_PROP_IPORTUA
, &iport_ua
) != DDI_SUCCESS
)
2247 return (DDI_FAILURE
);
2249 (void) ddi_prop_lookup_string(DDI_DEV_T_ANY
, child
,
2250 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
2251 SCSI_ADDR_PROP_INITIATOR_PORT
, &initiator_port
);
2253 if (initiator_port
) {
2254 SCSI_HBA_LOG((_LOG_NF(CONT
),
2255 "?%s%d at %s%d: %s %s %s %s",
2256 ddi_driver_name(child
), ddi_get_instance(child
),
2257 ddi_driver_name(self
), ddi_get_instance(self
),
2258 SCSI_ADDR_PROP_INITIATOR_PORT
, initiator_port
,
2259 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2260 ddi_prop_free(initiator_port
);
2262 SCSI_HBA_LOG((_LOG_NF(CONT
), "?%s%d at %s%d: %s %s",
2263 ddi_driver_name(child
), ddi_get_instance(child
),
2264 ddi_driver_name(self
), ddi_get_instance(self
),
2265 SCSI_ADDR_PROP_IPORTUA
, iport_ua
));
2267 ddi_prop_free(iport_ua
);
2268 return (DDI_SUCCESS
);
2271 /* initchild SCSA iport 'child' node */
2273 iport_busctl_initchild(dev_info_t
*child
)
2275 dev_info_t
*self
= ddi_get_parent(child
);
2276 dev_info_t
*dup
= NULL
;
2277 char addr
[SCSI_MAXNAMELEN
];
2279 if (iport_busctl_ua(child
, addr
, sizeof (addr
)) != DDI_SUCCESS
)
2280 return (DDI_NOT_WELL_FORMED
);
2282 /* Prevent duplicate nodes. */
2283 dup
= ndi_devi_findchild_by_callback(self
, ddi_node_name(child
), addr
,
2286 ASSERT(ndi_flavor_get(dup
) == SCSA_FLAVOR_IPORT
);
2287 if (ndi_flavor_get(dup
) != SCSA_FLAVOR_IPORT
) {
2288 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
2289 "init failed: %s@%s: not IPORT flavored",
2290 ddi_node_name(child
), addr
));
2291 return (DDI_FAILURE
);
2294 SCSI_HBA_LOG((_LOG(4), NULL
, child
,
2295 "init failed: %s@%s: detected duplicate %p",
2296 ddi_node_name(child
), addr
, (void *)dup
));
2297 return (DDI_FAILURE
);
2301 /* set the node @addr string */
2302 ddi_set_name_addr(child
, addr
);
2304 return (DDI_SUCCESS
);
2307 /* uninitchild SCSA iport 'child' node */
2309 iport_busctl_uninitchild(dev_info_t
*child
)
2311 ddi_set_name_addr(child
, NULL
);
2312 return (DDI_SUCCESS
);
2315 /* Uninitialize scsi_device flavor of transport on SCSA iport 'child' node. */
2317 iport_postdetach_tran_scsi_device(dev_info_t
*child
)
2319 scsi_hba_tran_t
*tran
;
2321 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SCSI_DEVICE
);
2325 scsa_tran_teardown(child
, tran
);
2326 scsa_nexus_teardown(child
, tran
);
2328 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, NULL
);
2329 scsi_hba_tran_free(tran
);
2332 /* Initialize scsi_device flavor of transport on SCSA iport 'child' node. */
2334 iport_preattach_tran_scsi_device(dev_info_t
*child
)
2336 dev_info_t
*hba
= ddi_get_parent(child
);
2337 scsi_hba_tran_t
*htran
;
2338 scsi_hba_tran_t
*tran
;
2340 /* parent HBA node scsi_device tran is required */
2341 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SCSI_DEVICE
);
2344 /* Allocate iport child's scsi_device transport vector */
2345 tran
= scsi_hba_tran_alloc(child
, SCSI_HBA_CANSLEEP
);
2348 /* Structure-copy scsi_device transport of HBA to iport. */
2352 * Reset scsi_device transport fields not shared with the
2353 * parent, and not established below.
2355 tran
->tran_open_flag
= 0;
2356 tran
->tran_hba_private
= NULL
;
2358 /* Establish the devinfo context of this tran structure. */
2359 tran
->tran_iport_dip
= child
;
2361 /* Clear SCSI_HBA_SCSA flags (except TA) */
2362 tran
->tran_hba_flags
&=
2363 ~(SCSI_HBA_SCSA_FM
| SCSI_HBA_SCSA_PHCI
); /* clear parent state */
2364 tran
->tran_hba_flags
|= SCSI_HBA_SCSA_TA
; /* always TA */
2365 tran
->tran_hba_flags
&= ~SCSI_HBA_HBA
; /* never HBA */
2367 /* Establish flavor of transport (and ddi_get_driver_private()) */
2368 ndi_flavorv_set(child
, SCSA_FLAVOR_SCSI_DEVICE
, tran
);
2370 /* Setup iport node */
2371 if ((scsa_nexus_setup(child
, tran
) != DDI_SUCCESS
) ||
2372 (scsa_tran_setup(child
, tran
) != DDI_SUCCESS
))
2373 iport_postdetach_tran_scsi_device(child
);
2376 /* Uninitialize smp_device flavor of transport on SCSA iport 'child' node. */
2378 iport_postdetach_tran_smp_device(dev_info_t
*child
)
2380 smp_hba_tran_t
*tran
;
2382 tran
= ndi_flavorv_get(child
, SCSA_FLAVOR_SMP
);
2386 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2387 smp_hba_tran_free(tran
);
2390 /* Initialize smp_device flavor of transport on SCSA iport 'child' node. */
2392 iport_preattach_tran_smp_device(dev_info_t
*child
)
2394 dev_info_t
*hba
= ddi_get_parent(child
);
2395 smp_hba_tran_t
*htran
;
2396 smp_hba_tran_t
*tran
;
2398 /* parent HBA node smp_device tran is optional */
2399 htran
= ndi_flavorv_get(hba
, SCSA_FLAVOR_SMP
);
2400 if (htran
== NULL
) {
2401 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, NULL
);
2405 /* Allocate iport child's smp_device transport vector */
2406 tran
= smp_hba_tran_alloc(child
);
2408 /* Structure-copy smp_device transport of HBA to iport. */
2411 /* Establish flavor of transport */
2412 ndi_flavorv_set(child
, SCSA_FLAVOR_SMP
, tran
);
2416 * Generic bus_ctl operations for SCSI HBA's,
2417 * hiding the busctl interface from the HBA.
2428 int child_flavor
= 0;
2430 ddi_dma_attr_t
*attr
;
2431 scsi_hba_tran_t
*tran
;
2432 struct attachspec
*as
;
2433 struct detachspec
*ds
;
2435 /* For some ops, child is 'arg'. */
2436 if ((op
== DDI_CTLOPS_INITCHILD
) || (op
== DDI_CTLOPS_UNINITCHILD
))
2437 child
= (dev_info_t
*)arg
;
2439 /* Determine the flavor of the child: scsi, smp, iport */
2440 child_flavor
= ndi_flavor_get(child
);
2443 case DDI_CTLOPS_INITCHILD
:
2444 switch (child_flavor
) {
2445 case SCSA_FLAVOR_SCSI_DEVICE
:
2446 return (scsi_busctl_initchild(child
));
2447 case SCSA_FLAVOR_SMP
:
2448 return (smp_busctl_initchild(child
));
2449 case SCSA_FLAVOR_IPORT
:
2450 return (iport_busctl_initchild(child
));
2452 return (DDI_FAILURE
);
2456 case DDI_CTLOPS_UNINITCHILD
:
2457 switch (child_flavor
) {
2458 case SCSA_FLAVOR_SCSI_DEVICE
:
2459 return (scsi_busctl_uninitchild(child
));
2460 case SCSA_FLAVOR_SMP
:
2461 return (smp_busctl_uninitchild(child
));
2462 case SCSA_FLAVOR_IPORT
:
2463 return (iport_busctl_uninitchild(child
));
2465 return (DDI_FAILURE
);
2469 case DDI_CTLOPS_REPORTDEV
:
2470 switch (child_flavor
) {
2471 case SCSA_FLAVOR_SCSI_DEVICE
:
2472 return (scsi_busctl_reportdev(child
));
2473 case SCSA_FLAVOR_SMP
:
2474 return (smp_busctl_reportdev(child
));
2475 case SCSA_FLAVOR_IPORT
:
2476 return (iport_busctl_reportdev(child
));
2478 return (DDI_FAILURE
);
2482 case DDI_CTLOPS_ATTACH
:
2483 as
= (struct attachspec
*)arg
;
2485 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2486 return (DDI_SUCCESS
);
2488 /* iport processing */
2489 if (as
->when
== DDI_PRE
) {
2490 /* setup pre attach(9E) */
2491 iport_preattach_tran_scsi_device(child
);
2492 iport_preattach_tran_smp_device(child
);
2493 } else if ((as
->when
== DDI_POST
) &&
2494 (as
->result
!= DDI_SUCCESS
)) {
2495 /* cleanup if attach(9E) failed */
2496 iport_postdetach_tran_scsi_device(child
);
2497 iport_postdetach_tran_smp_device(child
);
2499 return (DDI_SUCCESS
);
2501 case DDI_CTLOPS_DETACH
:
2502 ds
= (struct detachspec
*)arg
;
2504 if (child_flavor
!= SCSA_FLAVOR_IPORT
)
2505 return (DDI_SUCCESS
);
2507 /* iport processing */
2508 if ((ds
->when
== DDI_POST
) &&
2509 (ds
->result
== DDI_SUCCESS
)) {
2510 /* cleanup if detach(9E) was successful */
2511 iport_postdetach_tran_scsi_device(child
);
2512 iport_postdetach_tran_smp_device(child
);
2514 return (DDI_SUCCESS
);
2516 case DDI_CTLOPS_IOMIN
:
2517 tran
= ddi_get_driver_private(self
);
2520 return (DDI_FAILURE
);
2523 * The 'arg' value of nonzero indicates 'streaming'
2524 * mode. If in streaming mode, pick the largest
2525 * of our burstsizes available and say that that
2526 * is our minimum value (modulo what minxfer is).
2528 attr
= &tran
->tran_dma_attr
;
2529 val
= *((int *)result
);
2530 val
= maxbit(val
, attr
->dma_attr_minxfer
);
2531 *((int *)result
) = maxbit(val
, ((intptr_t)arg
?
2532 (1<<ddi_ffs(attr
->dma_attr_burstsizes
)-1) :
2533 (1<<(ddi_fls(attr
->dma_attr_burstsizes
)-1))));
2535 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2537 case DDI_CTLOPS_SIDDEV
:
2538 return (ndi_dev_is_persistent_node(child
) ?
2539 DDI_SUCCESS
: DDI_FAILURE
);
2541 case DDI_CTLOPS_POWER
:
2542 return (DDI_SUCCESS
);
2545 * These ops correspond to functions that "shouldn't" be called
2546 * by a SCSI target driver. So we whine when we're called.
2548 case DDI_CTLOPS_DMAPMAPC
:
2549 case DDI_CTLOPS_REPORTINT
:
2550 case DDI_CTLOPS_REGSIZE
:
2551 case DDI_CTLOPS_NREGS
:
2552 case DDI_CTLOPS_SLAVEONLY
:
2553 case DDI_CTLOPS_AFFINITY
:
2554 case DDI_CTLOPS_POKE
:
2555 case DDI_CTLOPS_PEEK
:
2556 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
, "invalid op (%d)", op
));
2557 return (DDI_FAILURE
);
2559 /* Everything else we pass up */
2560 case DDI_CTLOPS_PTOB
:
2561 case DDI_CTLOPS_BTOP
:
2562 case DDI_CTLOPS_BTOPR
:
2563 case DDI_CTLOPS_DVMAPAGESIZE
:
2565 return (ddi_ctlops(self
, child
, op
, arg
, result
));
2571 * Private wrapper for scsi_pkt's allocated via scsi_hba_pkt_alloc()
2573 struct scsi_pkt_wrapper
{
2574 struct scsi_pkt scsi_pkt
;
2575 int pkt_wrapper_magic
;
2576 int pkt_wrapper_len
;
2580 _NOTE(SCHEME_PROTECTS_DATA("unique per thread", scsi_pkt_wrapper
))
2581 _NOTE(SCHEME_PROTECTS_DATA("Unshared Data", dev_ops
))
2585 * Called by an HBA to allocate a scsi_pkt
2591 struct scsi_address
*ap
,
2596 int (*callback
)(caddr_t arg
),
2599 struct scsi_pkt
*pkt
;
2600 struct scsi_pkt_wrapper
*hba_pkt
;
2602 int acmdlen
, astatuslen
, atgtlen
, ahbalen
;
2606 if (callback
!= SLEEP_FUNC
&& callback
!= NULL_FUNC
)
2607 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2608 "callback must be SLEEP_FUNC or NULL_FUNC"));
2611 * Round up so everything gets allocated on long-word boundaries
2613 acmdlen
= ROUNDUP(cmdlen
);
2614 astatuslen
= ROUNDUP(statuslen
);
2615 atgtlen
= ROUNDUP(tgtlen
);
2616 ahbalen
= ROUNDUP(hbalen
);
2617 pktlen
= sizeof (struct scsi_pkt_wrapper
) +
2618 acmdlen
+ astatuslen
+ atgtlen
+ ahbalen
;
2620 hba_pkt
= kmem_zalloc(pktlen
,
2621 (callback
== SLEEP_FUNC
) ? KM_SLEEP
: KM_NOSLEEP
);
2622 if (hba_pkt
== NULL
) {
2623 ASSERT(callback
== NULL_FUNC
);
2628 * Set up our private info on this pkt
2630 hba_pkt
->pkt_wrapper_len
= pktlen
;
2631 hba_pkt
->pkt_wrapper_magic
= PKT_WRAPPER_MAGIC
; /* alloced correctly */
2632 pkt
= &hba_pkt
->scsi_pkt
;
2635 * Set up pointers to private data areas, cdb, and status.
2637 p
= (caddr_t
)(hba_pkt
+ 1);
2639 pkt
->pkt_ha_private
= (opaque_t
)p
;
2643 pkt
->pkt_private
= (opaque_t
)p
;
2646 if (statuslen
> 0) {
2647 pkt
->pkt_scbp
= (uchar_t
*)p
;
2651 pkt
->pkt_cdbp
= (uchar_t
*)p
;
2655 * Initialize the pkt's scsi_address
2657 pkt
->pkt_address
= *ap
;
2660 * NB: It may not be safe for drivers, esp target drivers, to depend
2661 * on the following fields being set until all the scsi_pkt
2662 * allocation violations discussed in scsi_pkt.h are all resolved.
2664 pkt
->pkt_cdblen
= cmdlen
;
2665 pkt
->pkt_tgtlen
= tgtlen
;
2666 pkt
->pkt_scblen
= statuslen
;
2672 * Called by an HBA to free a scsi_pkt
2677 struct scsi_address
*ap
,
2678 struct scsi_pkt
*pkt
)
2680 kmem_free(pkt
, ((struct scsi_pkt_wrapper
*)pkt
)->pkt_wrapper_len
);
2684 * Return 1 if the scsi_pkt used a proper allocator.
2686 * The DDI does not allow a driver to allocate it's own scsi_pkt(9S), a
2687 * driver should not have *any* compiled in dependencies on "sizeof (struct
2688 * scsi_pkt)". While this has been the case for many years, a number of
2689 * drivers have still not been fixed. This function can be used to detect
2690 * improperly allocated scsi_pkt structures, and produce messages identifying
2691 * drivers that need to be fixed.
2693 * While drivers in violation are being fixed, this function can also
2694 * be used by the framework to detect packets that violated allocation
2697 * NB: It is possible, but very unlikely, for this code to return a false
2698 * positive (finding correct magic, but for wrong reasons). Careful
2699 * consideration is needed for callers using this interface to condition
2700 * access to newer scsi_pkt fields (those after pkt_reason).
2702 * NB: As an aid to minimizing the amount of work involved in 'fixing' legacy
2703 * drivers that violate scsi_*(9S) allocation rules, private
2704 * scsi_pkt_size()/scsi_size_clean() functions are available (see their
2705 * implementation for details).
2707 * *** Non-legacy use of scsi_pkt_size() is discouraged. ***
2709 * NB: When supporting broken HBA drivers is not longer a concern, this
2710 * code should be removed.
2713 scsi_pkt_allocated_correctly(struct scsi_pkt
*pkt
)
2715 struct scsi_pkt_wrapper
*hba_pkt
= (struct scsi_pkt_wrapper
*)pkt
;
2719 int *pspwm
, *pspcwm
;
2722 * We are getting scsi packets from two 'correct' wrapper schemes,
2723 * make sure we are looking at the same place in both to detect
2724 * proper allocation.
2726 pspwm
= &((struct scsi_pkt_wrapper
*)0)->pkt_wrapper_magic
;
2727 pspcwm
= &((struct scsi_pkt_cache_wrapper
*)0)->pcw_magic
;
2728 ASSERT(pspwm
== pspcwm
);
2733 * Check to see if driver is scsi_size_clean(), assume it
2734 * is using the scsi_pkt_size() interface everywhere it needs to
2735 * if the driver indicates it is scsi_size_clean().
2737 major
= ddi_driver_major(P_TO_TRAN(pkt
)->tran_hba_dip
);
2738 if (devnamesp
[major
].dn_flags
& DN_SCSI_SIZE_CLEAN
)
2739 return (1); /* ok */
2742 * Special case crossing a page boundary. If the scsi_pkt was not
2743 * allocated correctly, then across a page boundary we have a
2746 if ((((uintptr_t)(&hba_pkt
->scsi_pkt
)) & MMU_PAGEMASK
) ==
2747 (((uintptr_t)(&hba_pkt
->pkt_wrapper_magic
)) & MMU_PAGEMASK
)) {
2748 /* fastpath, no cross-page hazard */
2749 magic
= hba_pkt
->pkt_wrapper_magic
;
2751 /* add protection for cross-page hazard */
2752 if (ddi_peek32((dev_info_t
*)NULL
,
2753 &hba_pkt
->pkt_wrapper_magic
, &magic
) == DDI_FAILURE
) {
2754 return (0); /* violation */
2758 /* properly allocated packet always has correct magic */
2759 return ((magic
== PKT_WRAPPER_MAGIC
) ? 1 : 0);
2763 * Private interfaces to simplify conversion of legacy drivers so they don't
2764 * depend on scsi_*(9S) size. Instead of using these private interface, HBA
2765 * drivers should use DDI sanctioned allocation methods:
2767 * scsi_pkt Use scsi_hba_pkt_alloc(9F), or implement
2768 * tran_setup_pkt(9E).
2770 * scsi_device You are doing something strange/special, a scsi_device
2771 * structure should only be allocated by scsi_hba.c
2772 * initchild code or scsi_vhci.c code.
2774 * scsi_hba_tran Use scsi_hba_tran_alloc(9F).
2779 return (sizeof (struct scsi_pkt
));
2783 scsi_hba_tran_size()
2785 return (sizeof (scsi_hba_tran_t
));
2791 return (sizeof (struct scsi_device
));
2795 * Legacy compliance to scsi_pkt(9S) allocation rules through use of
2796 * scsi_pkt_size() is detected by the 'scsi-size-clean' driver.conf property
2797 * or an HBA driver calling to scsi_size_clean() from attach(9E). A driver
2798 * developer should only indicate that a legacy driver is clean after using
2799 * SCSI_SIZE_CLEAN_VERIFY to ensure compliance (see scsi_pkt.h).
2802 scsi_size_clean(dev_info_t
*self
)
2805 struct devnames
*dnp
;
2808 major
= ddi_driver_major(self
);
2809 ASSERT(major
< devcnt
);
2810 if (major
>= devcnt
) {
2811 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
2812 "scsi_pkt_size: bogus major: %d", major
));
2816 /* Set DN_SCSI_SIZE_CLEAN flag in dn_flags. */
2817 dnp
= &devnamesp
[major
];
2818 if ((dnp
->dn_flags
& DN_SCSI_SIZE_CLEAN
) == 0) {
2819 LOCK_DEV_OPS(&dnp
->dn_lock
);
2820 dnp
->dn_flags
|= DN_SCSI_SIZE_CLEAN
;
2821 UNLOCK_DEV_OPS(&dnp
->dn_lock
);
2827 * Called by an HBA to map strings to capability indices
2830 scsi_hba_lookup_capstr(
2834 * Capability strings: only add entries to mask the legacy
2835 * '_' vs. '-' misery. All new capabilities should use '-',
2836 * and be captured be added to SCSI_CAP_ASCII.
2838 static struct cap_strings
{
2842 { "dma_max", SCSI_CAP_DMA_MAX
},
2843 { "msg_out", SCSI_CAP_MSG_OUT
},
2844 { "wide_xfer", SCSI_CAP_WIDE_XFER
},
2847 static char *cap_ascii
[] = SCSI_CAP_ASCII
;
2850 struct cap_strings
*cp
;
2852 for (cap
= cap_ascii
, i
= 0; *cap
!= NULL
; cap
++, i
++)
2853 if (strcmp(*cap
, capstr
) == 0)
2856 for (cp
= cap_strings
; cp
->cap_string
!= NULL
; cp
++)
2857 if (strcmp(cp
->cap_string
, capstr
) == 0)
2858 return (cp
->cap_index
);
2864 * Called by an HBA to determine if the system is in 'panic' state.
2869 return (panicstr
!= NULL
);
2873 * If a SCSI target driver attempts to mmap memory,
2874 * the buck stops here.
2889 return (DDI_FAILURE
);
2893 scsi_hba_get_eventcookie(
2897 ddi_eventcookie_t
*eventp
)
2899 scsi_hba_tran_t
*tran
;
2901 tran
= ddi_get_driver_private(self
);
2902 if (tran
->tran_get_eventcookie
&&
2903 ((*tran
->tran_get_eventcookie
)(self
,
2904 child
, name
, eventp
) == DDI_SUCCESS
)) {
2905 return (DDI_SUCCESS
);
2908 return (ndi_busop_get_eventcookie(self
, child
, name
, eventp
));
2912 scsi_hba_add_eventcall(
2915 ddi_eventcookie_t event
,
2918 ddi_eventcookie_t event
,
2920 void *bus_impldata
),
2922 ddi_callback_id_t
*cb_id
)
2924 scsi_hba_tran_t
*tran
;
2926 tran
= ddi_get_driver_private(self
);
2927 if (tran
->tran_add_eventcall
&&
2928 ((*tran
->tran_add_eventcall
)(self
, child
,
2929 event
, callback
, arg
, cb_id
) == DDI_SUCCESS
)) {
2930 return (DDI_SUCCESS
);
2933 return (DDI_FAILURE
);
2937 scsi_hba_remove_eventcall(dev_info_t
*self
, ddi_callback_id_t cb_id
)
2939 scsi_hba_tran_t
*tran
;
2942 tran
= ddi_get_driver_private(self
);
2943 if (tran
->tran_remove_eventcall
&&
2944 ((*tran
->tran_remove_eventcall
)(
2945 self
, cb_id
) == DDI_SUCCESS
)) {
2946 return (DDI_SUCCESS
);
2949 return (DDI_FAILURE
);
2953 scsi_hba_post_event(
2956 ddi_eventcookie_t event
,
2959 scsi_hba_tran_t
*tran
;
2961 tran
= ddi_get_driver_private(self
);
2962 if (tran
->tran_post_event
&&
2963 ((*tran
->tran_post_event
)(self
,
2964 child
, event
, bus_impldata
) == DDI_SUCCESS
)) {
2965 return (DDI_SUCCESS
);
2968 return (DDI_FAILURE
);
2972 * Default getinfo(9e) for scsi_hba
2976 scsi_hba_info(dev_info_t
*self
, ddi_info_cmd_t infocmd
, void *arg
,
2979 int error
= DDI_SUCCESS
;
2982 case DDI_INFO_DEVT2INSTANCE
:
2983 *result
= (void *)(intptr_t)(MINOR2INST(getminor((dev_t
)arg
)));
2986 error
= DDI_FAILURE
;
2992 * Default open and close routine for scsi_hba
2996 scsi_hba_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
2999 scsi_hba_tran_t
*tran
;
3002 if (otyp
!= OTYP_CHR
)
3005 if ((self
= e_ddi_hold_devi_by_dev(*devp
, 0)) == NULL
)
3008 tran
= ddi_get_driver_private(self
);
3010 ddi_release_devi(self
);
3015 * tran_open_flag bit field:
3017 * 1: shared open by minor at bit position
3018 * 1 at 31st bit: exclusive open
3020 mutex_enter(&(tran
->tran_open_lock
));
3021 if (flags
& FEXCL
) {
3022 if (tran
->tran_open_flag
!= 0) {
3023 rv
= EBUSY
; /* already open */
3025 tran
->tran_open_flag
= TRAN_OPEN_EXCL
;
3028 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3029 rv
= EBUSY
; /* already excl. open */
3031 int minor
= getminor(*devp
) & TRAN_MINOR_MASK
;
3032 tran
->tran_open_flag
|= (1 << minor
);
3034 * Ensure that the last framework reserved minor
3035 * is unused. Otherwise, the exclusive open
3036 * mechanism may break.
3038 ASSERT(minor
!= 31);
3041 mutex_exit(&(tran
->tran_open_lock
));
3043 ddi_release_devi(self
);
3049 scsi_hba_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
3052 scsi_hba_tran_t
*tran
;
3054 if (otyp
!= OTYP_CHR
)
3057 if ((self
= e_ddi_hold_devi_by_dev(dev
, 0)) == NULL
)
3060 tran
= ddi_get_driver_private(self
);
3062 ddi_release_devi(self
);
3066 mutex_enter(&(tran
->tran_open_lock
));
3067 if (tran
->tran_open_flag
== TRAN_OPEN_EXCL
) {
3068 tran
->tran_open_flag
= 0;
3070 int minor
= getminor(dev
) & TRAN_MINOR_MASK
;
3071 tran
->tran_open_flag
&= ~(1 << minor
);
3073 mutex_exit(&(tran
->tran_open_lock
));
3075 ddi_release_devi(self
);
3080 * standard ioctl commands for SCSI hotplugging
3084 scsi_hba_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
3088 struct devctl_iocdata
*dcp
= NULL
;
3089 dev_info_t
*child
= NULL
;
3090 mdi_pathinfo_t
*path
= NULL
;
3091 struct scsi_device
*sd
;
3092 scsi_hba_tran_t
*tran
;
3099 self
= e_ddi_hold_devi_by_dev(dev
, 0);
3105 tran
= ddi_get_driver_private(self
);
3111 /* Ioctls for which the generic implementation suffices. */
3113 case DEVCTL_BUS_GETSTATE
:
3114 rv
= ndi_devctl_ioctl(self
, cmd
, arg
, mode
, 0);
3118 /* read devctl ioctl data */
3119 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
) {
3124 /* Ioctls that require child identification */
3126 case DEVCTL_DEVICE_GETSTATE
:
3127 case DEVCTL_DEVICE_ONLINE
:
3128 case DEVCTL_DEVICE_OFFLINE
:
3129 case DEVCTL_DEVICE_REMOVE
:
3130 case DEVCTL_DEVICE_RESET
:
3131 name
= ndi_dc_getname(dcp
);
3132 addr
= ndi_dc_getaddr(dcp
);
3133 if ((name
== NULL
) || (addr
== NULL
)) {
3139 * Find child with name@addr - might find a devinfo
3140 * child (child), a pathinfo child (path), or nothing.
3142 scsi_hba_devi_enter(self
, &circ
);
3144 (void) scsi_findchild(self
, name
, addr
, 1, &child
, &path
, NULL
);
3146 /* Found a pathinfo */
3147 ASSERT(path
&& (child
== NULL
));
3148 mdi_hold_path(path
);
3149 scsi_hba_devi_exit_phci(self
, circ
);
3152 /* Found a devinfo */
3153 ASSERT(child
&& (path
== NULL
));
3155 /* verify scsi_device of child */
3156 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3157 sd
= ddi_get_driver_private(child
);
3161 ASSERT((path
== NULL
) && (child
== NULL
));
3162 scsi_hba_devi_exit(self
, circ
);
3163 rv
= ENXIO
; /* found nothing */
3168 case DEVCTL_BUS_RESETALL
: /* ioctl that operate on any child */
3170 * Find a child's scsi_address so we can invoke tran_reset.
3172 * Future: If no child exists, we could fake a child. This will
3173 * be a enhancement for the future - for now, we fall back to
3176 scsi_hba_devi_enter(self
, &circ
);
3177 child
= ddi_get_child(self
);
3180 /* verify scsi_device of child */
3181 if (ndi_flavor_get(child
) == SCSA_FLAVOR_SCSI_DEVICE
)
3182 sd
= ddi_get_driver_private(child
);
3185 * NOTE: node has a scsi_device structure, so
3186 * it must be initialized.
3188 ndi_hold_devi(child
);
3191 child
= ddi_get_next_sibling(child
);
3193 scsi_hba_devi_exit(self
, circ
);
3198 case DEVCTL_DEVICE_GETSTATE
:
3200 if (mdi_dc_return_dev_state(path
, dcp
) != MDI_SUCCESS
)
3203 if (ndi_dc_return_dev_state(child
, dcp
) != NDI_SUCCESS
)
3210 case DEVCTL_DEVICE_RESET
:
3215 if (tran
->tran_reset
== NULL
) {
3220 /* Start with the small stick */
3221 if (scsi_reset(&sd
->sd_address
, RESET_LUN
) == 1)
3222 break; /* LUN reset worked */
3223 if (scsi_reset(&sd
->sd_address
, RESET_TARGET
) != 1)
3224 rv
= EIO
; /* Target reset failed */
3227 case DEVCTL_BUS_QUIESCE
:
3228 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3229 (bus_state
== BUS_QUIESCED
))
3231 else if (tran
->tran_quiesce
== NULL
)
3232 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3233 else if (tran
->tran_quiesce(self
) != 0)
3235 else if (ndi_set_bus_state(self
, BUS_QUIESCED
) != NDI_SUCCESS
)
3239 case DEVCTL_BUS_UNQUIESCE
:
3240 if ((ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
) &&
3241 (bus_state
== BUS_ACTIVE
))
3243 else if (tran
->tran_unquiesce
== NULL
)
3244 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3245 else if (tran
->tran_unquiesce(self
) != 0)
3247 else if (ndi_set_bus_state(self
, BUS_ACTIVE
) != NDI_SUCCESS
)
3251 case DEVCTL_BUS_RESET
:
3252 if (tran
->tran_bus_reset
== NULL
)
3253 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3254 else if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3258 case DEVCTL_BUS_RESETALL
:
3260 (scsi_reset(&sd
->sd_address
, RESET_ALL
) == 1)) {
3261 break; /* reset all worked */
3263 if (tran
->tran_bus_reset
== NULL
) {
3264 rv
= ENOTSUP
; /* man ioctl(7I) says ENOTTY */
3267 if (tran
->tran_bus_reset(self
, RESET_BUS
) != 1)
3268 rv
= EIO
; /* bus reset failed */
3271 case DEVCTL_BUS_CONFIGURE
:
3272 if (ndi_devi_config(self
, NDI_DEVFS_CLEAN
| NDI_DEVI_PERSIST
|
3273 NDI_CONFIG_REPROBE
) != NDI_SUCCESS
) {
3278 case DEVCTL_BUS_UNCONFIGURE
:
3279 if (ndi_devi_unconfig(self
,
3280 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
) {
3285 case DEVCTL_DEVICE_ONLINE
:
3286 ASSERT(child
|| path
);
3288 if (mdi_pi_online(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3291 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
)
3296 case DEVCTL_DEVICE_OFFLINE
:
3297 ASSERT(child
|| path
);
3299 (void) scsi_clear_task_set(&sd
->sd_address
);
3301 if (mdi_pi_offline(path
, NDI_USER_REQ
) != MDI_SUCCESS
)
3304 if (ndi_devi_offline(child
,
3305 NDI_DEVFS_CLEAN
) != NDI_SUCCESS
)
3310 case DEVCTL_DEVICE_REMOVE
:
3311 ASSERT(child
|| path
);
3313 (void) scsi_clear_task_set(&sd
->sd_address
);
3315 /* NOTE: don't pass NDI_DEVI_REMOVE to mdi_pi_offline */
3316 if (mdi_pi_offline(path
, NDI_USER_REQ
) == MDI_SUCCESS
) {
3317 scsi_hba_devi_enter_phci(self
, &circ
);
3318 mdi_rele_path(path
);
3320 /* ... here is the DEVICE_REMOVE part. */
3321 (void) mdi_pi_free(path
, 0);
3327 if (ndi_devi_offline(child
,
3328 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) != NDI_SUCCESS
)
3334 ASSERT(dcp
!= NULL
);
3339 /* all done -- clean up and return */
3341 /* release hold on what we found */
3343 scsi_hba_devi_enter_phci(self
, &circ
);
3344 mdi_rele_path(path
);
3347 scsi_hba_devi_exit(self
, circ
);
3350 ndi_dc_freehdl(dcp
);
3353 ddi_release_devi(self
);
3362 scsi_hba_fm_init_child(dev_info_t
*self
, dev_info_t
*child
, int cap
,
3363 ddi_iblock_cookie_t
*ibc
)
3365 scsi_hba_tran_t
*tran
= ddi_get_driver_private(self
);
3367 return (tran
? tran
->tran_fm_capable
: scsi_fm_capable
);
3371 scsi_hba_bus_power(dev_info_t
*self
, void *impl_arg
, pm_bus_power_op_t op
,
3372 void *arg
, void *result
)
3374 scsi_hba_tran_t
*tran
;
3376 tran
= ddi_get_driver_private(self
);
3377 if (tran
&& tran
->tran_bus_power
) {
3378 return (tran
->tran_bus_power(self
, impl_arg
,
3382 return (pm_busop_bus_power(self
, impl_arg
, op
, arg
, result
));
3386 * Return the lun64 value from a address string: "addr,lun[,sfunc]". Either
3387 * the lun is after the first ',' or the entire address string is the lun.
3388 * Return SCSI_LUN64_ILLEGAL if the format is incorrect. A lun64 is at most
3389 * 16 hex digits long.
3391 * If the address string specified has incorrect syntax (busconfig one of
3392 * bogus /devices path) then scsi_addr_to_lun64 can return SCSI_LUN64_ILLEGAL.
3395 scsi_addr_to_lun64(char *addr
)
3402 s
= strchr(addr
, ','); /* "addr,lun" */
3404 s
++; /* skip ',', at lun */
3406 s
= addr
; /* "lun" */
3408 for (lun64
= 0, i
= 0; *s
&& (i
< 16); s
++, i
++) {
3409 if (*s
>= '0' && *s
<= '9')
3410 lun64
= (lun64
<< 4) + (*s
- '0');
3411 else if (*s
>= 'A' && *s
<= 'F')
3412 lun64
= (lun64
<< 4) + 10 + (*s
- 'A');
3413 else if (*s
>= 'a' && *s
<= 'f')
3414 lun64
= (lun64
<< 4) + 10 + (*s
- 'a');
3418 if (*s
&& (*s
!= ',')) /* [,sfunc] is OK */
3419 lun64
= SCSI_LUN64_ILLEGAL
;
3421 lun64
= SCSI_LUN64_ILLEGAL
;
3423 if (lun64
== SCSI_LUN64_ILLEGAL
)
3424 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
3425 "addr_to_lun64 %s lun %" PRIlun64
,
3426 addr
? addr
: "NULL", lun64
));
3431 * Return the sfunc value from a address string: "addr,lun[,sfunc]". Either the
3432 * sfunc is after the second ',' or the entire address string is the sfunc.
3433 * Return -1 if there is only one ',' in the address string or the string is
3434 * invalid. An sfunc is at most two hex digits long.
3437 scsi_addr_to_sfunc(char *addr
)
3444 s
= strchr(addr
, ','); /* "addr,lun" */
3446 s
++; /* skip ',', at lun */
3447 s
= strchr(s
, ','); /* "lun,sfunc" */
3449 return (-1); /* no ",sfunc" */
3450 s
++; /* skip ',', at sfunc */
3452 s
= addr
; /* "sfunc" */
3454 for (sfunc
= 0, i
= 0; *s
&& (i
< 2); s
++, i
++) {
3455 if (*s
>= '0' && *s
<= '9')
3456 sfunc
= (sfunc
<< 4) + (*s
- '0');
3457 else if (*s
>= 'A' && *s
<= 'F')
3458 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'A');
3459 else if (*s
>= 'a' && *s
<= 'f')
3460 sfunc
= (sfunc
<< 4) + 10 + (*s
- 'a');
3465 sfunc
= -1; /* illegal */
3472 * Convert scsi ascii string data to NULL terminated (semi) legal IEEE 1275
3473 * "compatible" (name) property form.
3475 * For ASCII INQUIRY data, a one-way conversion algorithm is needed to take
3476 * SCSI_ASCII (20h - 7Eh) to a 1275-like compatible form. The 1275 spec allows
3477 * letters, digits, one ",", and ". _ + -", all limited by a maximum 31
3478 * character length. Since ", ." are used as separators in the compatible
3479 * string itself, they are converted to "_". All SCSI_ASCII characters that
3480 * are illegal in 1275, as well as any illegal SCSI_ASCII characters
3481 * encountered, are converted to "_". To reduce length, trailing blanks are
3482 * trimmed from SCSI_ASCII fields prior to conversion.
3484 * Example: SCSI_ASCII "ST32550W SUN2.1G" -> "ST32550W_SUN2_1G"
3486 * NOTE: the 1275 string form is always less than or equal to the scsi form.
3489 string_scsi_to_1275(char *s_1275
, char *s_scsi
, int len
)
3491 (void) strncpy(s_1275
, s_scsi
, len
);
3492 s_1275
[len
--] = '\0';
3495 if (s_1275
[len
] == ' ')
3496 s_1275
[len
--] = '\0'; /* trim trailing " " */
3502 if (((s_1275
[len
] >= 'a') && (s_1275
[len
] <= 'z')) ||
3503 ((s_1275
[len
] >= 'A') && (s_1275
[len
] <= 'Z')) ||
3504 ((s_1275
[len
] >= '0') && (s_1275
[len
] <= '9')) ||
3505 (s_1275
[len
] == '_') ||
3506 (s_1275
[len
] == '+') ||
3507 (s_1275
[len
] == '-'))
3508 len
--; /* legal 1275 */
3510 s_1275
[len
--] = '_'; /* illegal SCSI_ASCII | 1275 */
3517 * Given the inquiry data, binding_set, and dtype_node for a scsi device,
3518 * return the nodename and compatible property for the device. The "compatible"
3519 * concept comes from IEEE-1275. The compatible information is returned is in
3520 * the correct form for direct use defining the "compatible" string array
3521 * property. Internally, "compatible" is also used to determine the nodename
3524 * This function is provided as a separate entry point for use by drivers that
3525 * currently issue their own non-SCSA inquiry command and perform their own
3526 * node creation based their own private compiled in tables. Converting these
3527 * drivers to use this interface provides a quick easy way of obtaining
3528 * consistency as well as the flexibility associated with the 1275 techniques.
3530 * The dtype_node is passed as a separate argument (instead of having the
3531 * implementation use inq_dtype). It indicates that information about
3532 * a secondary function embedded service should be produced.
3534 * Callers must always use scsi_hba_nodename_compatible_free, even if
3535 * *nodenamep is null, to free the nodename and compatible information
3538 * If a nodename can't be determined then **compatiblep will point to a
3539 * diagnostic string containing all the compatible forms.
3541 * NOTE: some compatible strings may violate the 31 character restriction
3542 * imposed by IEEE-1275. This is not a problem because Solaris does not care
3543 * about this 31 character limit.
3545 * Each compatible form belongs to a form-group. The form-groups currently
3546 * defined are generic ("scsiclass"), binding-set ("scsa.b"), and failover
3549 * The following compatible forms, in high to low precedence
3550 * order, are defined for SCSI target device nodes.
3552 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (1 *1&2)
3553 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (2 *1)
3554 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (3 *2)
3555 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR (4)
3556 * scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (5 *1&2)
3557 * scsiclass,DDEE.vVVVVVVVV.pPPPPPPPPPPPPPPPP (6 *1)
3558 * scsiclass,DDFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP (7 *2)
3559 * scsiclass,DD.vVVVVVVVV.pPPPPPPPPPPPPPPPP (8)
3560 * scsa,DD.bBBBBBBBB (8.5 *3)
3561 * scsiclass,DDEEFFF (9 *1&2)
3562 * scsiclass,DDEE (10 *1)
3563 * scsiclass,DDFFF (11 *2)
3565 * scsa.fFFF (12.5 *4)
3568 * *1 only produced on a secondary function node
3569 * *2 only produced when generic form-group flags exist.
3570 * *3 only produced when binding-set form-group legacy support is needed
3571 * *4 only produced when failover form-group flags exist.
3575 * v is the letter 'v'. Denotest the
3576 * beginning of VVVVVVVV.
3578 * VVVVVVVV Translated scsi_vendor.
3580 * p is the letter 'p'. Denotes the
3581 * beginning of PPPPPPPPPPPPPPPP.
3583 * PPPPPPPPPPPPPPPP Translated scsi_product.
3585 * r is the letter 'r'. Denotes the
3586 * beginning of RRRR.
3588 * RRRR Translated scsi_revision.
3590 * DD is a two digit ASCII hexadecimal
3591 * number. The value of the two digits is
3592 * based one the SCSI "Peripheral device
3593 * type" command set associated with the
3594 * node. On a primary node this is the
3595 * scsi_dtype of the primary command set,
3596 * on a secondary node this is the
3597 * scsi_dtype associated with the secondary
3598 * function embedded command set.
3600 * EE Same encoding used for DD. This form is
3601 * only generated on secondary function
3602 * nodes. The DD secondary function is embedded
3605 * FFF Concatenation, in alphabetical order,
3606 * of the flag characters within a form-group.
3607 * For a given form-group, the following
3608 * flags are defined.
3610 * scsiclass: (generic form-group):
3611 * R Removable_Media: Used when
3613 * S SAF-TE device: Used when
3614 * inquiry information indicates
3617 * scsa.f: (failover form-group):
3618 * E Explicit Target_Port_Group: Used
3619 * when inq_tpgse is set and 'G' is
3621 * G GUID: Used when a GUID can be
3622 * generated for the device.
3623 * I Implicit Target_Port_Group: Used
3624 * when inq_tpgs is set and 'G' is
3627 * Forms using FFF are only be generated
3628 * if there are applicable flag
3631 * b is the letter 'b'. Denotes the
3632 * beginning of BBBBBBBB.
3634 * BBBBBBBB Binding-set. Operating System Specific:
3635 * scsi-binding-set property of HBA.
3637 #define NCOMPAT (1 + (13 + 2) + 1)
3638 #define COMPAT_LONGEST (strlen( \
3639 "scsiclass,DDEEFFF.vVVVVVVVV.pPPPPPPPPPPPPPPPP.rRRRR" + 1))
3642 * Private version with extra device 'identity' arguments to allow code
3643 * to determine GUID FFF support.
3646 scsi_hba_ident_nodename_compatible_get(struct scsi_inquiry
*inq
,
3647 uchar_t
*inq80
, size_t inq80len
, uchar_t
*inq83
, size_t inq83len
,
3648 char *binding_set
, int dtype_node
, char *compat0
,
3649 char **nodenamep
, char **drivernamep
,
3650 char ***compatiblep
, int *ncompatiblep
)
3652 char vid
[sizeof (inq
->inq_vid
) + 1 ];
3653 char pid
[sizeof (inq
->inq_pid
) + 1];
3654 char rev
[sizeof (inq
->inq_revision
) + 1];
3655 char gf
[sizeof ("RS\0")];
3656 char ff
[sizeof ("EGI\0")];
3658 int ncompat
; /* number of compatible */
3659 char **compatp
; /* compatible ptrs */
3661 char *nname
; /* nodename */
3662 char *dname
; /* driver name */
3670 uchar_t
*iqd
= (uchar_t
*)inq
;
3673 * Nodename_aliases: This table was originally designed to be
3674 * implemented via a new nodename_aliases file - a peer to the
3675 * driver_aliases that selects a nodename based on compatible
3676 * forms in much the same say driver_aliases is used to select
3677 * driver bindings from compatible forms. Each compatible form
3678 * is an 'alias'. Until a more general need for a
3679 * nodename_aliases file exists, which may never occur, the
3680 * scsi mappings are described here via a compiled in table.
3682 * This table contains nodename mappings for self-identifying
3683 * scsi devices enumerated by the Solaris kernel. For a given
3684 * device, the highest precedence "compatible" form with a
3685 * mapping is used to select the nodename for the device. This
3686 * will typically be a generic nodename, however in some legacy
3687 * compatibility cases a driver nodename mapping may be selected.
3689 * Because of possible breakage associated with switching SCSI
3690 * target devices from driver nodenames to generic nodenames,
3691 * we are currently unable to support generic nodenames for all
3692 * SCSI devices (binding-sets). Although /devices paths are
3693 * defined as unstable, avoiding possible breakage is
3694 * important. Some of the newer SCSI transports (USB) already
3695 * use generic nodenames. All new SCSI transports and target
3696 * devices should use generic nodenames. At times this decision
3697 * may be architecture dependent (sparc .vs. intel) based on when
3698 * a transport was supported on a particular architecture.
3700 * We provide a base set of generic nodename mappings based on
3701 * scsiclass dtype and higher-precedence driver nodename
3702 * mappings based on scsa "binding-set" to cover legacy
3703 * issues. The binding-set is typically associated with
3704 * "scsi-binding-set" property value of the HBA. The legacy
3705 * mappings are provided independent of whether the driver they
3706 * refer to is installed. This allows a correctly named node
3707 * be created at discovery time, and binding to occur when/if
3708 * an add_drv of the legacy driver occurs.
3710 * We also have mappings for legacy SUN hardware that
3711 * misidentifies itself (enclosure services which identify
3712 * themselves as processors). All future hardware should use
3713 * the correct dtype.
3715 * As SCSI HBAs are modified to use the SCSA interfaces for
3716 * self-identifying SCSI target devices (PSARC/2004/116) the
3717 * nodename_aliases table (PSARC/2004/420) should be augmented
3718 * with legacy mappings in order to maintain compatibility with
3719 * existing /devices paths, especially for devices that house
3720 * an OS. Failure to do this may cause upgrade problems.
3721 * Additions for new target devices or transports should not
3722 * add scsa binding-set compatible mappings.
3724 static struct nodename_aliases
{
3725 char *na_nodename
; /* nodename */
3726 char *na_alias
; /* compatible form match */
3728 /* # mapping to generic nodenames based on scsi dtype */
3729 {"disk", "scsiclass,00"},
3730 {"tape", "scsiclass,01"},
3731 {"printer", "scsiclass,02"},
3732 {"processor", "scsiclass,03"},
3733 {"worm", "scsiclass,04"},
3734 {"cdrom", "scsiclass,05"},
3735 {"scanner", "scsiclass,06"},
3736 {"optical-disk", "scsiclass,07"},
3737 {"medium-changer", "scsiclass,08"},
3738 {"obsolete", "scsiclass,09"},
3739 {"prepress-a", "scsiclass,0a"},
3740 {"prepress-b", "scsiclass,0b"},
3741 {"array-controller", "scsiclass,0c"},
3742 {"enclosure", "scsiclass,0d"},
3743 {"disk", "scsiclass,0e"},
3744 {"card-reader", "scsiclass,0f"},
3745 {"bridge", "scsiclass,10"},
3746 {"object-store", "scsiclass,11"},
3747 {"reserved", "scsiclass,12"},
3748 {"reserved", "scsiclass,13"},
3749 {"reserved", "scsiclass,14"},
3750 {"reserved", "scsiclass,15"},
3751 {"reserved", "scsiclass,16"},
3752 {"reserved", "scsiclass,17"},
3753 {"reserved", "scsiclass,18"},
3754 {"reserved", "scsiclass,19"},
3755 {"reserved", "scsiclass,1a"},
3756 {"reserved", "scsiclass,1b"},
3757 {"reserved", "scsiclass,1c"},
3758 {"reserved", "scsiclass,1d"},
3759 {"well-known-lun", "scsiclass,1e"},
3760 {"unknown", "scsiclass,1f"},
3763 /* # legacy mapping to driver nodenames for fcp binding-set */
3764 {"ssd", "scsa,00.bfcp"},
3765 {"st", "scsa,01.bfcp"},
3766 {"sgen", "scsa,08.bfcp"},
3767 {"ses", "scsa,0d.bfcp"},
3769 /* # legacy mapping to driver nodenames for vhci binding-set */
3770 {"ssd", "scsa,00.bvhci"},
3771 {"st", "scsa,01.bvhci"},
3772 {"sgen", "scsa,08.bvhci"},
3773 {"ses", "scsa,0d.bvhci"},
3775 /* # for x86 fcp and vhci use generic nodenames */
3778 /* # legacy mapping to driver nodenames for spi binding-set */
3779 {"sd", "scsa,00.bspi"},
3780 {"sd", "scsa,05.bspi"},
3781 {"sd", "scsa,07.bspi"},
3782 {"st", "scsa,01.bspi"},
3783 {"ses", "scsa,0d.bspi"},
3785 /* # SUN misidentified spi hardware */
3786 {"ses", "scsiclass,03.vSUN.pD2"},
3787 {"ses", "scsiclass,03.vSYMBIOS.pD1000"},
3789 /* # legacy mapping to driver nodenames for atapi binding-set */
3790 {"sd", "scsa,00.batapi"},
3791 {"sd", "scsa,05.batapi"},
3792 {"sd", "scsa,07.batapi"},
3793 {"st", "scsa,01.batapi"},
3794 {"unknown", "scsa,0d.batapi"},
3796 /* # legacy mapping to generic nodenames for usb binding-set */
3797 {"disk", "scsa,05.busb"},
3798 {"disk", "scsa,07.busb"},
3799 {"changer", "scsa,08.busb"},
3800 {"comm", "scsa,09.busb"},
3801 {"array_ctlr", "scsa,0c.busb"},
3802 {"esi", "scsa,0d.busb"},
3805 * mapping nodenames for mpt based on scsi dtype
3806 * for being compatible with the original node names
3807 * under mpt controller
3809 {"sd", "scsa,00.bmpt"},
3810 {"sd", "scsa,05.bmpt"},
3811 {"sd", "scsa,07.bmpt"},
3812 {"st", "scsa,01.bmpt"},
3813 {"ses", "scsa,0d.bmpt"},
3814 {"sgen", "scsa,08.bmpt"},
3817 struct nodename_aliases
*nap
;
3819 /* NOTE: drivernamep can be NULL */
3820 ASSERT(nodenamep
&& compatiblep
&& ncompatiblep
&&
3821 (binding_set
== NULL
|| (strlen(binding_set
) <= 8)));
3822 if ((nodenamep
== NULL
) || (compatiblep
== NULL
) ||
3823 (ncompatiblep
== NULL
))
3827 * In order to reduce runtime we allocate one block of memory that
3828 * contains both the NULL terminated array of pointers to compatible
3829 * forms and the individual compatible strings. This block is
3830 * somewhat larger than needed, but is short lived - it only exists
3831 * until the caller can transfer the information into the "compatible"
3832 * string array property and call scsi_hba_nodename_compatible_free.
3834 tlen
= NCOMPAT
* COMPAT_LONGEST
;
3835 compatp
= kmem_alloc((NCOMPAT
* sizeof (char *)) + tlen
, KM_SLEEP
);
3837 /* convert inquiry data from SCSI ASCII to 1275 string */
3838 (void) string_scsi_to_1275(vid
, inq
->inq_vid
,
3839 sizeof (inq
->inq_vid
));
3840 (void) string_scsi_to_1275(pid
, inq
->inq_pid
,
3841 sizeof (inq
->inq_pid
));
3842 (void) string_scsi_to_1275(rev
, inq
->inq_revision
,
3843 sizeof (inq
->inq_revision
));
3844 ASSERT((strlen(vid
) <= sizeof (inq
->inq_vid
)) &&
3845 (strlen(pid
) <= sizeof (inq
->inq_pid
)) &&
3846 (strlen(rev
) <= sizeof (inq
->inq_revision
)));
3849 * Form flags in ***ALPHABETICAL*** order within form-group:
3851 * NOTE: When adding a new flag to an existing form-group, careful
3852 * consideration must be given to not breaking existing bindings
3853 * based on that form-group.
3857 * generic form-group flags
3859 * Set when inq_rmb is set and for well known scsi dtypes. For a
3860 * bus where the entire device is removable (like USB), we expect
3861 * the HBA to intercept the inquiry data and set inq_rmb.
3862 * Since OBP does not distinguish removable media in its generic
3863 * name selection we avoid setting the 'R' flag if the root is not
3866 * Set when the device type is SAT-TE.
3869 dtype_device
= inq
->inq_dtype
& DTYPE_MASK
;
3870 if (modrootloaded
&& (inq
->inq_rmb
||
3871 (dtype_device
== DTYPE_WORM
) ||
3872 (dtype_device
== DTYPE_RODIRECT
) ||
3873 (dtype_device
== DTYPE_OPTICAL
)))
3874 gf
[i
++] = 'R'; /* removable */
3877 if (modrootloaded
&&
3878 (dtype_device
== DTYPE_PROCESSOR
) &&
3879 (strncmp((char *)&iqd
[44], "SAF-TE", 4) == 0))
3884 * failover form-group flags
3885 * E Explicit Target_Port_Group_Supported:
3886 * Set for a device that has a GUID if inq_tpgse also set.
3888 * Set when we have identity information, can determine a devid
3889 * from the identity information, and can generate a guid from
3891 * I Implicit Target_Port_Group_Supported:
3892 * Set for a device that has a GUID if inq_tpgs also set.
3895 if ((inq80
|| inq83
) &&
3896 (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, NULL
,
3897 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
3898 &devid
) == DDI_SUCCESS
)) {
3899 guid
= ddi_devid_to_guid(devid
);
3900 ddi_devid_free(devid
);
3903 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_EXPLICIT
))
3904 ff
[i
++] = 'E'; /* EXPLICIT TPGS */
3906 ff
[i
++] = 'G'; /* GUID */
3907 if (guid
&& (inq
->inq_tpgs
& TPGS_FAILOVER_IMPLICIT
))
3908 ff
[i
++] = 'I'; /* IMPLICIT TPGS */
3911 ddi_devid_free_guid(guid
);
3914 * Construct all applicable compatible forms. See comment at the
3915 * head of the function for a description of the compatible forms.
3918 p
= (char *)(compatp
+ NCOMPAT
);
3920 /* ( 0) driver (optional, not documented in scsi(4)) */
3923 (void) snprintf(p
, tlen
, "%s", compat0
);
3924 len
= strlen(p
) + 1;
3929 /* ( 1) scsiclass,DDEEFFF.vV.pP.rR */
3930 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
&& *rev
) {
3932 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s.r%s",
3933 dtype_node
, dtype_device
, gf
, vid
, pid
, rev
);
3934 len
= strlen(p
) + 1;
3939 /* ( 2) scsiclass,DDEE.vV.pP.rR */
3940 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
&& *rev
) {
3942 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s.r%s",
3943 dtype_node
, dtype_device
, vid
, pid
, rev
);
3944 len
= strlen(p
) + 1;
3949 /* ( 3) scsiclass,DDFFF.vV.pP.rR */
3950 if (*gf
&& *vid
&& *pid
&& *rev
) {
3952 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s.r%s",
3953 dtype_node
, gf
, vid
, pid
, rev
);
3954 len
= strlen(p
) + 1;
3959 /* ( 4) scsiclass,DD.vV.pP.rR */
3960 if (*vid
&& *pid
&& *rev
) {
3962 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s.r%s",
3963 dtype_node
, vid
, pid
, rev
);
3964 len
= strlen(p
) + 1;
3969 /* ( 5) scsiclass,DDEEFFF.vV.pP */
3970 if ((dtype_device
!= dtype_node
) && *gf
&& *vid
&& *pid
) {
3972 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s.v%s.p%s",
3973 dtype_node
, dtype_device
, gf
, vid
, pid
);
3974 len
= strlen(p
) + 1;
3979 /* ( 6) scsiclass,DDEE.vV.pP */
3980 if ((dtype_device
!= dtype_node
) && *vid
&& *pid
) {
3982 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x.v%s.p%s",
3983 dtype_node
, dtype_device
, vid
, pid
);
3984 len
= strlen(p
) + 1;
3989 /* ( 7) scsiclass,DDFFF.vV.pP */
3990 if (*gf
&& *vid
&& *pid
) {
3992 (void) snprintf(p
, tlen
, "scsiclass,%02x%s.v%s.p%s",
3993 dtype_node
, gf
, vid
, pid
);
3994 len
= strlen(p
) + 1;
3999 /* ( 8) scsiclass,DD.vV.pP */
4002 (void) snprintf(p
, tlen
, "scsiclass,%02x.v%s.p%s",
4003 dtype_node
, vid
, pid
);
4004 len
= strlen(p
) + 1;
4009 /* (8.5) scsa,DD.bB (not documented in scsi(4)) */
4012 (void) snprintf(p
, tlen
, "scsa,%02x.b%s",
4013 dtype_node
, binding_set
);
4014 len
= strlen(p
) + 1;
4019 /* ( 9) scsiclass,DDEEFFF */
4020 if ((dtype_device
!= dtype_node
) && *gf
) {
4022 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x%s",
4023 dtype_node
, dtype_device
, gf
);
4024 len
= strlen(p
) + 1;
4029 /* (10) scsiclass,DDEE */
4030 if (dtype_device
!= dtype_node
) {
4032 (void) snprintf(p
, tlen
, "scsiclass,%02x%02x",
4033 dtype_node
, dtype_device
);
4034 len
= strlen(p
) + 1;
4039 /* (11) scsiclass,DDFFF */
4042 (void) snprintf(p
, tlen
, "scsiclass,%02x%s",
4044 len
= strlen(p
) + 1;
4049 /* (12) scsiclass,DD */
4051 (void) snprintf(p
, tlen
, "scsiclass,%02x", dtype_node
);
4052 len
= strlen(p
) + 1;
4056 /* (12.5) scsa.fFFF */
4059 (void) snprintf(p
, tlen
, "scsa.f%s", ff
);
4060 len
= strlen(p
) + 1;
4065 /* (13) scsiclass */
4067 (void) snprintf(p
, tlen
, "scsiclass");
4068 len
= strlen(p
) + 1;
4073 *csp
= NULL
; /* NULL terminate array of pointers */
4074 ncompat
= csp
- compatp
;
4077 * When determining a nodename, a nodename_aliases specified
4078 * mapping has precedence over using a driver_aliases specified
4079 * driver binding as a nodename.
4081 * See if any of the compatible forms have a nodename_aliases
4082 * specified nodename. These mappings are described by
4083 * nodename_aliases entries like:
4085 * disk "scsiclass,00"
4086 * enclosure "scsiclass,03.vSYMBIOS.pD1000"
4087 * ssd "scsa,00.bfcp"
4089 * All nodename_aliases mappings should idealy be to generic
4090 * names, however a higher precedence legacy mapping to a
4091 * driver name may exist. The highest precedence mapping
4092 * provides the nodename, so legacy driver nodename mappings
4093 * (if they exist) take precedence over generic nodename
4096 for (nname
= NULL
, csp
= compatp
; (nname
== NULL
) && *csp
; csp
++) {
4097 for (nap
= na
; nap
->na_nodename
; nap
++) {
4098 if (strcmp(*csp
, nap
->na_alias
) == 0) {
4099 nname
= nap
->na_nodename
;
4106 * Determine the driver name based on compatible (which may
4107 * have the passed in compat0 as the first item). The driver_aliases
4108 * file has entries like
4112 * that map compatible forms to specific drivers. These entries are
4113 * established by add_drv/update_drv. We use the most specific
4114 * driver binding as the nodename. This matches the eventual
4115 * ddi_driver_compatible_major() binding that will be
4116 * established by bind_node()
4118 for (dname
= NULL
, csp
= compatp
; *csp
; csp
++) {
4119 major
= ddi_name_to_major(*csp
);
4120 if ((major
== DDI_MAJOR_T_NONE
) ||
4121 (devnamesp
[major
].dn_flags
& DN_DRIVER_REMOVED
))
4123 if (dname
= ddi_major_to_name(major
))
4128 * If no nodename_aliases mapping exists then use the
4129 * driver_aliases specified driver binding as a nodename.
4134 /* return results */
4136 *nodenamep
= kmem_alloc(strlen(nname
) + 1, KM_SLEEP
);
4137 (void) strcpy(*nodenamep
, nname
);
4142 * If no nodename could be determined return a special
4143 * 'compatible' to be used for a diagnostic message. This
4144 * compatible contains all compatible forms concatenated
4145 * into a single string pointed to by the first element.
4147 for (csp
= compatp
; *(csp
+ 1); csp
++)
4148 *((*csp
) + strlen(*csp
)) = ' ';
4149 *(compatp
+ 1) = NULL
;
4155 *drivernamep
= kmem_alloc(strlen(dname
) + 1, KM_SLEEP
);
4156 (void) strcpy(*drivernamep
, dname
);
4158 *drivernamep
= NULL
;
4160 *compatiblep
= compatp
;
4161 *ncompatiblep
= ncompat
;
4165 * Free allocations associated with scsi_hba_ident_nodename_compatible_get.
4168 scsi_hba_ident_nodename_compatible_free(char *nodename
, char *drivername
,
4172 kmem_free(nodename
, strlen(nodename
) + 1);
4174 kmem_free(drivername
, strlen(drivername
) + 1);
4176 kmem_free(compatible
, (NCOMPAT
* sizeof (char *)) +
4177 (NCOMPAT
* COMPAT_LONGEST
));
4181 scsi_hba_nodename_compatible_get(struct scsi_inquiry
*inq
,
4182 char *binding_set
, int dtype_node
, char *compat0
,
4183 char **nodenamep
, char ***compatiblep
, int *ncompatiblep
)
4185 scsi_hba_ident_nodename_compatible_get(inq
,
4186 NULL
, 0, NULL
, 0, binding_set
, dtype_node
, compat0
, nodenamep
,
4187 NULL
, compatiblep
, ncompatiblep
);
4191 scsi_hba_nodename_compatible_free(char *nodename
, char **compatible
)
4193 scsi_hba_ident_nodename_compatible_free(nodename
, NULL
, compatible
);
4196 /* return the unit_address associated with a scsi_device */
4198 scsi_device_unit_address(struct scsi_device
*sd
)
4200 mdi_pathinfo_t
*pip
;
4202 ASSERT(sd
&& sd
->sd_dev
);
4203 if ((sd
== NULL
) || (sd
->sd_dev
== NULL
))
4206 pip
= (mdi_pathinfo_t
*)sd
->sd_pathinfo
;
4208 return (mdi_pi_get_addr(pip
));
4210 return (ddi_get_name_addr(sd
->sd_dev
));
4213 /* scsi_device property interfaces */
4214 #define _TYPE_DEFINED(flags) \
4215 (((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) || \
4216 ((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_DEVICE))
4218 #define _DEVICE_PIP(sd, flags) \
4219 ((((flags & SCSI_DEVICE_PROP_TYPE_MSK) == SCSI_DEVICE_PROP_PATH) && \
4220 sd->sd_pathinfo) ? (mdi_pathinfo_t *)sd->sd_pathinfo : NULL)
4223 scsi_device_prop_get_int(struct scsi_device
*sd
, uint_t flags
,
4224 char *name
, int defval
)
4226 mdi_pathinfo_t
*pip
;
4231 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4232 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4233 !_TYPE_DEFINED(flags
))
4236 pip
= _DEVICE_PIP(sd
, flags
);
4238 rv
= mdi_prop_lookup_int(pip
, name
, &data
);
4239 if (rv
== DDI_PROP_SUCCESS
)
4242 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, sd
->sd_dev
,
4243 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4249 scsi_device_prop_get_int64(struct scsi_device
*sd
, uint_t flags
,
4250 char *name
, int64_t defval
)
4252 mdi_pathinfo_t
*pip
;
4257 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4258 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4259 !_TYPE_DEFINED(flags
))
4262 pip
= _DEVICE_PIP(sd
, flags
);
4264 rv
= mdi_prop_lookup_int64(pip
, name
, &data
);
4265 if (rv
== DDI_PROP_SUCCESS
)
4268 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, sd
->sd_dev
,
4269 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4274 scsi_device_prop_lookup_byte_array(struct scsi_device
*sd
, uint_t flags
,
4275 char *name
, uchar_t
**data
, uint_t
*nelements
)
4277 mdi_pathinfo_t
*pip
;
4280 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4281 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4282 !_TYPE_DEFINED(flags
))
4283 return (DDI_PROP_INVAL_ARG
);
4285 pip
= _DEVICE_PIP(sd
, flags
);
4287 rv
= mdi_prop_lookup_byte_array(pip
, name
, data
, nelements
);
4289 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4290 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4291 name
, data
, nelements
);
4296 scsi_device_prop_lookup_int_array(struct scsi_device
*sd
, uint_t flags
,
4297 char *name
, int **data
, uint_t
*nelements
)
4299 mdi_pathinfo_t
*pip
;
4302 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4303 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4304 !_TYPE_DEFINED(flags
))
4305 return (DDI_PROP_INVAL_ARG
);
4307 pip
= _DEVICE_PIP(sd
, flags
);
4309 rv
= mdi_prop_lookup_int_array(pip
, name
, data
, nelements
);
4311 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4312 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4313 name
, data
, nelements
);
4319 scsi_device_prop_lookup_string(struct scsi_device
*sd
, uint_t flags
,
4320 char *name
, char **data
)
4322 mdi_pathinfo_t
*pip
;
4325 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4326 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4327 !_TYPE_DEFINED(flags
))
4328 return (DDI_PROP_INVAL_ARG
);
4330 pip
= _DEVICE_PIP(sd
, flags
);
4332 rv
= mdi_prop_lookup_string(pip
, name
, data
);
4334 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, sd
->sd_dev
,
4335 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4341 scsi_device_prop_lookup_string_array(struct scsi_device
*sd
, uint_t flags
,
4342 char *name
, char ***data
, uint_t
*nelements
)
4344 mdi_pathinfo_t
*pip
;
4347 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4348 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4349 !_TYPE_DEFINED(flags
))
4350 return (DDI_PROP_INVAL_ARG
);
4352 pip
= _DEVICE_PIP(sd
, flags
);
4354 rv
= mdi_prop_lookup_string_array(pip
, name
, data
, nelements
);
4356 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, sd
->sd_dev
,
4357 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4358 name
, data
, nelements
);
4363 scsi_device_prop_update_byte_array(struct scsi_device
*sd
, uint_t flags
,
4364 char *name
, uchar_t
*data
, uint_t nelements
)
4366 mdi_pathinfo_t
*pip
;
4369 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4370 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4371 !_TYPE_DEFINED(flags
))
4372 return (DDI_PROP_INVAL_ARG
);
4374 pip
= _DEVICE_PIP(sd
, flags
);
4376 rv
= mdi_prop_update_byte_array(pip
, name
, data
, nelements
);
4378 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4379 name
, data
, nelements
);
4384 scsi_device_prop_update_int(struct scsi_device
*sd
, uint_t flags
,
4385 char *name
, int data
)
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_int(pip
, name
, data
);
4399 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, sd
->sd_dev
,
4405 scsi_device_prop_update_int64(struct scsi_device
*sd
, uint_t flags
,
4406 char *name
, int64_t 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_int64(pip
, name
, data
);
4420 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, sd
->sd_dev
,
4426 scsi_device_prop_update_int_array(struct scsi_device
*sd
, uint_t flags
,
4427 char *name
, int *data
, uint_t nelements
)
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_int_array(pip
, name
, data
, nelements
);
4441 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4442 name
, data
, nelements
);
4447 scsi_device_prop_update_string(struct scsi_device
*sd
, uint_t flags
,
4448 char *name
, char *data
)
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_string(pip
, name
, data
);
4462 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, sd
->sd_dev
,
4468 scsi_device_prop_update_string_array(struct scsi_device
*sd
, uint_t flags
,
4469 char *name
, char **data
, uint_t nelements
)
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_array(pip
, name
, data
, nelements
);
4483 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, sd
->sd_dev
,
4484 name
, data
, nelements
);
4489 scsi_device_prop_remove(struct scsi_device
*sd
, uint_t flags
, char *name
)
4491 mdi_pathinfo_t
*pip
;
4494 ASSERT(sd
&& name
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4495 if ((sd
== NULL
) || (name
== NULL
) || (sd
->sd_dev
== NULL
) ||
4496 !_TYPE_DEFINED(flags
))
4497 return (DDI_PROP_INVAL_ARG
);
4499 pip
= _DEVICE_PIP(sd
, flags
);
4501 rv
= mdi_prop_remove(pip
, name
);
4503 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, sd
->sd_dev
, name
);
4508 scsi_device_prop_free(struct scsi_device
*sd
, uint_t flags
, void *data
)
4510 mdi_pathinfo_t
*pip
;
4512 ASSERT(sd
&& data
&& sd
->sd_dev
&& _TYPE_DEFINED(flags
));
4513 if ((sd
== NULL
) || (data
== NULL
) || (sd
->sd_dev
== NULL
) ||
4514 !_TYPE_DEFINED(flags
))
4517 pip
= _DEVICE_PIP(sd
, flags
);
4519 (void) mdi_prop_free(data
);
4521 ddi_prop_free(data
);
4524 /* SMP device property interfaces */
4526 smp_device_prop_get_int(struct smp_device
*smp_sd
, char *name
, int defval
)
4530 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4531 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4534 v
= ddi_prop_get_int(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4535 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4541 smp_device_prop_get_int64(struct smp_device
*smp_sd
, char *name
, int64_t defval
)
4545 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4546 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4549 v
= ddi_prop_get_int64(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4550 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, name
, v
);
4555 smp_device_prop_lookup_byte_array(struct smp_device
*smp_sd
, char *name
,
4556 uchar_t
**data
, uint_t
*nelements
)
4560 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4561 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4562 return (DDI_PROP_INVAL_ARG
);
4564 rv
= ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4565 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4566 name
, data
, nelements
);
4571 smp_device_prop_lookup_int_array(struct smp_device
*smp_sd
, char *name
,
4572 int **data
, uint_t
*nelements
)
4576 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4577 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4578 return (DDI_PROP_INVAL_ARG
);
4580 rv
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4581 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4582 name
, data
, nelements
);
4588 smp_device_prop_lookup_string(struct smp_device
*smp_sd
, char *name
,
4593 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4594 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4595 return (DDI_PROP_INVAL_ARG
);
4597 rv
= ddi_prop_lookup_string(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4598 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4604 smp_device_prop_lookup_string_array(struct smp_device
*smp_sd
, char *name
,
4605 char ***data
, uint_t
*nelements
)
4609 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4610 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4611 return (DDI_PROP_INVAL_ARG
);
4613 rv
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, smp_sd
->smp_sd_dev
,
4614 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
4615 name
, data
, nelements
);
4620 smp_device_prop_update_byte_array(struct smp_device
*smp_sd
, char *name
,
4621 uchar_t
*data
, uint_t nelements
)
4625 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4626 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4627 return (DDI_PROP_INVAL_ARG
);
4629 rv
= ndi_prop_update_byte_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4630 name
, data
, nelements
);
4635 smp_device_prop_update_int(struct smp_device
*smp_sd
, char *name
, int data
)
4639 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4640 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4641 return (DDI_PROP_INVAL_ARG
);
4643 rv
= ndi_prop_update_int(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4649 smp_device_prop_update_int64(struct smp_device
*smp_sd
, char *name
,
4654 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4655 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4656 return (DDI_PROP_INVAL_ARG
);
4658 rv
= ndi_prop_update_int64(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4664 smp_device_prop_update_int_array(struct smp_device
*smp_sd
, char *name
,
4665 int *data
, uint_t nelements
)
4669 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4670 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4671 return (DDI_PROP_INVAL_ARG
);
4673 rv
= ndi_prop_update_int_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4674 name
, data
, nelements
);
4679 smp_device_prop_update_string(struct smp_device
*smp_sd
, char *name
, char *data
)
4683 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4684 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4685 return (DDI_PROP_INVAL_ARG
);
4687 rv
= ndi_prop_update_string(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4693 smp_device_prop_update_string_array(struct smp_device
*smp_sd
, char *name
,
4694 char **data
, uint_t nelements
)
4698 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4699 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4700 return (DDI_PROP_INVAL_ARG
);
4702 rv
= ndi_prop_update_string_array(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
,
4703 name
, data
, nelements
);
4708 smp_device_prop_remove(struct smp_device
*smp_sd
, char *name
)
4712 ASSERT(smp_sd
&& name
&& smp_sd
->smp_sd_dev
);
4713 if ((smp_sd
== NULL
) || (name
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4714 return (DDI_PROP_INVAL_ARG
);
4716 rv
= ndi_prop_remove(DDI_DEV_T_NONE
, smp_sd
->smp_sd_dev
, name
);
4721 smp_device_prop_free(struct smp_device
*smp_sd
, void *data
)
4723 ASSERT(smp_sd
&& data
&& smp_sd
->smp_sd_dev
);
4724 if ((smp_sd
== NULL
) || (data
== NULL
) || (smp_sd
->smp_sd_dev
== NULL
))
4727 ddi_prop_free(data
);
4731 * scsi_hba_ua_set: given "unit-address" string, set properties.
4733 * Function to set the properties on a devinfo or pathinfo node from
4734 * the "unit-address" part of a "name@unit-address" /devices path 'name'
4737 * This function works in conjunction with scsi_ua_get()/scsi_hba_ua_get()
4738 * (and possibly with an HBA driver's tran_tgt_init() implementation).
4741 scsi_hba_ua_set(char *ua
, dev_info_t
*dchild
, mdi_pathinfo_t
*pchild
)
4751 /* Caller must choose to decorate devinfo *or* pathinfo */
4752 ASSERT((dchild
!= NULL
) ^ (pchild
!= NULL
));
4753 if (dchild
&& pchild
)
4757 * generic implementation based on "tgt,lun[,sfunc]" address form.
4758 * parse hex "tgt" part of "tgt,lun[,sfunc]"
4761 tgt_port_end
= NULL
;
4762 for (tgt
= 0; *p
&& *p
!= ','; p
++) {
4763 if (*p
>= '0' && *p
<= '9')
4764 tgt
= (tgt
<< 4) + (*p
- '0');
4765 else if (*p
>= 'a' && *p
<= 'f')
4766 tgt
= (tgt
<< 4) + 10 + (*p
- 'a');
4768 tgt
= -1; /* non-numeric */
4771 * if non-numeric or our of range set tgt to -1 and
4776 for (; *p
&& *p
!= ','; p
++)
4783 /* parse hex ",lun" part of "tgt,lun[,sfunc]" */
4786 for (lun64
= 0; *p
&& *p
!= ','; p
++) {
4787 if (*p
>= '0' && *p
<= '9')
4788 lun64
= (lun64
<< 4) + (*p
- '0');
4789 else if (*p
>= 'a' && *p
<= 'f')
4790 lun64
= (lun64
<< 4) + 10 + (*p
- 'a');
4795 /* parse hex ",sfunc" part of "tgt,lun[,sfunc]" */
4798 for (sfunc
= 0; *p
; p
++) {
4799 if (*p
>= '0' && *p
<= '9')
4800 sfunc
= (sfunc
<< 4) + (*p
- '0');
4801 else if (*p
>= 'a' && *p
<= 'f')
4802 sfunc
= (sfunc
<< 4) + 10 + (*p
- 'a');
4811 * Decorate a devinfo node with unit address properties.
4812 * This adds the the addressing properties needed to
4813 * DDI_CTLOPS_UNINITCHILD the devinfo node (i.e. perform
4814 * the reverse operation - form unit address from properties).
4816 if ((tgt
!= -1) && (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4817 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4821 tgt_port_len
= tgt_port_end
- ua
+ 1;
4822 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4823 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4824 if (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
4825 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4827 kmem_free(tgt_port
, tgt_port_len
);
4830 kmem_free(tgt_port
, tgt_port_len
);
4833 /* Set the appropriate lun properties. */
4834 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4835 if (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4836 SCSI_ADDR_PROP_LUN
, (int)lun64
) != DDI_PROP_SUCCESS
)
4839 if (ndi_prop_update_int64(DDI_DEV_T_NONE
, dchild
,
4840 SCSI_ADDR_PROP_LUN64
, lun64
) != DDI_PROP_SUCCESS
)
4843 /* Set the sfunc property */
4844 if ((sfunc
!= -1) &&
4845 (ndi_prop_update_int(DDI_DEV_T_NONE
, dchild
,
4846 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4848 } else if (pchild
) {
4850 * Decorate a pathinfo node with unit address properties.
4852 if ((tgt
!= -1) && (mdi_prop_update_int(pchild
,
4853 SCSI_ADDR_PROP_TARGET
, tgt
) != DDI_PROP_SUCCESS
))
4857 tgt_port_len
= tgt_port_end
- ua
+ 1;
4858 tgt_port
= kmem_alloc(tgt_port_len
, KM_SLEEP
);
4859 (void) strlcpy(tgt_port
, ua
, tgt_port_len
);
4860 if (mdi_prop_update_string(pchild
,
4861 SCSI_ADDR_PROP_TARGET_PORT
, tgt_port
) !=
4863 kmem_free(tgt_port
, tgt_port_len
);
4866 kmem_free(tgt_port
, tgt_port_len
);
4869 /* Set the appropriate lun properties */
4870 if (lun64
< SCSI_32LUNS_PER_TARGET
) {
4871 if (mdi_prop_update_int(pchild
, SCSI_ADDR_PROP_LUN
,
4872 (int)lun64
) != DDI_PROP_SUCCESS
)
4876 if (mdi_prop_update_int64(pchild
, SCSI_ADDR_PROP_LUN64
,
4877 lun64
) != DDI_PROP_SUCCESS
)
4880 /* Set the sfunc property */
4881 if ((sfunc
!= -1) &&
4882 (mdi_prop_update_int(pchild
,
4883 SCSI_ADDR_PROP_SFUNC
, (int)sfunc
) != DDI_PROP_SUCCESS
))
4890 * Private ndi_devi_find/mdi_pi_find implementation - find the child
4891 * dev_info/path_info of self whose phci name matches "name@caddr".
4892 * We have our own implementation because we need to search with both
4893 * forms of sibling lists (dev_info and path_info) and we need to be able
4894 * to search with a NULL name in order to find siblings already associated
4895 * with a given unit-address (same @addr). NOTE: NULL name search will never
4896 * return probe node.
4898 * If pchildp is NULL and we find a pathinfo child, we return the client
4899 * devinfo node in *dchildp.
4901 * The init flag argument should be clear when called from places where
4902 * recursion could occur (like scsi_busctl_initchild) and when the caller
4903 * has already performed a search for name@addr with init set (performance).
4905 * Future: Integrate ndi_devi_findchild_by_callback into scsi_findchild.
4908 scsi_findchild(dev_info_t
*self
, char *name
, char *addr
, int init
,
4909 dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
, int *ppi
)
4911 dev_info_t
*dchild
; /* devinfo child */
4912 mdi_pathinfo_t
*pchild
; /* pathinfo child */
4913 int found
= CHILD_TYPE_NONE
;
4916 ASSERT(self
&& DEVI_BUSY_OWNED(self
));
4917 ASSERT(addr
&& dchildp
);
4918 if ((self
== NULL
) || (addr
== NULL
) || (dchildp
== NULL
))
4919 return (CHILD_TYPE_NONE
);
4927 /* Walk devinfo child list to find a match */
4928 for (dchild
= ddi_get_child(self
); dchild
;
4929 dchild
= ddi_get_next_sibling(dchild
)) {
4930 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
4933 daddr
= ddi_get_name_addr(dchild
);
4934 if (daddr
&& (strcmp(addr
, daddr
) == 0) &&
4936 (strcmp(name
, DEVI(dchild
)->devi_node_name
) == 0))) {
4938 * If we are asked to find "anything" at a given
4939 * unit-address (name == NULL), we don't realy want
4940 * to find the 'probe' node. The existance of
4941 * a probe node on a 'name == NULL' search should
4942 * fail. This will trigger slow-path code where
4943 * we explicity look for, and synchronize against,
4944 * a node named "probe" at the unit-address.
4946 if ((name
== NULL
) &&
4947 scsi_hba_devi_is_barrier(dchild
)) {
4948 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4949 "%s@%s 'probe' devinfo found, skip",
4950 name
? name
: "", addr
));
4954 /* We have found a match. */
4955 found
|= CHILD_TYPE_DEVINFO
;
4956 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4957 "%s@%s devinfo found", name
? name
: "", addr
));
4958 *dchildp
= dchild
; /* devinfo found */
4964 * Walk pathinfo child list to find a match.
4966 * NOTE: Unlike devinfo nodes, pathinfo nodes have a string searchable
4967 * unit-address from creation - so there is no need for an 'init'
4968 * search block of code for pathinfo nodes below.
4970 pchild
= mdi_pi_find(self
, NULL
, addr
);
4973 * NOTE: If name specified and we match a pathinfo unit
4974 * address, we don't check the client node name.
4977 *ppi
= mdi_pi_get_path_instance(pchild
);
4978 found
|= CHILD_TYPE_PATHINFO
;
4981 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
4982 "%s pathinfo found", mdi_pi_spathname(pchild
)));
4983 *pchildp
= pchild
; /* pathinfo found */
4984 } else if (*dchildp
== NULL
) {
4986 * Did not find a devinfo node, found a pathinfo node,
4987 * but caller did not ask us to return a pathinfo node:
4988 * we return the 'client' devinfo node instead (but
4989 * with CHILD_TYPE_PATHINFO 'found' return value).
4991 dchild
= mdi_pi_get_client(pchild
);
4992 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
4993 "%s pathinfo found, client switch",
4994 mdi_pi_spathname(pchild
)));
4997 * A pathinfo node always has a 'client' devinfo node,
4998 * but we need to ensure that the 'client' is
4999 * initialized and has a scsi_device structure too.
5002 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
) {
5003 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5004 "%s found client, initchild",
5005 mdi_pi_spathname(pchild
)));
5006 (void) ddi_initchild(ddi_get_parent(dchild
),
5009 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
) {
5010 /* client found and initialized */
5013 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5014 "%s found client, but failed initchild",
5015 mdi_pi_spathname(pchild
)));
5020 /* Try devinfo again with initchild of uninitialized nodes */
5021 if ((found
== CHILD_TYPE_NONE
) && init
) {
5022 for (dchild
= ddi_get_child(self
); dchild
;
5023 dchild
= ddi_get_next_sibling(dchild
)) {
5024 /* skip if checked above */
5025 if (i_ddi_node_state(dchild
) >= DS_INITIALIZED
)
5027 /* attempt initchild to establish unit-address */
5028 (void) ddi_initchild(self
, dchild
);
5029 if (i_ddi_node_state(dchild
) < DS_INITIALIZED
)
5031 daddr
= ddi_get_name_addr(dchild
);
5033 ((name
== NULL
) || (strcmp(name
,
5034 DEVI(dchild
)->devi_node_name
) == 0)) &&
5035 (strcmp(addr
, daddr
) == 0)) {
5036 found
|= CHILD_TYPE_DEVINFO
;
5037 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5038 "%s@%s devinfo found post initchild",
5039 name
? name
: "", addr
));
5040 *dchildp
= dchild
; /* devinfo found */
5041 break; /* node found */
5047 * We should never find devinfo and pathinfo at the same
5050 ASSERT(found
!= (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
));
5051 if (found
== (CHILD_TYPE_DEVINFO
| CHILD_TYPE_PATHINFO
)) {
5052 found
= CHILD_TYPE_NONE
;
5060 * Given information about a child device (contained on probe node) construct
5061 * and return a pointer to the dynamic SID devinfo node associated with the
5062 * device. In the creation of this SID node a compatible property for the
5063 * device is formed and used to establish a nodename (via
5064 * /etc/nodename_aliases) and to bind a driver (via /etc/driver_aliases).
5066 * If this routine is called then we got a response from a device and
5067 * obtained the inquiry data from the device. Some inquiry results indicate
5068 * that the specific LUN we addressed does not exist, and we don't want to
5069 * bind a standard target driver to the node we create. Even though the
5070 * specific LUN is not usable, the framework may still want to bind a
5071 * target driver to the device for internal communication with the device -
5072 * an example would be issuing a report_lun to enumerate other LUNs under a
5073 * DPQ_NEVER LUN0. Another example would be wanting to known that the
5074 * DPQ_NEVER LUN0 device exists in BUS_CONFIG_ONE for non-existent LUN
5075 * caching optimizations. To support this we let the caller specify a
5076 * compatible property (or driver). If LUN0 inquiry data indicates that the
5077 * LUN does not exist then we establish compat0 as the highest precedence(0)
5078 * compatible form. If used, this compat0 driver will never be called on to
5079 * issue external commands to the device.
5081 * If no driver binds to the device using driver_alias we establish the driver
5082 * passed in as the node name.
5085 extern int e_devid_cache_pathinfo(mdi_pathinfo_t
*, ddi_devid_t
);
5088 scsi_device_createchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5089 struct scsi_device
*sdprobe
, dev_info_t
**dchildp
, mdi_pathinfo_t
**pchildp
)
5099 char **compat
= NULL
;
5101 dev_info_t
*dchild
= NULL
;
5102 mdi_pathinfo_t
*pchild
= NULL
;
5103 dev_info_t
*probe
= sdprobe
->sd_dev
;
5104 struct scsi_inquiry
*inq
= sdprobe
->sd_inq
;
5105 uchar_t
*inq80
= NULL
;
5106 uchar_t
*inq83
= NULL
;
5107 uint_t inq80len
, inq83len
;
5108 char *binding_set
= NULL
;
5113 int have_cdevid
= 0;
5117 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5118 ASSERT(dchildp
&& pchildp
);
5121 * Determine the lun and whether the lun exists. We may need to create
5122 * a node for LUN0 (with compat0 driver binding) even if the lun does
5123 * not exist - so we can run report_lun to find additional LUNs.
5125 lun64
= scsi_addr_to_lun64(addr
);
5126 dtype
= inq
->inq_dtype
& DTYPE_MASK
; /* device */
5127 dpq
= inq
->inq_dtype
& DPQ_MASK
;
5128 dpq_vu
= inq
->inq_dtype
& DPQ_VUNIQ
? 1 : 0;
5130 dtype_node
= scsi_addr_to_sfunc(addr
); /* secondary function */
5131 if (dtype_node
== -1)
5132 dtype_node
= dtype
; /* node for device */
5134 lunexists
= (dtype
!= dtype_node
) || /* override */
5135 ((dpq_vu
== 0) && (dpq
== DPQ_POSSIBLE
)) || /* ANSII */
5136 (dpq_vu
&& (lun64
== 0)); /* VU LUN0 */
5137 if (dtype
== DTYPE_UNKNOWN
)
5140 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5141 "@%s dtype %x %x dpq_vu %d dpq %x: %d",
5142 addr
, dtype
, dtype_node
, dpq_vu
, dpq
, lunexists
));
5144 /* A non-existent LUN0 uses compatible_nodev. */
5146 compat0
= NULL
; /* compat0 not needed */
5147 } else if (lun64
== 0) {
5148 compat0
= compatible_nodev
;
5149 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5150 "@%s lun 0 with compat0 %s", addr
, compat0
));
5152 goto out
; /* no node created */
5154 /* Obtain identity information from probe node. */
5155 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5156 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-80",
5157 &inq80
, &inq80len
) != DDI_PROP_SUCCESS
)
5159 if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY
, probe
,
5160 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "inquiry-page-83",
5161 &inq83
, &inq83len
) != DDI_PROP_SUCCESS
)
5164 /* Get "scsi-binding-set" property (if there is one). */
5165 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
5166 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
5167 "scsi-binding-set", &binding_set
) == DDI_PROP_SUCCESS
)
5168 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
5169 "binding_set '%s'", binding_set
));
5171 /* determine the node name and compatible information */
5172 scsi_hba_ident_nodename_compatible_get(inq
,
5173 inq80
, inq80len
, inq83
, inq83len
, binding_set
, dtype_node
,
5174 compat0
, &nname
, &dname
, &compat
, &ncompat
);
5176 if (nname
== NULL
) {
5178 * We will not be able to create a node because we could not
5179 * determine a node name. Print out a NODRIVER level warning
5180 * message with the compatible forms for the device. Note that
5181 * there may be a driver.conf node that attaches to the device,
5182 * which is why we only produce this warning message for debug
5185 SCSI_HBA_LOG((_LOG(1), NULL
, self
,
5186 "no node_name for device @%s:\n compatible: %s",
5192 * FUTURE: some day we may want an accurate "compatible" on the probe
5193 * node so that vhci_is_dev_supported() in scsi_vhci could, at
5194 * least in part, determine/configure based on "compatible".
5196 * if (ndi_prop_update_string_array(DDI_DEV_T_NONE, probe,
5197 * "compatible", compat, ncompat) != DDI_PROP_SUCCESS) {
5198 * SCSI_HBA_LOG((_LOG(3), self, NULL,
5199 * "%s@%s failed probe compatible decoration",
5205 /* Encode devid from identity information. */
5206 if (ddi_devid_scsi_encode(DEVID_SCSI_ENCODE_VERSION_LATEST
, dname
,
5207 (uchar_t
*)inq
, sizeof (*inq
), inq80
, inq80len
, inq83
, inq83len
,
5208 &devid
) == DDI_SUCCESS
) {
5211 /* Attempt to form guid from devid. */
5212 guid
= ddi_devid_to_guid(devid
);
5214 /* Produce string devid for debug. */
5215 devid_str
= ddi_devid_str_encode(devid
, NULL
);
5216 SCSI_HBA_LOG((_LOG(3), self
, probe
, "devid '%s' guid '%s'",
5217 devid_str
? devid_str
: "NULL", guid
? guid
: "NULL"));
5218 ddi_devid_str_free(devid_str
);
5223 * Determine if the device should be enumerated as under the vHCI
5224 * (client node) or under the pHCI. By convention scsi_vhci expects
5225 * the "cinfo" argument identity information to be represented as a
5226 * devinfo node with the needed information (i.e. the pHCI probe node).
5228 if ((guid
== NULL
) ||
5229 (mdi_is_dev_supported(MDI_HCI_CLASS_SCSI
, self
, sdprobe
) !=
5231 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==> devinfo"));
5234 * Enumerate under pHCI:
5236 * Create dynamic SID dchild node. No attempt is made to
5237 * transfer information (except the addressing and identity
5238 * information) from the probe node to the dynamic node since
5239 * there may be HBA specific side effects that the framework
5240 * does not known how to transfer.
5242 ndi_devi_alloc_sleep(self
, nname
,
5243 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
5246 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5249 * Decorate new node with addressing properties (via
5250 * scsi_hba_ua_set()), compatible, identity information, and
5253 if ((scsi_hba_ua_set(addr
, dchild
, NULL
) == 0) ||
5254 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, dchild
,
5255 "compatible", compat
, ncompat
) != DDI_PROP_SUCCESS
) ||
5256 (inq80
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5257 dchild
, "inquiry-page-80", inq80
, inq80len
) !=
5258 DDI_PROP_SUCCESS
)) ||
5259 (inq83
&& (ndi_prop_update_byte_array(DDI_DEV_T_NONE
,
5260 dchild
, "inquiry-page-83", inq83
, inq83len
) !=
5261 DDI_PROP_SUCCESS
)) ||
5262 (ndi_prop_update_string(DDI_DEV_T_NONE
, dchild
,
5263 "class", "scsi") != DDI_PROP_SUCCESS
)) {
5264 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5265 "devinfo @%s failed decoration", addr
));
5266 (void) scsi_hba_remove_node(dchild
);
5271 /* Bind the driver */
5272 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5273 /* need to bind in order to register a devid */
5274 SCSI_HBA_LOG((_LOGCFG
, NULL
, dchild
,
5275 "devinfo @%s created, no driver-> "
5276 "no devid_register", addr
));
5280 /* Register devid */
5282 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5283 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5284 "devinfo @%s created, "
5285 "devid register failed", addr
));
5287 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5288 "devinfo @%s created with devid", addr
));
5290 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5291 "devinfo @%s created, no devid", addr
));
5294 * Enumerate under vHCI:
5296 * Create a pathinfo pchild node.
5298 SCSI_HBA_LOG((_LOG(3), self
, probe
, "==>pathinfo"));
5300 if (mdi_pi_alloc_compatible(self
, nname
, guid
, addr
, compat
,
5301 ncompat
, 0, &pchild
) != MDI_SUCCESS
) {
5302 SCSI_HBA_LOG((_LOG(2), self
, probe
,
5303 "pathinfo alloc failed"));
5308 dchild
= mdi_pi_get_client(pchild
);
5310 ndi_flavor_set(dchild
, SCSA_FLAVOR_SCSI_DEVICE
);
5313 * Decorate new node with addressing properties via
5314 * scsi_hba_ua_set().
5316 if (scsi_hba_ua_set(addr
, NULL
, pchild
) == 0) {
5317 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5318 "pathinfo %s decoration failed",
5319 mdi_pi_spathname(pchild
)));
5320 (void) mdi_pi_free(pchild
, 0);
5325 /* Bind the driver */
5326 if (ndi_devi_bind_driver(dchild
, 0) != NDI_SUCCESS
) {
5327 /* need to bind in order to register a devid */
5328 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
5329 "pathinfo %s created, no client driver-> "
5330 "no devid_register", mdi_pi_spathname(pchild
)));
5334 /* Watch out for inconsistancies in devids. */
5335 if (ddi_devid_get(dchild
, &cdevid
) == DDI_SUCCESS
)
5338 if (have_devid
&& !have_cdevid
) {
5339 /* Client does not yet have devid, register ours. */
5340 if (ddi_devid_register(dchild
, devid
) == DDI_FAILURE
)
5341 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
5342 "pathinfo %s created, "
5343 "devid register failed",
5344 mdi_pi_spathname(pchild
)));
5346 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5347 "pathinfo %s created with devid",
5348 mdi_pi_spathname(pchild
)));
5349 } else if (have_devid
&& have_cdevid
) {
5351 * We have devid and client already has devid:
5352 * they must be the same.
5354 if (ddi_devid_compare(cdevid
, devid
) != 0) {
5355 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5356 "mismatched devid on path %s",
5357 mdi_pi_spathname(pchild
)));
5359 } else if (!have_devid
&& have_cdevid
) {
5361 * Client already has a devid, but we don't:
5362 * we should not have missing devids.
5364 SCSI_HBA_LOG((_LOG(WARN
), NULL
, dchild
,
5365 "missing devid on path %s",
5366 mdi_pi_spathname(pchild
)));
5367 } else if (!have_cdevid
&& !have_devid
) {
5368 /* devid not supported */
5369 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5370 "pathinfo %s created, no devid",
5371 mdi_pi_spathname(pchild
)));
5375 * The above has registered devid for the device under
5376 * the client node. Now register it under the full pHCI
5377 * path to the device. We'll get an entry equivalent to
5378 * booting with mpxio disabled. This is needed for
5379 * telemetry during enumeration.
5381 if (e_devid_cache_pathinfo(pchild
, devid
) == DDI_SUCCESS
) {
5382 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5383 "pathinfo @%s created with devid", addr
));
5385 SCSI_HBA_LOG((_LOG(1), NULL
, dchild
,
5386 "pathinfo @%s devid cache failed", addr
));
5390 /* free the node name and compatible information */
5391 out
: if (have_devid
)
5392 ddi_devid_free(devid
);
5394 ddi_devid_free(cdevid
);
5396 ddi_devid_free_guid(guid
);
5398 scsi_hba_ident_nodename_compatible_free(nname
, dname
, compat
);
5400 ddi_prop_free(inq80
);
5402 ddi_prop_free(inq83
);
5404 ddi_prop_free(binding_set
);
5406 /* return child_type results */
5410 return (CHILD_TYPE_PATHINFO
);
5411 } else if (dchild
) {
5414 return (CHILD_TYPE_DEVINFO
);
5417 return (CHILD_TYPE_NONE
);
5421 * Call scsi_device_createchild and then initchild the new node.
5424 scsi_device_configchild(dev_info_t
*self
, char *addr
, scsi_enum_t se
,
5425 struct scsi_device
*sdprobe
, int *circp
, int *ppi
)
5429 mdi_pathinfo_t
*pchild
;
5433 ASSERT(self
&& addr
&& *addr
&& DEVI_BUSY_OWNED(self
));
5437 child_type
= scsi_device_createchild(self
, addr
, se
, sdprobe
,
5441 * Prevent multiple initialized (tran_tgt_init) nodes associated with
5442 * the same @addr at the same time by calling tran_tgt_free() on the
5443 * probe node prior to promotion of the 'real' node. After the call
5444 * to scsi_hba_barrier_tran_tgt_free(), the HBA no longer has any
5445 * probe node context.
5447 scsi_hba_barrier_tran_tgt_free(sdprobe
->sd_dev
);
5449 switch (child_type
) {
5450 case CHILD_TYPE_NONE
:
5454 case CHILD_TYPE_PATHINFO
:
5456 * Online pathinfo: Hold the path and exit the pHCI while
5457 * calling mdi_pi_online() to avoid deadlock with power
5458 * management of pHCI.
5460 ASSERT(MDI_PHCI(self
));
5461 mdi_hold_path(pchild
);
5462 scsi_hba_devi_exit_phci(self
, *circp
);
5464 rval
= mdi_pi_online(pchild
, 0);
5466 scsi_hba_devi_enter_phci(self
, circp
);
5467 mdi_rele_path(pchild
);
5469 if (rval
!= MDI_SUCCESS
) {
5470 /* pathinfo form of "failed during tran_tgt_init" */
5471 scsi_enumeration_failed(NULL
, se
,
5472 mdi_pi_spathname(pchild
), "path online");
5473 (void) mdi_pi_free(pchild
, 0);
5478 * Return the path_instance of the pathinfo node.
5480 * NOTE: We assume that sd_inq is not path-specific.
5483 *ppi
= mdi_pi_get_path_instance(pchild
);
5487 * Fallthrough into CHILD_TYPE_DEVINFO code to promote
5488 * the 'client' devinfo node as a dchild.
5490 dchild
= mdi_pi_get_client(pchild
);
5491 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5492 "pathinfo online successful"));
5495 case CHILD_TYPE_DEVINFO
:
5497 * For now, we ndi_devi_online() the child because some other
5498 * parts of the IO framework, like degenerate devid code,
5499 * depend on bus_config driving nodes to DS_ATTACHED. At some
5500 * point in the future, to keep things light-weight, we would
5501 * like to change the ndi_devi_online call below to be
5503 * if (ddi_initchild(self, dchild) != DDI_SUCCESS)
5505 * This would promote the node so that framework code could
5506 * find the child with an @addr search, but does not incur
5507 * attach(9E) overhead for BUS_CONFIG_ALL cases where the
5508 * framework is not interested in attach of the node.
5510 * NOTE: If the addr specified has incorrect syntax (busconfig
5511 * one of bogus /devices path) then call below can fail.
5513 if (ndi_devi_online(dchild
, 0) != NDI_SUCCESS
) {
5514 SCSI_HBA_LOG((_LOG(2), NULL
, dchild
,
5515 "devinfo online failed"));
5517 /* failed online does not remove the node */
5518 (void) scsi_hba_remove_node(dchild
);
5521 SCSI_HBA_LOG((_LOG(4), NULL
, dchild
,
5522 "devinfo initchild successful"));
5530 scsi_hba_pkt_comp(struct scsi_pkt
*pkt
)
5532 scsi_hba_tran_t
*tran
;
5538 * Catch second call on the same packet before doing anything else.
5540 if (pkt
->pkt_flags
& FLAG_PKT_COMP_CALLED
) {
5547 "%s duplicate scsi_hba_pkt_comp(9F) on same scsi_pkt(9S)",
5548 mod_containing_pc(caller()));
5551 pkt
->pkt_flags
|= FLAG_PKT_COMP_CALLED
;
5553 if (pkt
->pkt_comp
== NULL
)
5557 * For HBA drivers that implement tran_setup_pkt(9E), if we are
5558 * completing a 'consistent' mode DMA operation then we must
5559 * perform dma_sync prior to calling pkt_comp to ensure that
5560 * the target driver sees the correct data in memory.
5562 ASSERT((pkt
->pkt_flags
& FLAG_NOINTR
) == 0);
5563 if (((pkt
->pkt_dma_flags
& DDI_DMA_CONSISTENT
) &&
5564 (pkt
->pkt_dma_flags
& DDI_DMA_READ
)) &&
5565 ((P_TO_TRAN(pkt
)->tran_setup_pkt
) != NULL
)) {
5570 * If the HBA driver is using SCSAv3 scsi_hba_tgtmap_create enumeration
5571 * then we detect the special ASC/ASCQ completion codes that indicate
5572 * that the lun configuration of a target has changed. Since we need to
5573 * be determine scsi_device given scsi_address enbedded in
5574 * scsi_pkt (via scsi_address_device(9F)), we also require use of
5575 * SCSI_HBA_ADDR_COMPLEX.
5577 tran
= pkt
->pkt_address
.a_hba_tran
;
5579 if ((tran
->tran_tgtmap
== NULL
) ||
5580 !(tran
->tran_hba_flags
& SCSI_HBA_ADDR_COMPLEX
))
5581 goto comp
; /* not using tgtmap */
5584 * Check for lun-change notification and queue the scsi_pkt for
5585 * lunchg1 processing. The 'pkt_comp' call to the target driver
5586 * is part of lunchg1 processing.
5588 if ((pkt
->pkt_reason
== CMD_CMPLT
) &&
5589 (((*pkt
->pkt_scbp
) & STATUS_MASK
) == STATUS_CHECK
) &&
5590 (pkt
->pkt_state
& STATE_ARQ_DONE
)) {
5591 sensep
= (uint8_t *)&(((struct scsi_arq_status
*)(uintptr_t)
5592 (pkt
->pkt_scbp
))->sts_sensedata
);
5593 if (((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5594 (scsi_sense_asc(sensep
) == 0x3f) &&
5595 (scsi_sense_ascq(sensep
) == 0x0e)) ||
5597 ((scsi_sense_key(sensep
) == KEY_UNIT_ATTENTION
) &&
5598 (scsi_sense_asc(sensep
) == 0x25) &&
5599 (scsi_sense_ascq(sensep
) == 0x00))) {
5601 * The host adaptor is done with the packet, we use
5602 * pkt_stmp stage-temporary to link the packet for
5603 * lunchg1 processing.
5605 * NOTE: pkt_ha_private is not available since its use
5606 * extends to tran_teardown_pkt.
5608 mutex_enter(&scsi_lunchg1_mutex
);
5609 pkt
->pkt_stmp
= scsi_lunchg1_list
;
5610 scsi_lunchg1_list
= pkt
;
5611 if (pkt
->pkt_stmp
== NULL
)
5612 (void) cv_signal(&scsi_lunchg1_cv
);
5613 mutex_exit(&scsi_lunchg1_mutex
);
5618 comp
: (*pkt
->pkt_comp
)(pkt
);
5622 * return 1 if the specified node is a barrier/probe node
5625 scsi_hba_devi_is_barrier(dev_info_t
*probe
)
5627 if (probe
&& (strcmp(ddi_node_name(probe
), "probe") == 0))
5633 * A host adapter driver is easier to write if we prevent multiple initialized
5634 * (tran_tgt_init) scsi_device structures to the same unit-address at the same
5635 * time. We prevent this from occurring all the time during the barrier/probe
5636 * node to real child hand-off by calling scsi_hba_barrier_tran_tgt_free
5637 * on the probe node prior to ddi_inichild of the 'real' node. As part of
5638 * this early tran_tgt_free implementation, we must also call this function
5639 * as we put a probe node on the scsi_hba_barrier_list.
5642 scsi_hba_barrier_tran_tgt_free(dev_info_t
*probe
)
5644 struct scsi_device
*sdprobe
;
5646 scsi_hba_tran_t
*tran
;
5648 ASSERT(probe
&& scsi_hba_devi_is_barrier(probe
));
5650 /* Return if we never called tran_tgt_init(9E). */
5651 if (i_ddi_node_state(probe
) < DS_INITIALIZED
)
5654 sdprobe
= ddi_get_driver_private(probe
);
5655 self
= ddi_get_parent(probe
);
5656 ASSERT(sdprobe
&& self
);
5657 tran
= ddi_get_driver_private(self
);
5660 if (tran
->tran_tgt_free
) {
5662 * To correctly support TRAN_CLONE, we need to use the same
5663 * cloned scsi_hba_tran(9S) structure for both tran_tgt_init(9E)
5664 * and tran_tgt_free(9E).
5666 if (tran
->tran_hba_flags
& SCSI_HBA_TRAN_CLONE
)
5667 tran
= sdprobe
->sd_address
.a_hba_tran
;
5669 if (!sdprobe
->sd_tran_tgt_free_done
) {
5670 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5671 "tran_tgt_free EARLY"));
5672 (*tran
->tran_tgt_free
) (self
, probe
, tran
, sdprobe
);
5673 sdprobe
->sd_tran_tgt_free_done
= 1;
5675 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5676 "tran_tgt_free EARLY already done"));
5682 * Add an entry to the list of barrier nodes to be asynchronously deleted by
5683 * the scsi_hba_barrier_daemon after the specified timeout. Nodes on
5684 * the barrier list are used to implement the bus_config probe cache
5685 * of non-existent devices. The nodes are at DS_INITIALIZED, so their
5686 * @addr is established for searching. Since devi_ref of a DS_INITIALIZED
5687 * node will *not* prevent demotion, demotion is prevented by setting
5688 * sd_uninit_prevent. Devinfo snapshots attempt to attach probe cache
5689 * nodes, and on failure attempt to demote the node (without the participation
5690 * of bus_unconfig) to DS_BOUND - this demotion is prevented via
5691 * sd_uninit_prevent causing any attempted DDI_CTLOPS_UNINITCHILD to fail.
5692 * Probe nodes are bound to nulldriver. The list is sorted by
5695 * NOTE: If we drove a probe node to DS_ATTACHED, we could use ndi_hold_devi()
5696 * to prevent demotion (instead of sd_uninit_prevent).
5699 scsi_hba_barrier_add(dev_info_t
*probe
, int seconds
)
5701 struct scsi_hba_barrier
*nb
;
5702 struct scsi_hba_barrier
*b
;
5703 struct scsi_hba_barrier
**bp
;
5706 ASSERT(scsi_hba_devi_is_barrier(probe
));
5708 /* HBA is no longer responsible for nodes on the barrier list. */
5709 scsi_hba_barrier_tran_tgt_free(probe
);
5710 nb
= kmem_alloc(sizeof (struct scsi_hba_barrier
), KM_SLEEP
);
5711 mutex_enter(&scsi_hba_barrier_mutex
);
5712 endtime
= ddi_get_lbolt() + drv_usectohz(seconds
* MICROSEC
);
5713 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
;
5714 bp
= &b
->barrier_next
)
5715 if (b
->barrier_endtime
> endtime
)
5717 nb
->barrier_next
= *bp
;
5718 nb
->barrier_endtime
= endtime
;
5719 nb
->barrier_probe
= probe
;
5721 if (bp
== &scsi_hba_barrier_list
)
5722 (void) cv_signal(&scsi_hba_barrier_cv
);
5723 mutex_exit(&scsi_hba_barrier_mutex
);
5727 * Attempt to remove devinfo node node, return 1 if removed. We
5728 * don't try to remove barrier nodes that have sd_uninit_prevent set
5729 * (even though they should fail device_uninitchild).
5732 scsi_hba_remove_node(dev_info_t
*child
)
5734 dev_info_t
*self
= ddi_get_parent(child
);
5735 struct scsi_device
*sd
;
5739 char na
[SCSI_MAXNAMELEN
];
5741 scsi_hba_devi_enter(self
, &circ
);
5743 /* Honor sd_uninit_prevent on barrier nodes */
5744 if (scsi_hba_devi_is_barrier(child
)) {
5745 sd
= ddi_get_driver_private(child
);
5746 if (sd
&& sd
->sd_uninit_prevent
)
5751 (void) ddi_deviname(child
, na
);
5752 if (ddi_remove_child(child
, 0) != DDI_SUCCESS
) {
5753 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
5754 "remove_node failed"));
5756 child
= NULL
; /* child is gone */
5757 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
5758 "remove_node removed %s", *na
? &na
[1] : na
));
5762 SCSI_HBA_LOG((_LOG(4), NULL
, child
, "remove_node prevented"));
5764 scsi_hba_devi_exit(self
, circ
);
5769 * The asynchronous barrier deletion daemon. Waits for a barrier timeout
5770 * to expire, then deletes the barrier (removes it as a child).
5774 scsi_hba_barrier_daemon(void *arg
)
5776 struct scsi_hba_barrier
*b
;
5778 callb_cpr_t cprinfo
;
5782 CALLB_CPR_INIT(&cprinfo
, &scsi_hba_barrier_mutex
,
5783 callb_generic_cpr
, "scsi_hba_barrier_daemon");
5784 again
: mutex_enter(&scsi_hba_barrier_mutex
);
5786 b
= scsi_hba_barrier_list
;
5788 /* all barriers expired, wait for barrier_add */
5789 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5790 (void) cv_wait(&scsi_hba_barrier_cv
,
5791 &scsi_hba_barrier_mutex
);
5792 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_hba_barrier_mutex
);
5794 if (ddi_get_lbolt() >= b
->barrier_endtime
) {
5796 * Drop and retry if ordering issue. Do this
5797 * before calling scsi_hba_remove_node() and
5800 probe
= b
->barrier_probe
;
5801 self
= ddi_get_parent(probe
);
5802 if (scsi_hba_devi_tryenter(self
, &circ
) == 0) {
5803 delay
: mutex_exit(&scsi_hba_barrier_mutex
);
5808 /* process expired barrier */
5809 if (!scsi_hba_remove_node(probe
)) {
5810 /* remove failed, delay and retry */
5811 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
5813 scsi_hba_devi_exit(self
, circ
);
5816 scsi_hba_barrier_list
= b
->barrier_next
;
5817 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5818 scsi_hba_devi_exit(self
, circ
);
5820 /* establish timeout for next barrier expire */
5821 (void) cv_timedwait(&scsi_hba_barrier_cv
,
5822 &scsi_hba_barrier_mutex
,
5823 b
->barrier_endtime
);
5830 * Remove all barriers associated with the specified HBA. This is called
5831 * from from the bus_unconfig implementation to remove probe nodes associated
5832 * with the specified HBA (self) so that probe nodes that have not expired
5833 * will not prevent DR of the HBA.
5836 scsi_hba_barrier_purge(dev_info_t
*self
)
5838 struct scsi_hba_barrier
**bp
;
5839 struct scsi_hba_barrier
*b
;
5841 mutex_enter(&scsi_hba_barrier_mutex
);
5842 for (bp
= &scsi_hba_barrier_list
; (b
= *bp
) != NULL
; ) {
5843 if (ddi_get_parent(b
->barrier_probe
) == self
) {
5844 if (scsi_hba_remove_node(b
->barrier_probe
)) {
5845 *bp
= b
->barrier_next
;
5846 kmem_free(b
, sizeof (struct scsi_hba_barrier
));
5848 SCSI_HBA_LOG((_LOG(4), NULL
, b
->barrier_probe
,
5852 bp
= &b
->barrier_next
;
5855 mutex_exit(&scsi_hba_barrier_mutex
);
5859 * LUN-change processing daemons: processing occurs in two stages:
5861 * Stage 1: Daemon waits for a lunchg1 queued scsi_pkt, dequeues the pkt,
5862 * forms the path, completes the scsi_pkt (pkt_comp), and
5863 * queues the path for stage 2 processing. The use of stage 1
5864 * avoids issues related to memory allocation in interrupt context
5865 * (scsi_hba_pkt_comp()). We delay the pkt_comp completion until
5866 * after lunchg1 processing forms the path for stage 2 - this is
5867 * done to prevent the target driver from detaching until the
5868 * path formation is complete (driver with outstanding commands
5869 * should not detach).
5871 * Stage 2: Daemon waits for a lunchg2 queued request, dequeues the
5872 * request, and opens the path using ldi_open_by_name(). The
5873 * path opened uses a special "@taddr,*" unit address that will
5874 * trigger lun enumeration in scsi_hba_bus_configone(). We
5875 * trigger lun enumeration in stage 2 to avoid problems when
5876 * initial ASC/ASCQ trigger occurs during discovery.
5880 scsi_lunchg1_daemon(void *arg
)
5882 callb_cpr_t cprinfo
;
5883 struct scsi_pkt
*pkt
;
5884 scsi_hba_tran_t
*tran
;
5886 struct scsi_device
*sd
;
5888 char taddr
[SCSI_MAXNAMELEN
];
5889 char path
[MAXPATHLEN
];
5890 struct scsi_lunchg2
*lunchg2
;
5892 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg1_mutex
,
5893 callb_generic_cpr
, "scsi_lunchg1_daemon");
5894 mutex_enter(&scsi_lunchg1_mutex
);
5896 pkt
= scsi_lunchg1_list
;
5898 /* All lunchg1 processing requests serviced, wait. */
5899 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5900 (void) cv_wait(&scsi_lunchg1_cv
,
5901 &scsi_lunchg1_mutex
);
5902 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg1_mutex
);
5906 /* Unlink and perform lunchg1 processing on pkt. */
5907 scsi_lunchg1_list
= pkt
->pkt_stmp
;
5909 /* Determine initiator port (self) from the pkt_address. */
5910 tran
= pkt
->pkt_address
.a_hba_tran
;
5911 ASSERT(tran
&& tran
->tran_tgtmap
&& tran
->tran_iport_dip
);
5912 self
= tran
->tran_iport_dip
;
5915 * Determine scsi_devie from pkt_address (depends on
5916 * SCSI_HBA_ADDR_COMPLEX).
5918 sd
= scsi_address_device(&(pkt
->pkt_address
));
5921 (*pkt
->pkt_comp
)(pkt
);
5925 /* Determine unit-address from scsi_device. */
5926 ua
= scsi_device_unit_address(sd
);
5928 /* Extract taddr from the unit-address. */
5929 for (p
= taddr
; (*ua
!= ',') && (*ua
!= '\0'); )
5931 *p
= '\0'; /* NULL terminate taddr */
5934 * Form path using special "@taddr,*" notation to trigger
5937 (void) ddi_pathname(self
, path
);
5938 (void) strcat(path
, "/luns@");
5939 (void) strcat(path
, taddr
);
5940 (void) strcat(path
, ",*");
5943 * Now that we have the path, complete the pkt that
5944 * triggered lunchg1 processing.
5946 (*pkt
->pkt_comp
)(pkt
);
5948 /* Allocate element for stage2 processing queue. */
5949 lunchg2
= kmem_alloc(sizeof (*lunchg2
), KM_SLEEP
);
5950 lunchg2
->lunchg2_path
= strdup(path
);
5952 /* Queue and dispatch to stage 2. */
5953 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
5954 "lunchg stage1: queue %s", lunchg2
->lunchg2_path
));
5955 mutex_enter(&scsi_lunchg2_mutex
);
5956 lunchg2
->lunchg2_next
= scsi_lunchg2_list
;
5957 scsi_lunchg2_list
= lunchg2
;
5958 if (lunchg2
->lunchg2_next
== NULL
)
5959 (void) cv_signal(&scsi_lunchg2_cv
);
5960 mutex_exit(&scsi_lunchg2_mutex
);
5966 scsi_lunchg2_daemon(void *arg
)
5968 callb_cpr_t cprinfo
;
5969 struct scsi_lunchg2
*lunchg2
;
5973 CALLB_CPR_INIT(&cprinfo
, &scsi_lunchg2_mutex
,
5974 callb_generic_cpr
, "scsi_lunchg2_daemon");
5976 li
= ldi_ident_from_anon();
5977 mutex_enter(&scsi_lunchg2_mutex
);
5979 lunchg2
= scsi_lunchg2_list
;
5980 if (lunchg2
== NULL
) {
5981 /* All lunchg2 processing requests serviced, wait. */
5982 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
5983 (void) cv_wait(&scsi_lunchg2_cv
,
5984 &scsi_lunchg2_mutex
);
5985 CALLB_CPR_SAFE_END(&cprinfo
, &scsi_lunchg2_mutex
);
5989 /* Unlink and perform lunchg2 processing on pkt. */
5990 scsi_lunchg2_list
= lunchg2
->lunchg2_next
;
5993 * Open and close the path to trigger lun enumeration. We
5994 * don't expect the open to succeed, but we do expect code in
5995 * scsi_hba_bus_configone() to trigger lun enumeration.
5997 SCSI_HBA_LOG((_LOG(2), NULL
, NULL
,
5998 "lunchg stage2: open %s", lunchg2
->lunchg2_path
));
5999 if (ldi_open_by_name(lunchg2
->lunchg2_path
,
6000 FREAD
, kcred
, &lh
, li
) == 0)
6001 (void) ldi_close(lh
, FREAD
, kcred
);
6003 /* Free path and linked element. */
6004 strfree(lunchg2
->lunchg2_path
);
6005 kmem_free(lunchg2
, sizeof (*lunchg2
));
6010 * Enumerate a child at the specified @addr. If a device exists @addr then
6011 * ensure that we have the appropriately named devinfo node for it. Name is
6012 * NULL in the bus_config_all case. This routine has no knowledge of the
6013 * format of an @addr string or associated addressing properties.
6015 * The caller must guarantee that there is an open scsi_hba_devi_enter on the
6016 * parent. We return the scsi_device structure for the child device. This
6017 * scsi_device structure is valid until the caller scsi_hba_devi_exit the
6018 * parent. The caller can add do ndi_hold_devi of the child prior to the
6019 * scsi_hba_devi_exit to extend the validity of the child.
6021 * In some cases the returned scsi_device structure may be used to drive
6022 * additional SCMD_REPORT_LUNS operations by bus_config_all callers.
6024 * The first operation performed is to see if there is a dynamic SID nodes
6025 * already attached at the specified "name@addr". This is the fastpath
6026 * case for resolving a reference to a node that has already been created.
6027 * All other references are serialized for a given @addr prior to probing
6028 * to determine the type of device, if any, at the specified @addr.
6029 * If no device is present then NDI_FAILURE is returned. The fact that a
6030 * device does not exist may be determined via the barrier/probe cache,
6031 * minimizing the probes of non-existent devices.
6033 * When there is a device present the dynamic SID node is created based on
6034 * the device found. If a driver.conf node exists for the same @addr it
6035 * will either merge into the dynamic SID node (if the SID node bound to
6036 * that driver), or exist independently. To prevent the actions of one driver
6037 * causing side effects in another, code prevents multiple SID nodes from
6038 * binding to the same "@addr" at the same time. There is autodetach code
6039 * to allow one device to be replaced with another at the same @addr for
6040 * slot addressed SCSI bus implementations (SPI). For compatibility with
6041 * legacy driver.conf behavior, the code does not prevent multiple driver.conf
6042 * nodes from attaching to the same @addr at the same time.
6044 * This routine may have the side effect of creating nodes for devices other
6045 * than the one being sought. It is possible that there is a different type of
6046 * target device at that target/lun address than we were asking for. In that
6047 * It is the caller's responsibility to determine whether the device we found,
6048 * if any, at the specified address, is the one it really wanted.
6050 static struct scsi_device
*
6051 scsi_device_config(dev_info_t
*self
, char *name
, char *addr
, scsi_enum_t se
,
6052 int *circp
, int *ppi
)
6054 dev_info_t
*child
= NULL
;
6055 dev_info_t
*probe
= NULL
;
6056 struct scsi_device
*sdchild
;
6057 struct scsi_device
*sdprobe
;
6058 dev_info_t
*dsearch
;
6059 mdi_pathinfo_t
*psearch
;
6063 int wait_msg
= scsi_hba_wait_msg
;
6066 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6068 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s wanted",
6069 name
? name
: "", addr
));
6071 /* playing with "probe" node name is dangerous */
6072 if (name
&& (strcmp(name
, "probe") == 0))
6076 * NOTE: use 'goto done;' or 'goto fail;'. There should only be one
6077 * 'return' statement from here to the end of the function - the one
6078 * on the last line of the function.
6082 * Fastpath: search to see if we are requesting a named SID node that
6083 * already exists (we already created) - probe node does not count.
6084 * scsi_findchild() does not hold the returned devinfo node, but
6085 * this is OK since the caller has a scsi_hba_devi_enter on the
6086 * attached parent HBA (self). The caller is responsible for attaching
6087 * and placing a hold on the child (directly via ndi_hold_devi or
6088 * indirectly via ndi_busop_bus_config) before doing an
6089 * scsi_hba_devi_exit on the parent.
6091 * NOTE: This fastpath prevents detecting a driver binding change
6092 * (autodetach) if the same nodename is used for old and new binding.
6094 /* first call is with init set */
6095 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6096 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
) &&
6097 !scsi_hba_devi_is_barrier(dsearch
)) {
6098 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6099 "%s@%s devinfo fastpath", name
? name
: "", addr
));
6105 * Create a barrier devinfo node used to "probe" the device with. We
6106 * need to drive this node to DS_INITIALIZED so that the
6107 * DDI_CTLOPS_INITCHILD has occurred, bringing the SCSA transport to
6108 * a state useable state for issuing our "probe" commands. We establish
6109 * this barrier node with a node name of "probe" and compatible
6110 * property of "scsiprobe". The compatible property must be associated
6111 * in /etc/driver_aliases with a scsi target driver available in the
6112 * root file system (sd).
6114 * The "probe" that we perform on the barrier node, after it is
6115 * DS_INITIALIZED, is used to find the information needed to create a
6116 * dynamic devinfo (SID) node. This "probe" is separate from the
6117 * probe(9E) call associated with the transition of a node from
6118 * DS_INITIALIZED to DS_PROBED. The probe(9E) call that eventually
6119 * occurs against the created SID node should find ddi_dev_is_sid and
6120 * just return DDI_PROBE_DONTCARE.
6122 * Trying to avoid the use of a barrier node is not a good idea
6123 * because we may have an HBA driver that uses generic bus_config
6124 * (this code) but implements its own DDI_CTLOPS_INITCHILD with side
6125 * effects that we can't duplicate (such as the ATA nexus driver).
6127 * The probe/barrier node plays an integral part of the locking scheme.
6128 * The objective is to single thread probes of the same device (same
6129 * @addr) while allowing parallelism for probes of different devices
6130 * with the same parent. At this point we are serialized on our self.
6131 * For parallelism we will need to release our self. Prior to release
6132 * we construct a barrier for probes of the same device to serialize
6133 * against. The "probe@addr" node acts as this barrier. An entering
6134 * thread must wait until the probe node does not exist - it can then
6135 * create and link the probe node - dropping the HBA (self) lock after
6136 * the node is linked and visible (after ddi_initchild). A side effect
6137 * of this is that transports should not "go over the wire" (i.e. do
6138 * things that incur significant delays) until after tran_target_init.
6139 * This means that the first "over the wire" operation should occur
6140 * at tran_target_probe time - when things are running in parallel
6143 * If the probe node exists then another probe with the same @addr is
6144 * in progress, we must wait until there is no probe in progress
6145 * before proceeding, and when we proceed we must continue to hold the
6146 * HBA (self) until we have linked a new probe node as a barrier.
6148 * When a device is found to *not* exist, its probe/barrier node may be
6149 * marked with DEVICE_REMOVED with node deletion scheduled for some
6150 * future time (seconds). This asynchronous deletion allows the
6151 * framework to detect repeated requests to the same non-existent
6152 * device and avoid overhead associated with contacting a non-existent
6153 * device again and again.
6157 * Search for probe node - they should only exist as devinfo
6160 (void) scsi_findchild(self
, "probe", addr
,
6161 0, &probe
, &psearch
, NULL
);
6162 if (probe
== NULL
) {
6164 SCSI_HBA_LOG((_LOG(2), self
,
6165 mdi_pi_get_client(psearch
),
6166 "???? @%s 'probe' search found "
6167 "pathinfo: %p", addr
, (void *)psearch
));
6172 * The barrier node may cache the non-existence of a device
6173 * by leaving the barrier node in place (with
6174 * DEVI_DEVICE_REMOVED flag set ) for some amount of time after
6175 * the failure of a probe. This flag is used to fail
6176 * additional probes until the barrier probe node is deleted,
6177 * which will occur from a timeout some time after a failed
6178 * probe. The failed probe will use DEVI_SET_DEVICE_REMOVED
6179 * and schedule probe node deletion from a timeout. The callers
6180 * scsi_hba_devi_exit on the way out of the first failure will
6181 * do the cv_broadcast associated with the cv_wait below - this
6182 * handles threads that wait prior to DEVI_DEVICE_REMOVED being
6185 if (DEVI_IS_DEVICE_REMOVED(probe
)) {
6186 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6187 "detected probe DEVICE_REMOVED"));
6188 probe
= NULL
; /* deletion already scheduled */
6193 * Drop the lock on the HBA (self) and wait until the probe in
6194 * progress has completed. A changes in the sibling list from
6195 * removing the probe node will cause cv_wait to return
6196 * (scsi_hba_devi_exit does the cv_broadcast).
6200 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6201 "exists, probe already in progress: %s", wait_msg
?
6202 "waiting..." : "last msg, but still waiting..."));
6206 * NOTE: we could avoid rare case of one second delay by
6207 * implementing scsi_hba_devi_exit_and_wait based on
6208 * ndi/mdi_devi_exit_and_wait (and consider switching devcfg.c
6209 * code to use these ndi/mdi interfaces too).
6211 scsi_hba_devi_exit(self
, *circp
);
6212 mutex_enter(&DEVI(self
)->devi_lock
);
6213 (void) cv_timedwait(&DEVI(self
)->devi_cv
,
6214 &DEVI(self
)->devi_lock
,
6215 ddi_get_lbolt() + drv_usectohz(MICROSEC
));
6216 mutex_exit(&DEVI(self
)->devi_lock
);
6217 scsi_hba_devi_enter(self
, circp
);
6219 ASSERT(probe
== NULL
);
6222 * Search to see if we are requesting a SID node that already exists.
6223 * We hold the HBA (self) and there is not another probe in progress at
6224 * the same @addr. scsi_findchild() does not hold the returned
6225 * devinfo node but this is OK since we hold the HBA (self).
6228 (void) scsi_findchild(self
, name
, addr
, 1, &dsearch
, NULL
, &pi
);
6229 if (dsearch
&& scsi_hba_dev_is_sid(dsearch
)) {
6230 SCSI_HBA_LOG((_LOG(4), NULL
, dsearch
,
6231 "%s@%s probe devinfo fastpath",
6232 name
? name
: "", addr
));
6239 * We are looking for a SID node that does not exist or a driver.conf
6242 * To avoid probe side effects, before we probe the device at the
6243 * specified address we need to check to see if there is already an
6244 * initialized child "@addr".
6246 * o If we find an initialized SID child and name is NULL or matches
6247 * the name or the name of the attached driver then we return the
6250 * o If we find a non-matching SID node, we will attempt to autodetach
6251 * and remove the node in preference to our new node.
6253 * o If SID node found does not match and can't be autodetached, we
6254 * fail: we only allow one SID node at an address.
6256 * NOTE: This code depends on SID nodes showing up prior to
6257 * driver.conf nodes in the sibling list.
6260 /* first NULL name call is with init set */
6261 (void) scsi_findchild(self
, NULL
, addr
, 1, &dsearch
, NULL
, &pi
);
6262 if (dsearch
== NULL
)
6264 ASSERT(!scsi_hba_devi_is_barrier(dsearch
));
6267 * To detect changes in driver binding that should attempt
6268 * autodetach we determine the major number of the driver
6269 * that should currently be associated with the device based
6270 * on the compatible property.
6272 major
= DDI_MAJOR_T_NONE
;
6273 if (scsi_hba_dev_is_sid(dsearch
))
6274 major
= ddi_compatible_driver_major(dsearch
, NULL
);
6275 if ((major
== DDI_MAJOR_T_NONE
) && (name
== NULL
))
6276 major
= ddi_driver_major(dsearch
);
6278 if ((scsi_hba_dev_is_sid(dsearch
) ||
6279 (i_ddi_node_state(dsearch
) >= DS_INITIALIZED
)) &&
6281 (strcmp(ddi_node_name(dsearch
), name
) == 0) ||
6282 (strcmp(ddi_driver_name(dsearch
), name
) == 0)) &&
6283 (major
== ddi_driver_major(dsearch
))) {
6284 SCSI_HBA_LOG((_LOG(3), NULL
, dsearch
,
6285 "already attached @addr"));
6290 if (!scsi_hba_dev_is_sid(dsearch
))
6291 break; /* driver.conf node */
6294 * Implement autodetach of SID node for situations like a
6295 * previously "scsinodev" LUN0 coming into existence (or a
6296 * disk/tape on an SPI transport at same addr but never both
6297 * powered on at the same time). Try to autodetach the existing
6298 * SID node @addr. If that works, search again - otherwise fail.
6300 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6301 "looking for %s@%s: SID @addr exists, autodetach",
6302 name
? name
: "", addr
));
6303 if (!scsi_hba_remove_node(dsearch
)) {
6304 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6305 "autodetach @%s failed: fail %s@%s",
6306 addr
, name
? name
: "", addr
));
6309 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "autodetach @%s OK", addr
));
6313 * We will be creating a new SID node, allocate probe node
6314 * used to find out information about the device located @addr.
6315 * The probe node also acts as a barrier against additional
6316 * configuration at the same address, and in the case of non-existent
6317 * devices it will (for some amount of time) avoid re-learning that
6318 * the device does not exist on every reference. Once the probe
6319 * node is DS_LINKED we can drop the HBA (self).
6321 * The probe node is allocated as a hidden node so that it does not
6322 * show up in devinfo snapshots.
6324 ndi_devi_alloc_sleep(self
, "probe",
6325 (se
== SE_HP
) ? DEVI_SID_HP_HIDDEN_NODEID
: DEVI_SID_HIDDEN_NODEID
,
6328 ndi_flavor_set(probe
, SCSA_FLAVOR_SCSI_DEVICE
);
6331 * Decorate the probe node with the property representation of @addr
6332 * unit-address string prior to initchild so that initchild can
6333 * construct the name of the node from properties and tran_tgt_init
6334 * implementation can determine what LUN is being referenced.
6336 * If the addr specified has incorrect syntax (busconfig one of bogus
6337 * /devices path) then scsi_hba_ua_set can fail. If the address
6338 * is not understood by the SCSA HBA driver then this operation will
6339 * work, but tran_tgt_init may still fail (for example the HBA
6340 * driver may not support secondary functions).
6342 if (scsi_hba_ua_set(addr
, probe
, NULL
) == 0) {
6343 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6344 "@%s failed scsi_hba_ua_set", addr
));
6349 * Set the class property to "scsi". This is sufficient to distinguish
6350 * the node for HBAs that have multiple classes of children (like uata
6351 * - which has "dada" class for ATA children and "scsi" class for
6352 * ATAPI children) and may not use our scsi_busctl_initchild()
6353 * implementation. We also add a "compatible" property of "scsiprobe"
6354 * to select the probe driver.
6356 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, probe
,
6357 "class", "scsi") != DDI_PROP_SUCCESS
) ||
6358 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, probe
,
6359 "compatible", &compatible_probe
, 1) != DDI_PROP_SUCCESS
)) {
6360 SCSI_HBA_LOG((_LOG(1), NULL
, probe
,
6361 "@%s failed node decoration", addr
));
6366 * Promote probe node to DS_INITIALIZED so that transport can be used
6367 * for scsi_probe. After this the node is linked and visible as a
6368 * barrier for serialization of other @addr operations.
6370 * NOTE: If we attached the probe node, we could get rid of
6373 if (ddi_initchild(self
, probe
) != DDI_SUCCESS
) {
6374 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6375 "@%s failed initchild", addr
));
6377 /* probe node will be removed in fail exit path */
6381 /* get the scsi_device structure of the probe node */
6382 sdprobe
= ddi_get_driver_private(probe
);
6386 * Do scsi_probe. The probe node is linked and visible as a barrier.
6387 * We prevent uninitialization of the probe node and drop our HBA (self)
6388 * while we run scsi_probe() of this "@addr". This allows the framework
6389 * to support multiple scsi_probes for different devices attached to
6390 * the same HBA (self) in parallel. We prevent node demotion of the
6391 * probe node from DS_INITIALIZED by setting sd_uninit_prevent. The
6392 * probe node can not be successfully demoted below DS_INITIALIZED
6393 * (scsi_busctl_uninitchild will fail) until we zero sd_uninit_prevent
6394 * as we are freeing the node via scsi_hba_remove_node(probe).
6396 sdprobe
->sd_uninit_prevent
++;
6397 scsi_hba_devi_exit(self
, *circp
);
6398 sp
= scsi_probe(sdprobe
, SLEEP_FUNC
);
6400 /* Introduce a small delay here to increase parallelism. */
6403 if (sp
== SCSIPROBE_EXISTS
) {
6405 * For a device that exists, while still running in parallel,
6406 * also get identity information from device. This is done
6407 * separate from scsi_probe/tran_tgt_probe/scsi_hba_probe
6408 * since the probe code path may still be used for HBAs
6409 * that don't use common bus_config services (we don't want
6410 * to expose that code path to a behavior change). This
6411 * operation is called 'identity' to avoid confusion with
6412 * deprecated identify(9E).
6414 * Future: We may eventually want to allow HBA customization via
6415 * scsi_identity/tran_tgt_identity/scsi_device_identity, but for
6416 * now we just scsi_device_identity.
6418 * The identity operation will establish additional properties
6419 * on the probe node related to device identity:
6421 * "inquiry-page-80" byte array of SCSI page 80
6422 * "inquiry-page-83" byte array of SCSI page 83
6424 * These properties will be used to generate a devid
6425 * (ddi_devid_scsi_encode) and guid - and to register
6426 * (ddi_devid_register) a devid for the device.
6428 * If identify fails (non-zero return), the we had allocation
6429 * problems or the device returned inconsistent results then
6430 * we pretend that device does not exist.
6432 if (scsi_device_identity(sdprobe
, SLEEP_FUNC
)) {
6433 scsi_enumeration_failed(probe
, -1, NULL
, "identify");
6434 sp
= SCSIPROBE_FAILURE
;
6438 * Future: Is there anything more we can do here to help avoid
6439 * serialization on iport parent during scsi_device attach(9E)?
6442 scsi_hba_devi_enter(self
, circp
);
6443 sdprobe
->sd_uninit_prevent
--;
6445 if (sp
!= SCSIPROBE_EXISTS
) {
6446 scsi_enumeration_failed(probe
, -1, NULL
, "probe");
6448 if ((se
!= SE_HP
) && scsi_hba_barrier_timeout
) {
6450 * Target does not exist. Mark the barrier probe node
6451 * as DEVICE_REMOVED and schedule an asynchronous
6452 * deletion of the node in scsi_hba_barrier_timeout
6453 * seconds. We keep our hold on the probe node
6454 * until we are ready perform the asynchronous node
6457 SCSI_HBA_LOG((_LOG(3), NULL
, probe
,
6458 "set probe DEVICE_REMOVED"));
6459 mutex_enter(&DEVI(probe
)->devi_lock
);
6460 DEVI_SET_DEVICE_REMOVED(probe
);
6461 mutex_exit(&DEVI(probe
)->devi_lock
);
6463 scsi_hba_barrier_add(probe
, scsi_hba_barrier_timeout
);
6469 /* Create the child node from the inquiry data in the probe node. */
6470 if ((child
= scsi_device_configchild(self
, addr
, se
, sdprobe
,
6471 circp
, &pi
)) == NULL
) {
6473 * This may fail because there was no driver binding identified
6474 * via driver_alias. We may still have a conf node.
6477 (void) scsi_findchild(self
, name
, addr
,
6478 0, &child
, NULL
, &pi
);
6480 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6481 "using driver.conf driver binding"));
6483 if (child
== NULL
) {
6484 SCSI_HBA_LOG((_LOG(2), NULL
, probe
,
6485 "device not configured"));
6491 * Transfer the inquiry data from the probe node to the child
6492 * SID node to avoid an extra scsi_probe. Callers depend on
6493 * established inquiry data for the returned scsi_device.
6495 sdchild
= ddi_get_driver_private(child
);
6496 if (sdchild
&& (sdchild
->sd_inq
== NULL
)) {
6497 sdchild
->sd_inq
= sdprobe
->sd_inq
;
6498 sdprobe
->sd_inq
= NULL
;
6502 * If we are doing a bus_configone and the node we created has the
6503 * wrong node and driver name then switch the return result to a
6504 * driver.conf node with the correct name - if such a node exists.
6506 if (name
&& (strcmp(ddi_node_name(child
), name
) != 0) &&
6507 (strcmp(ddi_driver_name(child
), name
) != 0)) {
6508 (void) scsi_findchild(self
, name
, addr
,
6509 0, &dsearch
, NULL
, &pi
);
6510 if (dsearch
== NULL
) {
6511 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6512 "wrong device configured %s@%s", name
, addr
));
6514 * We can't remove when modrootloaded == 0 in case
6515 * boot-device a uses generic name and
6516 * scsi_hba_nodename_compatible_get() returned a
6517 * legacy binding-set driver oriented name.
6519 if (modrootloaded
) {
6520 (void) scsi_hba_remove_node(child
);
6525 SCSI_HBA_LOG((_LOG(2), NULL
, dsearch
,
6526 "device configured, but switching to driver.conf"));
6531 /* get the scsi_device structure from the node */
6532 SCSI_HBA_LOG((_LOG(3), NULL
, child
, "device configured"));
6535 done
: ASSERT(child
);
6536 sdchild
= ddi_get_driver_private(child
);
6540 * We may have ended up here after promotion of a previously
6541 * demoted node, where demotion deleted sd_inq data in
6542 * scsi_busctl_uninitchild. We redo the scsi_probe() to
6543 * reestablish sd_inq. We also want to redo the scsi_probe
6544 * for devices are currently device_isremove in order to
6545 * detect new device_insert.
6547 if ((sdchild
->sd_inq
== NULL
) ||
6548 ((pi
== NULL
) && ndi_devi_device_isremoved(child
))) {
6550 /* hotplug_node can only be revived via hotplug. */
6551 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
6552 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6553 "scsi_probe() demoted devinfo"));
6555 sp
= scsi_probe(sdchild
, SLEEP_FUNC
);
6557 if (sp
== SCSIPROBE_EXISTS
) {
6558 ASSERT(sdchild
->sd_inq
);
6561 * Devinfo child exists and we are
6562 * talking to the device, report
6563 * reinsert and note if this was a
6566 chg
= ndi_devi_device_insert(child
);
6567 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6568 "devinfo %s@%s device_reinsert%s",
6569 name
? name
: "", addr
,
6570 chg
? "" : "ed already"));
6572 scsi_enumeration_failed(child
, se
,
6575 chg
= ndi_devi_device_remove(child
);
6576 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6577 "%s device_remove%s",
6578 (sp
> (sizeof (scsi_probe_ascii
) /
6579 sizeof (scsi_probe_ascii
[0]))) ?
6580 "UNKNOWN" : scsi_probe_ascii
[sp
],
6581 chg
? "" : "ed already"));
6587 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6595 fail
: ASSERT(child
== NULL
);
6600 * Clean up probe node, destroying node if uninit_prevent
6601 * it is going to zero. Destroying the probe node (deleting
6602 * from the sibling list) will wake up any people waiting on
6603 * the probe node barrier.
6605 SCSI_HBA_LOG((_LOG(4), NULL
, probe
, "remove probe"));
6606 if (!scsi_hba_remove_node(probe
)) {
6608 * Probe node removal should not fail, but if it
6609 * does we hand that responsibility over to the
6610 * async barrier deletion thread - other references
6611 * to the same unit-address can hang until the
6612 * probe node delete completes.
6614 SCSI_HBA_LOG((_LOG(4), NULL
, probe
,
6615 "remove probe failed, go async"));
6616 scsi_hba_barrier_add(probe
, 1);
6622 * If we successfully resolved via a pathinfo node, we need to find
6623 * the pathinfo node and ensure that it is online (if possible). This
6624 * is done for the case where the device was open when
6625 * scsi_device_unconfig occurred, so mdi_pi_free did not occur. If the
6626 * device has now been reinserted, we want the path back online.
6627 * NOTE: This needs to occur after destruction of the probe node to
6628 * avoid ASSERT related to two nodes at the same unit-address.
6630 if (sdchild
&& pi
&& (probe
== NULL
)) {
6631 ASSERT(MDI_PHCI(self
));
6633 (void) scsi_findchild(self
, NULL
, addr
,
6634 0, &dsearch
, &psearch
, NULL
);
6635 ASSERT((psearch
== NULL
) ||
6636 (mdi_pi_get_client(psearch
) == child
));
6638 if (psearch
&& mdi_pi_device_isremoved(psearch
)) {
6640 * Verify that we can talk to the device, and if
6641 * so note if this is a new device_insert.
6643 * NOTE: We depend on mdi_path_select(), when given
6644 * a specific path_instance, to select that path
6645 * even if the path is offline.
6647 * NOTE: A Client node is not ndi_dev_is_hotplug_node().
6650 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
6651 "%s scsi_probe() demoted pathinfo",
6652 mdi_pi_spathname(psearch
)));
6654 sp
= scsi_hba_probe_pi(sdchild
, SLEEP_FUNC
, pi
);
6656 if (sp
== SCSIPROBE_EXISTS
) {
6658 * Pathinfo child exists and we are
6659 * talking to the device, report
6660 * reinsert and note if this
6661 * was a new reinsert.
6663 chg
= mdi_pi_device_insert(psearch
);
6664 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
6665 "pathinfo %s device_reinsert%s",
6666 mdi_pi_spathname(psearch
),
6667 chg
? "" : "ed already"));
6670 (void) mdi_pi_online(psearch
,
6674 * Report client reinsert and note if
6675 * this was a new reinsert.
6677 chg
= ndi_devi_device_insert(child
);
6678 SCSI_HBA_LOG((_LOGCFG
, NULL
, child
,
6679 "client devinfo %s@%s "
6680 "device_reinsert%s",
6681 name
? name
: "", addr
,
6682 chg
? "" : "ed already"));
6684 scsi_enumeration_failed(child
, se
,
6685 mdi_pi_spathname(psearch
),
6692 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
6694 mdi_pi_spathname(psearch
)));
6702 /* If asked for path_instance, return it. */
6710 scsi_device_unconfig(dev_info_t
*self
, char *name
, char *addr
, int *circp
)
6712 dev_info_t
*child
= NULL
;
6713 mdi_pathinfo_t
*path
= NULL
;
6717 ASSERT(self
&& addr
&& DEVI_BUSY_OWNED(self
));
6720 * We have a catch-22. We may have a demoted node that we need to find
6721 * and offline/remove. To find the node if it isn't demoted, we
6722 * use scsi_findchild. If it's demoted, we then use
6723 * ndi_devi_findchild_by_callback.
6725 (void) scsi_findchild(self
, name
, addr
, 0, &child
, &path
, NULL
);
6727 if ((child
== NULL
) && (path
== NULL
)) {
6728 child
= ndi_devi_findchild_by_callback(self
, name
, addr
,
6731 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6732 "devinfo %s@%s found by callback",
6733 name
? name
: "", addr
));
6734 ASSERT(ndi_flavor_get(child
) ==
6735 SCSA_FLAVOR_SCSI_DEVICE
);
6736 if (ndi_flavor_get(child
) != SCSA_FLAVOR_SCSI_DEVICE
) {
6737 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6738 "devinfo %s@%s not SCSI_DEVICE flavored",
6739 name
? name
: "", addr
));
6746 ASSERT(child
&& (path
== NULL
));
6748 /* Don't unconfig probe nodes. */
6749 if (scsi_hba_devi_is_barrier(child
)) {
6750 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6751 "devinfo %s@%s is_barrier, skip",
6752 name
? name
: "", addr
));
6756 /* Attempt to offline/remove the devinfo node */
6757 if (ndi_devi_offline(child
,
6758 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
6759 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6760 "devinfo %s@%s offlined and removed",
6761 name
? name
: "", addr
));
6762 } else if (ndi_devi_device_remove(child
)) {
6763 /* Offline/remove failed, note new device_remove */
6764 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6765 "devinfo %s@%s offline failed, device_remove",
6766 name
? name
: "", addr
));
6769 ASSERT(path
&& (child
== NULL
));
6772 * Attempt to offline/remove the pathinfo node.
6774 * NOTE: mdi_pi_offline of last path will fail if the
6775 * device is open (i.e. the client can't be offlined).
6777 * NOTE: For mdi there is no REMOVE flag for mdi_pi_offline().
6778 * When mdi_pi_offline returns MDI_SUCCESS, we are responsible
6779 * for remove via mdi_pi_free().
6781 mdi_hold_path(path
);
6782 spathname
= mdi_pi_spathname(path
); /* valid after free */
6783 scsi_hba_devi_exit_phci(self
, *circp
);
6784 rval
= mdi_pi_offline(path
, 0);
6785 scsi_hba_devi_enter_phci(self
, circp
);
6787 /* Note new device_remove */
6788 if (mdi_pi_device_remove(path
))
6789 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6790 "pathinfo %s note device_remove", spathname
));
6792 mdi_rele_path(path
);
6793 if (rval
== MDI_SUCCESS
) {
6794 (void) mdi_pi_free(path
, 0);
6795 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6796 "pathinfo %s offlined, then freed", spathname
));
6799 ASSERT((path
== NULL
) && (child
== NULL
));
6801 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
6802 "%s@%s not found", name
? name
: "", addr
));
6807 * configure the device at the specified "@addr" address.
6809 static struct scsi_device
*
6810 scsi_hba_bus_configone_addr(dev_info_t
*self
, char *addr
, scsi_enum_t se
)
6813 struct scsi_device
*sd
;
6815 scsi_hba_devi_enter(self
, &circ
);
6816 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, NULL
);
6817 scsi_hba_devi_exit(self
, circ
);
6822 * unconfigure the device at the specified "@addr" address.
6825 scsi_hba_bus_unconfigone_addr(dev_info_t
*self
, char *addr
)
6829 scsi_hba_devi_enter(self
, &circ
);
6830 (void) scsi_device_unconfig(self
, NULL
, addr
, &circ
);
6831 scsi_hba_devi_exit(self
, circ
);
6835 * The bus_config_all operations are multi-threaded for performance. A
6836 * separate thread per target and per LUN is used. The config handle is used
6837 * to coordinate all the threads at a given level and the config thread data
6838 * contains the required information for a specific thread to identify what it
6839 * is processing and the handle under which this is being processed.
6842 /* multi-threaded config handle */
6843 struct scsi_hba_mte_h
{
6844 dev_info_t
*h_self
; /* initiator port */
6850 /* target of 'self' config thread data */
6851 struct scsi_hba_mte_td
{
6852 struct scsi_hba_mte_h
*td_h
;
6853 char *td_taddr
; /* target port */
6858 /* Invoke callback on a vector of taddrs from multiple threads */
6860 scsi_hba_thread_taddrs(dev_info_t
*self
, char **taddrs
, int mt
,
6861 scsi_enum_t se
, void (*callback
)(void *arg
))
6863 struct scsi_hba_mte_h
*h
; /* HBA header */
6864 struct scsi_hba_mte_td
*td
; /* target data */
6867 /* allocate and initialize the handle */
6868 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
6869 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
6870 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
6873 /* loop over all the targets */
6874 for (taddr
= taddrs
; *taddr
; taddr
++) {
6875 /* allocate a thread data structure for target */
6876 td
= kmem_alloc(sizeof (*td
), KM_SLEEP
);
6878 td
->td_taddr
= *taddr
;
6882 /* process the target */
6883 mutex_enter(&h
->h_lock
);
6885 mutex_exit(&h
->h_lock
);
6887 if (mt
& SCSI_ENUMERATION_MT_TARGET_DISABLE
)
6888 callback((void *)td
);
6890 (void) thread_create(NULL
, 0, callback
, (void *)td
,
6891 0, &p0
, TS_RUN
, minclsyspri
);
6894 /* wait for all the target threads to complete */
6895 mutex_enter(&h
->h_lock
);
6896 while (h
->h_thr_count
> 0)
6897 cv_wait(&h
->h_cv
, &h
->h_lock
);
6898 mutex_exit(&h
->h_lock
);
6900 /* free the handle */
6901 cv_destroy(&h
->h_cv
);
6902 mutex_destroy(&h
->h_lock
);
6903 kmem_free(h
, sizeof (*h
));
6907 /* lun/secondary function of lun0 config thread data */
6908 struct scsi_hba_mte_ld
{
6909 struct scsi_hba_mte_h
*ld_h
;
6910 char *ld_taddr
; /* target port */
6911 scsi_lun64_t ld_lun64
; /* lun */
6912 int ld_sfunc
; /* secondary function */
6917 * Enumerate the LUNs and secondary functions of the specified target. The
6918 * target portion of the "@addr" is already represented as a string in the
6919 * thread data, we add a ",lun" representation to this and perform a
6920 * bus_configone byte of enumeration on that "@addr".
6923 scsi_hba_enum_lsf_of_tgt_thr(void *arg
)
6925 struct scsi_hba_mte_ld
*ld
= (struct scsi_hba_mte_ld
*)arg
;
6926 struct scsi_hba_mte_h
*h
= ld
->ld_h
;
6927 dev_info_t
*self
= h
->h_self
;
6928 char addr
[SCSI_MAXNAMELEN
];
6930 /* make string form of "@taddr,lun[,sfunc]" and see if it exists */
6931 if (ld
->ld_sfunc
== -1)
6932 (void) snprintf(addr
, sizeof (addr
),
6933 "%s,%" PRIx64
, ld
->ld_taddr
, ld
->ld_lun64
);
6935 (void) snprintf(addr
, sizeof (addr
),
6936 "%s,%" PRIx64
",%x",
6937 ld
->ld_taddr
, ld
->ld_lun64
, ld
->ld_sfunc
);
6939 /* configure device at that unit-address address */
6940 (void) scsi_hba_bus_configone_addr(self
, addr
, ld
->ld_se
);
6942 /* signal completion of this LUN thread to the target */
6943 mutex_enter(&h
->h_lock
);
6944 if (--h
->h_thr_count
== 0)
6945 cv_broadcast(&h
->h_cv
);
6946 mutex_exit(&h
->h_lock
);
6948 /* free config thread data */
6949 kmem_free(ld
, sizeof (*ld
));
6952 /* Format of SCSI REPORT_LUNS report */
6953 typedef struct scsi_lunrpt
{
6954 uchar_t lunrpt_len_msb
; /* # LUNs being reported */
6955 uchar_t lunrpt_len_mmsb
;
6956 uchar_t lunrpt_len_mlsb
;
6957 uchar_t lunrpt_len_lsb
;
6958 uchar_t lunrpt_reserved
[4];
6959 scsi_lun_t lunrpt_luns
[1]; /* LUNs, variable size */
6963 * scsi_device_reportluns()
6965 * Callers of this routine should ensure that the 'sd0' scsi_device structure
6966 * and 'pi' path_instance specified are associated with a responding LUN0.
6967 * This should not be called for SCSI-1 devices.
6969 * To get a LUN report, we must allocate a buffer. To know how big to make the
6970 * buffer, we must know the number of LUNs. To know the number of LUNs, we must
6971 * get a LUN report. We first issue a SCMD_REPORT_LUNS command using a
6972 * reasonably sized buffer that's big enough to report all LUNs for most
6973 * typical devices. If it turns out that we needed a bigger buffer, we attempt
6974 * to allocate a buffer of sufficient size, and reissue the command. If the
6975 * first command succeeds, but the second fails, we return whatever we were
6976 * able to get the first time. We return enough information for the caller to
6977 * tell whether they got all the LUNs or only a subset.
6979 * If successful, we allocate an array of scsi_lun_t to hold the results. The
6980 * caller must kmem_free(*lunarrayp, *sizep) when finished with it. Upon
6981 * successful return return value is NDI_SUCCESS and:
6983 * *lunarrayp points to the allocated array,
6984 * *nlunsp is the number of valid LUN entries in the array,
6985 * *tlunsp is the total number of LUNs in the target,
6986 * *sizep is the size of the lunarrayp array, which must be freed.
6988 * If the *nlunsp is less than *tlunsp, then we were only able to retrieve a
6989 * subset of the total set of LUNs in the target.
6992 scsi_device_reportluns(struct scsi_device
*sd0
, char *taddr
, int pi
,
6993 scsi_lun_t
**lunarrayp
, uint32_t *nlunsp
, uint32_t *tlunsp
, size_t *sizep
)
6995 struct buf
*lunrpt_bp
;
6996 struct scsi_pkt
*lunrpt_pkt
;
6997 scsi_lunrpt_t
*lunrpt
;
6999 uint32_t tluns
, nluns
;
7000 int default_maxluns
= scsi_lunrpt_default_max
;
7003 ASSERT(sd0
&& lunarrayp
&& nlunsp
&& tlunsp
&& sizep
);
7006 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7007 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7008 * of a child of the 'self' pHCI we are enumerating.
7010 child
= sd0
->sd_dev
;
7012 /* first try, look for up to scsi_lunrpt_default_max LUNs */
7013 nluns
= default_maxluns
;
7015 again
: bsize
= sizeof (struct scsi_lunrpt
) +
7016 ((nluns
- 1) * sizeof (struct scsi_lun
));
7018 lunrpt_bp
= scsi_alloc_consistent_buf(&sd0
->sd_address
,
7019 (struct buf
*)NULL
, bsize
, B_READ
, SLEEP_FUNC
, NULL
);
7020 if (lunrpt_bp
== NULL
) {
7021 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed alloc"));
7025 lunrpt_pkt
= scsi_init_pkt(&sd0
->sd_address
,
7026 (struct scsi_pkt
*)NULL
, lunrpt_bp
, CDB_GROUP5
,
7027 sizeof (struct scsi_arq_status
), 0, PKT_CONSISTENT
,
7029 if (lunrpt_pkt
== NULL
) {
7030 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "failed init"));
7031 scsi_free_consistent_buf(lunrpt_bp
);
7035 (void) scsi_setup_cdb((union scsi_cdb
*)lunrpt_pkt
->pkt_cdbp
,
7036 SCMD_REPORT_LUNS
, 0, bsize
, 0);
7038 lunrpt_pkt
->pkt_time
= scsi_lunrpt_timeout
;
7041 * When sd0 is a vHCI scsi device, we need reportlun to be issued
7042 * against a specific LUN0 path_instance that we are enumerating.
7044 lunrpt_pkt
->pkt_path_instance
= pi
;
7045 lunrpt_pkt
->pkt_flags
|= FLAG_PKT_PATH_INSTANCE
;
7048 * NOTE: scsi_poll may not allow HBA specific recovery from TRAN_BUSY.
7050 if (scsi_poll(lunrpt_pkt
) < 0) {
7051 SCSI_HBA_LOG((_LOG(2), NULL
, child
, "reportlun not supported"));
7052 scsi_destroy_pkt(lunrpt_pkt
);
7053 scsi_free_consistent_buf(lunrpt_bp
);
7054 return (NDI_FAILURE
);
7057 scsi_destroy_pkt(lunrpt_pkt
);
7059 lunrpt
= (scsi_lunrpt_t
*)lunrpt_bp
->b_un
.b_addr
;
7061 /* Compute the total number of LUNs in the target */
7062 tluns
= (((uint_t
)lunrpt
->lunrpt_len_msb
<< 24) |
7063 ((uint_t
)lunrpt
->lunrpt_len_mmsb
<< 16) |
7064 ((uint_t
)lunrpt
->lunrpt_len_mlsb
<< 8) |
7065 ((uint_t
)lunrpt
->lunrpt_len_lsb
)) >> 3;
7068 /* Illegal response -- this target is broken */
7069 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "illegal tluns of zero"));
7070 scsi_free_consistent_buf(lunrpt_bp
);
7071 return (DDI_NOT_WELL_FORMED
);
7074 if (tluns
> nluns
) {
7075 /* have more than we allocated space for */
7076 if (nluns
== default_maxluns
) {
7077 /* first time around, reallocate larger */
7078 scsi_free_consistent_buf(lunrpt_bp
);
7083 /* uh oh, we got a different tluns the second time! */
7084 SCSI_HBA_LOG((_LOG(1), NULL
, child
,
7085 "tluns changed from %d to %d", nluns
, tluns
));
7091 * lunrpt_bp is the buffer we're using;
7092 * tluns is the total number of LUNs the target says it has;
7093 * nluns is the number of LUNs we were able to get into the buffer.
7095 * Copy the data out of scarce iopb memory into regular kmem.
7096 * The caller must kmem_free(*lunarrayp, *sizep) when finished with it.
7098 *lunarrayp
= (scsi_lun_t
*)kmem_alloc(
7099 nluns
* sizeof (scsi_lun_t
), KM_SLEEP
);
7100 if (*lunarrayp
== NULL
) {
7101 SCSI_HBA_LOG((_LOG(1), NULL
, child
, "NULL lunarray"));
7102 scsi_free_consistent_buf(lunrpt_bp
);
7106 *sizep
= nluns
* sizeof (scsi_lun_t
);
7109 bcopy((void *)&lunrpt
->lunrpt_luns
, (void *)*lunarrayp
, *sizep
);
7110 scsi_free_consistent_buf(lunrpt_bp
);
7111 SCSI_HBA_LOG((_LOG(3), NULL
, child
,
7112 "@%s,0 path %d: %d/%d luns", taddr
, pi
, nluns
, tluns
));
7113 return (NDI_SUCCESS
);
7117 * Enumerate all the LUNs and secondary functions of the specified 'taddr'
7118 * target port as accessed via 'self' pHCI. Note that sd0 may be associated
7119 * with a child of the vHCI instead of 'self' - in this case the 'pi'
7120 * path_instance is used to ensure that the SCMD_REPORT_LUNS command is issued
7121 * through the 'self' pHCI path.
7123 * We multi-thread across all the LUNs and secondary functions and enumerate
7124 * them. Which LUNs exist is based on SCMD_REPORT_LUNS data.
7126 * The scsi_device we are called with should be for LUN0 and has been probed.
7128 * This function is structured so that an HBA that has a different target
7129 * addressing structure can still use this function to enumerate the its
7130 * LUNs if it uses "taddr,lun" for its LUN space.
7132 * We make assumptions about other LUNs associated with the target:
7134 * For SCSI-2 and SCSI-3 target we will issue the SCSI report_luns
7135 * command. If this fails or we have a SCSI-1 then the number of
7136 * LUNs is determined based on SCSI_OPTIONS_NLUNS. For a SCSI-1
7137 * target we never probe above LUN 8, even if SCSI_OPTIONS_NLUNS
7138 * indicates we should.
7140 * HBA drivers wanting a different set of assumptions should implement their
7141 * own LUN enumeration code.
7144 scsi_hba_enum_lsf_of_t(struct scsi_device
*sd0
,
7145 dev_info_t
*self
, char *taddr
, int pi
, int mt
, scsi_enum_t se
)
7148 scsi_hba_tran_t
*tran
;
7149 impl_scsi_tgtmap_t
*tgtmap
;
7152 damap_t
*lundam
= NULL
;
7153 struct scsi_hba_mte_h
*h
;
7154 struct scsi_hba_mte_ld
*ld
;
7156 scsi_lun_t
*lunp
= NULL
;
7165 * If LUN0 failed then we have no other LUNs.
7167 * NOTE: We need sd_inq to be valid to check ansi version. Since
7168 * scsi_unprobe is now a noop (sd_inq freeded in
7169 * scsi_busctl_uninitchild) sd_inq remains valid even if a target
7170 * driver detach(9E) occurs, resulting in a scsi_unprobe call
7171 * (sd_uninit_prevent keeps sd_inq valid by failing any
7172 * device_uninitchild attempts).
7174 ASSERT(sd0
&& sd0
->sd_uninit_prevent
&& sd0
->sd_dev
&& sd0
->sd_inq
);
7175 if ((sd0
== NULL
) || (sd0
->sd_dev
== NULL
) || (sd0
->sd_inq
== NULL
)) {
7176 SCSI_HBA_LOG((_LOG(1), NULL
, sd0
? sd0
->sd_dev
: NULL
,
7177 "not setup correctly:%s%s%s",
7178 (sd0
== NULL
) ? " device" : "",
7179 (sd0
&& (sd0
->sd_dev
== NULL
)) ? " dip" : "",
7180 (sd0
&& (sd0
->sd_inq
== NULL
)) ? " inq" : ""));
7181 return (DDI_FAILURE
);
7185 * NOTE: child should only be used in SCSI_HBA_LOG context since with
7186 * vHCI enumeration it may be the vHCI 'client' devinfo child instead
7187 * of a child of the 'self' pHCI we are enumerating.
7189 child
= sd0
->sd_dev
;
7191 /* Determine if we are reporting lun observations into lunmap. */
7192 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7193 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7195 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
7196 tgtid
= damap_lookup(tgtdam
, taddr
);
7197 if (tgtid
!= NODAM
) {
7198 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
7199 damap_id_rele(tgtdam
, tgtid
);
7205 /* If using lunmap, start the observation */
7206 scsi_lunmap_set_begin(self
, lundam
);
7208 /* allocate and initialize the LUN handle */
7209 h
= kmem_zalloc(sizeof (*h
), KM_SLEEP
);
7210 mutex_init(&h
->h_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
7211 cv_init(&h
->h_cv
, NULL
, CV_DEFAULT
, NULL
);
7215 /* See if SCMD_REPORT_LUNS works for SCSI-2 and beyond */
7216 aver
= sd0
->sd_inq
->inq_ansi
;
7217 if ((aver
>= SCSI_VERSION_2
) && (scsi_device_reportluns(sd0
,
7218 taddr
, pi
, &lunp
, &nluns
, &tluns
, &size
) == NDI_SUCCESS
)) {
7220 ASSERT(lunp
&& (size
> 0) && (nluns
> 0) && (tluns
> 0));
7222 /* loop over the reported LUNs */
7223 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7224 "@%s,0 path %d: enumerating %d reported lun%s", taddr
, pi
,
7225 nluns
, nluns
> 1 ? "s" : ""));
7227 for (lun
= 0; lun
< nluns
; lun
++) {
7228 lun64
= scsi_lun_to_lun64(lunp
[lun
]);
7231 if (scsi_lunmap_set_add(self
, lundam
,
7232 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7233 SCSI_HBA_LOG((_LOG_NF(WARN
),
7234 "@%s,%" PRIx64
" failed to create",
7241 /* allocate a thread data structure for LUN */
7242 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7244 ld
->ld_taddr
= taddr
;
7245 ld
->ld_lun64
= lun64
;
7249 /* process the LUN */
7250 mutex_enter(&h
->h_lock
);
7252 mutex_exit(&h
->h_lock
);
7254 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7255 scsi_hba_enum_lsf_of_tgt_thr(
7258 (void) thread_create(NULL
, 0,
7259 scsi_hba_enum_lsf_of_tgt_thr
,
7260 (void *)ld
, 0, &p0
, TS_RUN
,
7265 /* free the LUN array allocated by scsi_device_reportluns */
7266 kmem_free(lunp
, size
);
7268 /* Determine the number of LUNs to enumerate. */
7269 maxluns
= scsi_get_scsi_maxluns(sd0
);
7271 /* Couldn't get SCMD_REPORT_LUNS data */
7272 if (aver
>= SCSI_VERSION_3
) {
7273 scsi_enumeration_failed(child
, se
, taddr
, "report_lun");
7276 * Based on calling context tunable, only enumerate one
7277 * lun (lun0) if scsi_device_reportluns() fails on a
7278 * SCSI_VERSION_3 or greater device.
7280 if (scsi_lunrpt_failed_do1lun
& (1 << se
))
7284 /* loop over possible LUNs, skipping LUN0 */
7286 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7287 "@%s,0 path %d: enumerating luns 1-%d", taddr
, pi
,
7290 SCSI_HBA_LOG((_LOG(2), NULL
, child
,
7291 "@%s,0 path %d: enumerating just lun0", taddr
, pi
));
7293 for (lun64
= 0; lun64
< maxluns
; lun64
++) {
7295 if (scsi_lunmap_set_add(self
, lundam
,
7296 taddr
, lun64
, -1) != DDI_SUCCESS
) {
7297 SCSI_HBA_LOG((_LOG_NF(WARN
),
7298 "@%s,%" PRIx64
" failed to create",
7305 /* allocate a thread data structure for LUN */
7306 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7308 ld
->ld_taddr
= taddr
;
7309 ld
->ld_lun64
= lun64
;
7313 /* process the LUN */
7314 mutex_enter(&h
->h_lock
);
7316 mutex_exit(&h
->h_lock
);
7317 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7318 scsi_hba_enum_lsf_of_tgt_thr(
7321 (void) thread_create(NULL
, 0,
7322 scsi_hba_enum_lsf_of_tgt_thr
,
7323 (void *)ld
, 0, &p0
, TS_RUN
,
7330 * If we have an embedded service as a secondary function on LUN0 and
7331 * the primary LUN0 function is different than the secondary function
7332 * then enumerate the secondary function. The sfunc value is the dtype
7333 * associated with the embedded service.
7335 * inq_encserv: enclosure service and our dtype is not DTYPE_ESI
7336 * or DTYPE_UNKNOWN then create a separate DTYPE_ESI node for
7337 * enclosure service access.
7339 ASSERT(sd0
->sd_inq
);
7340 if (sd0
->sd_inq
->inq_encserv
&&
7341 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_UNKNOWN
) &&
7342 ((sd0
->sd_inq
->inq_dtype
& DTYPE_MASK
) != DTYPE_ESI
) &&
7343 ((sd0
->sd_inq
->inq_ansi
>= SCSI_VERSION_3
))) {
7345 if (scsi_lunmap_set_add(self
, lundam
,
7346 taddr
, 0, DTYPE_ESI
) != DDI_SUCCESS
) {
7347 SCSI_HBA_LOG((_LOG_NF(WARN
),
7348 "@%s,0,%x failed to create",
7352 /* allocate a thread data structure for sfunc */
7353 ld
= kmem_alloc(sizeof (*ld
), KM_SLEEP
);
7355 ld
->ld_taddr
= taddr
;
7357 ld
->ld_sfunc
= DTYPE_ESI
;
7360 /* process the LUN */
7361 mutex_enter(&h
->h_lock
);
7363 mutex_exit(&h
->h_lock
);
7364 if (mt
& SCSI_ENUMERATION_MT_LUN_DISABLE
)
7365 scsi_hba_enum_lsf_of_tgt_thr((void *)ld
);
7367 (void) thread_create(NULL
, 0,
7368 scsi_hba_enum_lsf_of_tgt_thr
, (void *)ld
,
7369 0, &p0
, TS_RUN
, minclsyspri
);
7374 * Future: Add secondary function support for:
7375 * inq_mchngr (DTYPE_CHANGER)
7376 * inq_sccs (DTYPE_ARRAY_CTRL)
7380 /* If using lunmap, end the observation */
7381 scsi_lunmap_set_end(self
, lundam
);
7383 /* wait for all the LUN threads of this target to complete */
7384 mutex_enter(&h
->h_lock
);
7385 while (h
->h_thr_count
> 0)
7386 cv_wait(&h
->h_cv
, &h
->h_lock
);
7387 mutex_exit(&h
->h_lock
);
7389 /* free the target handle */
7390 cv_destroy(&h
->h_cv
);
7391 mutex_destroy(&h
->h_lock
);
7392 kmem_free(h
, sizeof (*h
));
7395 return (DDI_SUCCESS
);
7399 * Enumerate LUN0 and all other LUNs and secondary functions associated with
7400 * the specified target address.
7402 * Return NDI_SUCCESS if we might have created a new node.
7403 * Return NDI_FAILURE if we definitely did not create a new node.
7406 scsi_hba_bus_config_taddr(dev_info_t
*self
, char *taddr
, int mt
, scsi_enum_t se
)
7408 char addr
[SCSI_MAXNAMELEN
];
7409 struct scsi_device
*sd
;
7414 /* See if LUN0 of the specified target exists. */
7415 (void) snprintf(addr
, sizeof (addr
), "%s,0", taddr
);
7417 scsi_hba_devi_enter(self
, &circ
);
7418 sd
= scsi_device_config(self
, NULL
, addr
, se
, &circ
, &pi
);
7422 * LUN0 exists, enumerate all the other LUNs.
7424 * With vHCI enumeration, when 'self' is a pHCI the sd
7425 * scsi_device may be associated with the vHCI 'client'.
7426 * In this case 'pi' is the path_instance needed to
7427 * continue enumeration communication LUN0 via 'self'
7428 * pHCI and specific 'taddr' target address.
7430 * We prevent the removal of LUN0 until we are done with
7431 * prevent/allow because we must exit the parent for
7432 * multi-threaded scsi_hba_enum_lsf_of_t().
7434 * NOTE: scsi_unprobe is a noop, sd->sd_inq is valid until
7435 * device_uninitchild - so sd_uninit_prevent keeps sd_inq valid
7436 * by failing any device_uninitchild attempts.
7439 sd
->sd_uninit_prevent
++;
7440 scsi_hba_devi_exit(self
, circ
);
7442 (void) scsi_hba_enum_lsf_of_t(sd
, self
, taddr
, pi
, mt
, se
);
7444 scsi_hba_devi_enter(self
, &circ
);
7445 sd
->sd_uninit_prevent
--;
7448 scsi_hba_devi_exit(self
, circ
);
7452 /* Config callout from scsi_hba_thread_taddrs */
7454 scsi_hba_taddr_config_thr(void *arg
)
7456 struct scsi_hba_mte_td
*td
= (struct scsi_hba_mte_td
*)arg
;
7457 struct scsi_hba_mte_h
*h
= td
->td_h
;
7459 (void) scsi_hba_bus_config_taddr(h
->h_self
, td
->td_taddr
,
7460 td
->td_mt
, td
->td_se
);
7462 /* signal completion of this target thread to the HBA */
7463 mutex_enter(&h
->h_lock
);
7464 if (--h
->h_thr_count
== 0)
7465 cv_broadcast(&h
->h_cv
);
7466 mutex_exit(&h
->h_lock
);
7468 /* free config thread data */
7469 kmem_free(td
, sizeof (*td
));
7473 * Enumerate all the children of the specified SCSI parallel interface (spi).
7474 * An HBA associated with a non-parallel scsi bus should be using another bus
7475 * level enumeration implementation (possibly their own) and calling
7476 * scsi_hba_bus_config_taddr to do enumeration of devices associated with a
7477 * particular target address.
7479 * On an spi bus the targets are sequentially enumerated based on the
7480 * width of the bus. We also take care to try to skip the HBAs own initiator
7481 * id. See scsi_hba_enum_lsf_of_t() for LUN and secondary function enumeration.
7483 * Return NDI_SUCCESS if we might have created a new node.
7484 * Return NDI_FAILURE if we definitely did not create a new node.
7486 * Note: At some point we may want to expose this interface in transport.h
7487 * if we find an hba that implements bus_config but still uses spi-like target
7491 scsi_hba_bus_configall_spi(dev_info_t
*self
, int mt
)
7502 * Find the number of targets supported on the bus. Look at the per
7503 * bus scsi-options property on the HBA node and check its
7504 * SCSI_OPTIONS_WIDE setting.
7506 options
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7507 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-options", -1);
7508 if ((options
!= -1) && ((options
& SCSI_OPTIONS_WIDE
) == 0))
7509 ntargets
= NTARGETS
; /* 8 */
7511 ntargets
= NTARGETS_WIDE
; /* 16 */
7514 * Find the initiator-id for the HBA so we can skip that. We get the
7515 * cached value on the HBA node, established in scsi_hba_attach_setup.
7516 * If we were unable to determine the id then we rely on the HBA to
7517 * fail gracefully when asked to enumerate itself.
7519 id
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7520 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-initiator-id", -1);
7521 if (id
> ntargets
) {
7522 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
7523 "'scsi-initiator-id' bogus for %d target bus: %d",
7527 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7528 "enumerating targets 0-%d skip %d", ntargets
, id
));
7530 /* form vector of target addresses */
7531 taddrs
= kmem_zalloc(sizeof (char *) * (ntargets
+ 1), KM_SLEEP
);
7532 for (tgt
= 0, taddr
= taddrs
; tgt
< ntargets
; tgt
++) {
7533 /* skip initiator */
7537 /* convert to string and enumerate the target address */
7538 tbuf
= kmem_alloc(((tgt
/16) + 1) + 1, KM_SLEEP
);
7539 (void) sprintf(tbuf
, "%x", tgt
);
7540 ASSERT(strlen(tbuf
) == ((tgt
/16) + 1));
7544 /* null terminate vector of target addresses */
7547 /* configure vector of target addresses */
7548 scsi_hba_thread_taddrs(self
, taddrs
, mt
, SE_BUSCONFIG
,
7549 scsi_hba_taddr_config_thr
);
7551 /* free vector of target addresses */
7552 for (taddr
= taddrs
; *taddr
; taddr
++)
7553 kmem_free(*taddr
, strlen(*taddr
) + 1);
7554 kmem_free(taddrs
, sizeof (char *) * (ntargets
+ 1));
7555 return (NDI_SUCCESS
);
7559 * Transport independent bus_configone BUS_CONFIG_ONE implementation. Takes
7560 * same arguments, minus op, as scsi_hba_bus_config(), tran_bus_config(),
7561 * and scsi_hba_bus_config_spi().
7564 scsi_hba_bus_configone(dev_info_t
*self
, uint_t flags
, char *arg
,
7565 dev_info_t
**childp
)
7572 char nameaddr
[SCSI_MAXNAMELEN
];
7573 extern int i_ndi_make_spec_children(dev_info_t
*, uint_t
);
7574 struct scsi_device
*sd0
, *sd
;
7578 /* parse_name modifies arg1, we must duplicate "name@addr" */
7579 (void) strcpy(nameaddr
, arg
);
7580 i_ddi_parse_name(nameaddr
, &name
, &addr
, NULL
);
7582 /* verify the form of the node - we need an @addr */
7583 if ((name
== NULL
) || (addr
== NULL
) ||
7584 (*name
== '\0') || (*addr
== '\0')) {
7586 * OBP may create ill formed template/stub/wild-card
7587 * nodes (no @addr) for legacy driver loading methods -
7590 SCSI_HBA_LOG((_LOG(2), self
, NULL
, "%s ill formed", arg
));
7591 return (NDI_FAILURE
);
7595 * Check to see if this is a non-scsi flavor configuration operation.
7597 if (strcmp(name
, "smp") == 0) {
7599 * Configure the child, and if we're successful return with
7602 return (smp_hba_bus_config(self
, addr
, childp
));
7606 * The framework does not ensure the creation of driver.conf
7607 * nodes prior to calling a nexus bus_config. For legacy
7608 * support of driver.conf file nodes we want to create our
7609 * driver.conf file children now so that we can detect if we
7610 * are being asked to bus_configone one of these nodes.
7612 * Needing driver.conf file nodes prior to bus config is unique
7613 * to scsi_enumeration mixed mode (legacy driver.conf and
7614 * dynamic SID node) support. There is no general need for the
7615 * framework to make driver.conf children prior to bus_config.
7617 * We enter our HBA (self) prior to scsi_device_config, and
7618 * pass it our circ. The scsi_device_config may exit the
7619 * HBA around scsi_probe() operations to allow for parallelism.
7620 * This is done after the probe node "@addr" is available as a
7621 * barrier to prevent parallel probes of the same device. The
7622 * probe node is also configured in a way that it can't be
7623 * removed by the framework until we are done with it.
7625 * NOTE: The framework is currently preventing many parallel
7626 * sibling operations (such as attaches), so the parallelism
7627 * we are providing is of marginal use until that is improved.
7628 * The most logical way to solve this would be to have separate
7629 * target and lun nodes. This would be a large change in the
7630 * format of /devices paths and is not being pursued at this
7631 * time. The need for parallelism will become more of an issue
7632 * with top-down attach for mpxio/vhci and for iSCSI support.
7633 * We may want to eventually want a dual mode implementation,
7634 * where the HBA determines if we should construct separate
7635 * target and lun devinfo nodes.
7637 scsi_hba_devi_enter(self
, &circ
);
7638 SCSI_HBA_LOG((_LOG(4), self
, NULL
, "%s@%s config_one", name
, addr
));
7639 (void) i_ndi_make_spec_children(self
, flags
);
7642 * For bus_configone, we make sure that we can find LUN0
7643 * first. This allows the delayed probe/barrier deletion for a
7644 * non-existent LUN0 (if enabled in scsi_device_config) to
7645 * cover all LUNs on the target. This is done to minimize the
7646 * number of independent target selection timeouts that occur
7647 * when a target with many LUNs is no longer accessible
7648 * (powered off). This removes the need for target driver
7649 * probe cache implementations.
7651 * This optimization may not be desirable in a pure bridge
7652 * environment where targets on the other side of the bridge
7653 * show up as LUNs to the host. If we ever need to support
7654 * such a configuration then we should consider implementing a
7655 * SCSI_OPTIONS_ILUN0 bit.
7657 * NOTE: we are *not* applying any target limitation filtering
7658 * to bus_configone, which means that we are relying on the
7659 * HBA tran_tgt_init entry point invoked by scsi_busctl_initchild
7662 sd0
= (struct scsi_device
*)-1;
7663 lcp
= strchr(addr
, ','); /* "addr,lun[,sfunc]" */
7666 * With "tgt,lun[,sfunc]" addressing, multiple addressing levels
7667 * have been compressed into single devinfo node unit-address.
7668 * This presents a mismatch - there is no bus_config to discover
7669 * LUNs below a specific target, the only choice is to
7670 * BUS_CONFIG_ALL the HBA. To support BUS_CONFIG_ALL_LUNS below
7671 * a specific target, a bus_configone with lun address of "*"
7672 * triggers lun discovery below a target.
7674 if (*(lcp
+ 1) == '*') {
7675 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7676 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7677 "scsi-enumeration", scsi_enumeration
);
7678 mt
|= scsi_hba_log_mt_disable
;
7680 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7681 "%s@%s lun enumeration triggered", name
, addr
));
7682 *lcp
= '\0'; /* turn ',' into '\0' */
7683 scsi_hba_devi_exit(self
, circ
);
7684 (void) scsi_hba_bus_config_taddr(self
, addr
,
7686 return (NDI_FAILURE
);
7689 /* convert hex lun number from ascii */
7690 lun64
= scsi_addr_to_lun64(lcp
+ 1);
7692 if ((lun64
!= 0) && (lun64
!= SCSI_LUN64_ILLEGAL
)) {
7694 * configure ",0" lun first, saving off
7695 * original lun characters.
7701 sd0
= scsi_device_config(self
,
7702 NULL
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7704 /* restore original lun */
7709 * Apply maxlun filtering.
7711 * Future: We still have the kludged
7712 * scsi_check_ss2_LUN_limit() filtering off
7713 * scsi_probe() to catch bogus driver.conf
7716 if (sd0
&& (lun64
< SCSI_32LUNS_PER_TARGET
) &&
7717 (lun64
>= scsi_get_scsi_maxluns(sd0
))) {
7719 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7720 "%s@%s filtered", name
, addr
));
7722 SCSI_HBA_LOG((_LOG(4), self
, NULL
,
7723 "%s@%s lun 0 %s", name
, addr
,
7724 sd0
? "worked" : "failed"));
7729 * configure the requested device if LUN0 exists or we were
7730 * unable to determine the lun format to determine if LUN0
7734 sd
= scsi_device_config(self
,
7735 name
, addr
, SE_BUSCONFIG
, &circ
, NULL
);
7738 SCSI_HBA_LOG((_LOG(2), self
, NULL
,
7739 "%s@%s no lun 0 or filtered lun", name
, addr
));
7743 * We know what we found, to reduce overhead we finish BUS_CONFIG_ONE
7744 * processing without calling back to the frameworks
7745 * ndi_busop_bus_config (unless we goto framework below).
7747 * If the reference is to a driver name and we created a generic name
7748 * (bound to that driver) we will still succeed. This is important
7749 * for correctly resolving old drivername references to device that now
7750 * uses a generic names across the transition to generic naming. This
7751 * is effectively an internal implementation of the NDI_DRIVERNAME flag.
7753 * We also need to special case the resolve_pathname OBP boot-device
7754 * case (modrootloaded == 0) where reference is to a generic name but
7755 * we created a legacy driver name node by returning just returning
7758 if (sd
&& sd
->sd_dev
&&
7759 ((strcmp(ddi_node_name(sd
->sd_dev
), name
) == 0) ||
7760 (strcmp(ddi_driver_name(sd
->sd_dev
), name
) == 0) ||
7761 (modrootloaded
== 0)) &&
7762 (ndi_devi_online(sd
->sd_dev
,
7763 flags
& NDI_NO_EVENT
) == NDI_SUCCESS
)) {
7765 /* device attached, return devinfo node with hold */
7767 *childp
= sd
->sd_dev
;
7768 ndi_hold_devi(sd
->sd_dev
);
7771 * In the process of failing we may have added nodes to the HBA
7772 * (self), clearing DEVI_MADE_CHILDREN. To reduce the overhead
7773 * associated with the frameworks reaction to this we clear the
7776 mutex_enter(&DEVI(self
)->devi_lock
);
7777 DEVI(self
)->devi_flags
&= ~DEVI_MADE_CHILDREN
;
7778 mutex_exit(&DEVI(self
)->devi_lock
);
7782 * The framework may still be able to succeed with
7783 * with its GENERIC_PROP code.
7785 scsi_hba_devi_exit(self
, circ
);
7786 if (flags
& NDI_DRV_CONF_REPROBE
)
7787 flags
|= NDI_CONFIG_REPROBE
;
7788 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7789 return (ndi_busop_bus_config(self
, flags
, BUS_CONFIG_ONE
,
7790 (void *)arg
, childp
, 0));
7793 scsi_hba_devi_exit(self
, circ
);
7798 * Perform SCSI Parallel Interconnect bus_config
7801 scsi_hba_bus_config_spi(dev_info_t
*self
, uint_t flags
,
7802 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7808 * Enumerate scsi target devices: See if we are doing generic dynamic
7809 * enumeration: if driver.conf has not specified the 'scsi-enumeration'
7810 * knob then use the global scsi_enumeration knob.
7812 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7813 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7814 "scsi-enumeration", scsi_enumeration
);
7815 mt
|= scsi_hba_log_mt_disable
;
7817 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0) {
7819 * Static driver.conf file enumeration:
7821 * Force reprobe for BUS_CONFIG_ONE or when manually
7822 * reconfiguring via devfsadm(1m) to emulate deferred attach.
7823 * Reprobe only discovers driver.conf enumerated nodes, more
7824 * dynamic implementations probably require their own
7827 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
7828 flags
|= NDI_CONFIG_REPROBE
;
7829 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7830 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
7833 if (scsi_hba_bus_config_debug
)
7834 flags
|= NDI_DEVI_DEBUG
;
7837 * Generic spi dynamic bus config enumeration to discover and enumerate
7838 * the target device nodes we are looking for.
7841 case BUS_CONFIG_ONE
: /* enumerate the named child */
7842 ret
= scsi_hba_bus_configone(self
, flags
, (char *)arg
, childp
);
7845 case BUS_CONFIG_ALL
: /* enumerate all children on the bus */
7846 case BUS_CONFIG_DRIVER
: /* enumerate all children that bind to driver */
7847 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7848 "BUS_CONFIG_%s mt %x",
7849 (op
== BUS_CONFIG_ALL
) ? "ALL" : "DRIVER", mt
));
7852 * Enumerate targets on SCSI parallel interconnect and let the
7853 * framework finish the operation (attach the nodes).
7855 if ((ret
= scsi_hba_bus_configall_spi(self
, mt
)) == NDI_SUCCESS
)
7856 ret
= ndi_busop_bus_config(self
, flags
, op
,
7868 * Perform SCSI Parallel Interconnect bus_unconfig
7871 scsi_hba_bus_unconfig_spi(dev_info_t
*self
, uint_t flags
,
7872 ddi_bus_config_op_t op
, void *arg
)
7879 * See if we are doing generic dynamic enumeration: if driver.conf has
7880 * not specified the 'scsi-enumeration' knob then use the global
7881 * scsi_enumeration knob.
7883 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
7884 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
,
7885 "scsi-enumeration", scsi_enumeration
);
7886 mt
|= scsi_hba_log_mt_disable
;
7888 if ((mt
& SCSI_ENUMERATION_ENABLE
) == 0)
7889 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
7891 if (scsi_hba_bus_config_debug
)
7892 flags
|= NDI_DEVI_DEBUG
;
7894 scsi_hba_devi_enter(self
, &circ
);
7896 case BUS_UNCONFIG_ONE
:
7897 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
7898 "unconfig one: %s", (char *)arg
));
7902 case BUS_UNCONFIG_ALL
:
7903 case BUS_UNCONFIG_DRIVER
:
7912 /* Perform the generic default bus unconfig */
7913 if (ret
== NDI_SUCCESS
)
7914 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
7916 scsi_hba_devi_exit(self
, circ
);
7922 scsi_hba_bus_config_tgtmap(dev_info_t
*self
, uint_t flags
,
7923 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
7925 scsi_hba_tran_t
*tran
;
7926 impl_scsi_tgtmap_t
*tgtmap
;
7927 uint64_t tsa
= 0; /* clock64_t */
7931 int ret
= NDI_FAILURE
;
7933 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
7934 (op
!= BUS_CONFIG_DRIVER
))
7937 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
7938 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
7942 * MPXIO is never a sure thing (and we have mixed children), so
7943 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
7944 * search for both devinfo and pathinfo children.
7946 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
7947 * devinfo/pathinfo children in parallel (instead of old way of
7948 * looking for one form of child and then doing "fallback" to
7949 * look for other form of child).
7951 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
7954 * If bus_config occurred within the map create-to-hotplug_sync window,
7955 * we need the framework to wait for children that are physicaly
7956 * present at map create time to show up (via tgtmap hotplug config).
7958 * The duration of this window is specified by the HBA driver at
7959 * scsi_hba_tgtmap_create(9F) time (during attach(9E)). Its
7960 * 'csync_usec' value is selected based on how long it takes the HBA
7961 * driver to get from map creation to initial observation for something
7962 * already plugged in. Estimate high, a low estimate can result in
7963 * devices not showing up correctly on first reference. The call to
7964 * ndi_busop_bus_config needs a timeout value large enough so that
7965 * the map sync call further down is not a noop (i.e. done against
7966 * an empty map when something is infact plugged in). With
7967 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
7968 * soon as the desired device is enumerated via hotplug - so we are
7969 * not committed to waiting the entire time.
7971 * We are typically outside the window, so timeout is 0.
7973 sync_usec
= tgtmap
->tgtmap_create_csync_usec
;
7974 if (tgtmap
->tgtmap_create_window
) {
7975 tsa
= ddi_get_lbolt64() - tgtmap
->tgtmap_create_time
;
7976 if (tsa
< drv_usectohz(sync_usec
)) {
7977 tsa
= drv_usectohz(sync_usec
) - tsa
;
7978 ret
= ndi_busop_bus_config(self
,
7979 flags
, op
, arg
, childp
, (clock_t)tsa
);
7981 tsa
= 0; /* passed window */
7983 /* First one out closes the window. */
7984 tgtmap
->tgtmap_create_window
= 0;
7985 } else if (op
== BUS_CONFIG_ONE
)
7986 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
7988 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
7989 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
7990 goto out
; /* performance path */
7993 * We sync if we were in the window, on the first bus_config_one, and
7994 * every bus_config_all (or bus_config_driver).
7996 if (tsa
|| (tgtmap
->tgtmap_sync_cnt
== 0) ||
7997 (op
!= BUS_CONFIG_ONE
)) {
7999 * Sync current observations in the map and look again. We
8000 * place an upper bound on the amount of time we will wait for
8001 * sync to complete to avoid a bad device causing this
8002 * busconfig operation to hang.
8004 * We are typically stable, so damap_sync returns immediately.
8006 * Max time to wait for sync is settle_usec per possible device.
8008 tgtmap
->tgtmap_sync_cnt
++;
8009 maxdev
= damap_size(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8010 maxdev
= (maxdev
> scsi_hba_map_settle_f
) ? maxdev
:
8011 scsi_hba_map_settle_f
;
8012 sync_usec
= maxdev
* tgtmap
->tgtmap_settle_usec
;
8013 synced
= scsi_tgtmap_sync((scsi_hba_tgtmap_t
*)tgtmap
,
8016 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8017 "tgtmap_sync timeout"));
8021 if (op
== BUS_CONFIG_ONE
)
8022 ret
= scsi_hba_bus_configone(self
, flags
, arg
, childp
);
8024 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8028 if (ret
!= NDI_SUCCESS
) {
8029 if (scsi_hba_bus_config_failure_msg
||
8030 scsi_hba_bus_config_failure_dbg
) {
8031 scsi_hba_bus_config_failure_msg
--;
8032 printf("%s%d: bus_config_tgtmap %p failure on %s: "
8034 ddi_driver_name(self
), ddi_get_instance(self
),
8036 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8039 if (scsi_hba_bus_config_failure_dbg
) {
8040 scsi_hba_bus_config_failure_dbg
--;
8041 debug_enter("config_tgtmap failure");
8043 } else if (scsi_hba_bus_config_success_msg
||
8044 scsi_hba_bus_config_success_dbg
) {
8045 scsi_hba_bus_config_success_msg
--;
8046 printf("%s%d: bus_config_tgtmap %p success on %s: %d %d\n",
8047 ddi_driver_name(self
), ddi_get_instance(self
),
8049 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8051 if (scsi_hba_bus_config_success_dbg
) {
8052 scsi_hba_bus_config_success_dbg
--;
8053 debug_enter("config_tgtmap success");
8061 scsi_hba_bus_unconfig_tgtmap(dev_info_t
*self
, uint_t flags
,
8062 ddi_bus_config_op_t op
, void *arg
)
8064 int ret
= NDI_FAILURE
;
8067 case BUS_UNCONFIG_ONE
:
8068 case BUS_UNCONFIG_DRIVER
:
8069 case BUS_UNCONFIG_ALL
:
8076 if (ret
== NDI_SUCCESS
) {
8077 flags
&= ~NDI_DEVI_REMOVE
;
8078 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8084 scsi_hba_bus_config_iportmap(dev_info_t
*self
, uint_t flags
,
8085 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8087 scsi_hba_tran_t
*tran
;
8088 impl_scsi_iportmap_t
*iportmap
;
8091 uint64_t tsa
= 0; /* clock64_t */
8094 int ret
= NDI_FAILURE
;
8096 if ((op
!= BUS_CONFIG_ONE
) && (op
!= BUS_CONFIG_ALL
) &&
8097 (op
!= BUS_CONFIG_DRIVER
))
8100 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8101 iportmap
= (impl_scsi_iportmap_t
*)tran
->tran_iportmap
;
8105 * MPXIO is never a sure thing (and we have mixed children), so
8106 * set NDI_NDI_FALLBACK so that ndi_busop_bus_config will
8107 * search for both devinfo and pathinfo children.
8109 * Future: Remove NDI_MDI_FALLBACK since devcfg.c now looks for
8110 * devinfo/pathinfo children in parallel (instead of old way of
8111 * looking for one form of child and then doing "fallback" to
8112 * look for other form of child).
8114 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
8117 * If bus_config occurred within the map create-to-hotplug_sync window,
8118 * we need the framework to wait for children that are physicaly
8119 * present at map create time to show up (via iportmap hotplug config).
8121 * The duration of this window is specified by the HBA driver at
8122 * scsi_hba_iportmap_create(9F) time (during attach(9E)). Its
8123 * 'csync_usec' value is selected based on how long it takes the HBA
8124 * driver to get from map creation to initial observation for something
8125 * already plugged in. Estimate high, a low estimate can result in
8126 * devices not showing up correctly on first reference. The call to
8127 * ndi_busop_bus_config needs a timeout value large enough so that
8128 * the map sync call further down is not a noop (i.e. done against
8129 * an empty map when something is infact plugged in). With
8130 * BUS_CONFIG_ONE, the call to ndi_busop_bus_config will return as
8131 * soon as the desired device is enumerated via hotplug - so we are
8132 * not committed to waiting the entire time.
8134 * We are typically outside the window, so timeout is 0.
8136 sync_usec
= iportmap
->iportmap_create_csync_usec
;
8137 if (iportmap
->iportmap_create_window
) {
8138 tsa
= ddi_get_lbolt64() - iportmap
->iportmap_create_time
;
8139 if (tsa
< drv_usectohz(sync_usec
)) {
8140 tsa
= drv_usectohz(sync_usec
) - tsa
;
8141 ret
= ndi_busop_bus_config(self
,
8142 flags
, op
, arg
, childp
, (clock_t)tsa
);
8144 tsa
= 0; /* passed window */
8146 /* First one out closes the window. */
8147 iportmap
->iportmap_create_window
= 0;
8148 } else if (op
== BUS_CONFIG_ONE
)
8149 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8151 /* Return if doing a BUS_CONFIG_ONE and we found what we want. */
8152 if ((op
== BUS_CONFIG_ONE
) && (ret
== NDI_SUCCESS
))
8153 goto out
; /* performance path */
8156 * We sync if we were in the window, on the first bus_config_one, and
8157 * every bus_config_all (or bus_config_driver).
8159 if (tsa
|| (iportmap
->iportmap_sync_cnt
== 0) ||
8160 (op
!= BUS_CONFIG_ONE
)) {
8162 * Sync current observations in the map and look again. We
8163 * place an upper bound on the amount of time we will wait for
8164 * sync to complete to avoid a bad device causing this
8165 * busconfig operation to hang.
8167 * We are typically stable, so damap_sync returns immediately.
8169 * Max time to wait for sync is settle_usec times settle factor.
8171 iportmap
->iportmap_sync_cnt
++;
8172 synced
= damap_sync(iportmap
->iportmap_dam
, sync_usec
);
8174 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
8175 "iportmap_sync timeout"));
8179 if (op
== BUS_CONFIG_ONE
) {
8180 /* create the iport node child */
8181 scsi_hba_devi_enter(self
, &circ
);
8182 if ((child
= scsi_hba_bus_config_port(self
, (char *)arg
,
8183 SE_BUSCONFIG
)) != NULL
) {
8185 ndi_hold_devi(child
);
8190 scsi_hba_devi_exit(self
, circ
);
8192 ret
= ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0);
8196 if (ret
!= NDI_SUCCESS
) {
8197 if (scsi_hba_bus_config_failure_msg
||
8198 scsi_hba_bus_config_failure_dbg
) {
8199 scsi_hba_bus_config_failure_msg
--;
8200 printf("%s%d: bus_config_iportmap %p failure on %s: "
8202 ddi_driver_name(self
), ddi_get_instance(self
),
8204 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8207 if (scsi_hba_bus_config_failure_dbg
) {
8208 scsi_hba_bus_config_failure_dbg
--;
8209 debug_enter("config_iportmap failure");
8211 } else if (scsi_hba_bus_config_success_msg
||
8212 scsi_hba_bus_config_success_dbg
) {
8213 scsi_hba_bus_config_success_msg
--;
8214 printf("%s%d: bus_config_iportmap %p success on %s: %d %d\n",
8215 ddi_driver_name(self
), ddi_get_instance(self
),
8217 (op
== BUS_CONFIG_ONE
) ? (char *)arg
: "ALL",
8219 if (scsi_hba_bus_config_success_dbg
) {
8220 scsi_hba_bus_config_success_dbg
--;
8221 debug_enter("config_iportmap success");
8229 scsi_hba_bus_unconfig_iportmap(dev_info_t
*self
, uint_t flags
,
8230 ddi_bus_config_op_t op
, void *arg
)
8232 flags
&= ~NDI_DEVI_REMOVE
;
8233 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8237 * SCSI HBA bus config enumeration entry point. Called via the bus_ops
8238 * bus_config entry point for all SCSA HBA drivers.
8240 * o If an HBA implements its own bus_config via tran_bus_config then we
8241 * invoke it. An HBA that implements its own tran_bus_config entry point
8242 * may still call back into common SCSA code bus_config code for:
8244 * o SPI bus_config (scsi_hba_bus_spi)
8245 * o LUN and secondary function enumeration (scsi_hba_enum_lsf_of_t()).
8246 * o configuration of a specific device (scsi_device_config).
8247 * o determining 1275 SCSI nodename and compatible property
8248 * (scsi_hba_nodename_compatible_get/_free).
8250 * o Otherwise we implement a SCSI parallel interface (spi) bus config.
8252 * Return NDI_SUCCESS if we might have created a new node.
8253 * Return NDI_FAILURE if we definitely did not create a new node.
8256 scsi_hba_bus_config(dev_info_t
*self
, uint_t flags
,
8257 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
8259 scsi_hba_tran_t
*tran
;
8262 /* make sure that we will not disappear */
8263 ASSERT(DEVI(self
)->devi_ref
);
8265 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
8267 /* NULL tran driver.conf config (used by cmdk). */
8268 if ((op
== BUS_CONFIG_ONE
) || (flags
& NDI_DRV_CONF_REPROBE
))
8269 flags
|= NDI_CONFIG_REPROBE
;
8270 return (ndi_busop_bus_config(self
, flags
, op
, arg
, childp
, 0));
8273 /* Check if self is HBA-only node. */
8274 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8275 /* The bus_config request is to configure iports below HBA. */
8279 * Sparc's 'boot-device' OBP property value lacks an /iport@X/
8280 * component. Prior to the mount of root, we drive a disk@
8281 * BUS_CONFIG_ONE operatino down a level to resolve an
8282 * OBP 'boot-device' path.
8284 * Future: Add (modrootloaded == 0) below, and insure that
8285 * all attempts bus_conf of 'bo_name' (in OBP form) occur
8286 * prior to 'modrootloaded = 1;' assignment in vfs_mountroot.
8288 if ((op
== BUS_CONFIG_ONE
) &&
8289 (strncmp((char *)arg
, "disk@", strlen("disk@")) == 0)) {
8290 return (scsi_hba_bus_config_prom_node(self
,
8291 flags
, arg
, childp
));
8295 if (tran
->tran_iportmap
) {
8296 /* config based on scsi_hba_iportmap API */
8297 ret
= scsi_hba_bus_config_iportmap(self
,
8298 flags
, op
, arg
, childp
);
8300 /* config based on 'iport_register' API */
8301 ret
= scsi_hba_bus_config_iports(self
,
8302 flags
, op
, arg
, childp
);
8307 /* Check to see how the iport/HBA does target/lun bus config. */
8308 if (tran
->tran_bus_config
) {
8309 /* HBA config based on Sun-private/legacy tran_bus_config */
8310 ret
= tran
->tran_bus_config(self
, flags
, op
, arg
, childp
);
8311 } else if (tran
->tran_tgtmap
) {
8312 /* SCSAv3 config based on scsi_hba_tgtmap_*() API */
8313 ret
= scsi_hba_bus_config_tgtmap(self
, flags
, op
, arg
, childp
);
8315 /* SCSA config based on SCSI Parallel Interconnect */
8316 ret
= scsi_hba_bus_config_spi(self
, flags
, op
, arg
, childp
);
8322 * Called via the bus_ops bus_unconfig entry point for SCSI HBA drivers.
8325 scsi_hba_bus_unconfig(dev_info_t
*self
, uint_t flags
,
8326 ddi_bus_config_op_t op
, void *arg
)
8329 scsi_hba_tran_t
*tran
;
8332 tran
= ddi_get_driver_private(self
);
8334 /* NULL tran driver.conf unconfig (used by cmdk). */
8335 return (ndi_busop_bus_unconfig(self
, flags
, op
, arg
));
8339 * Purge barrier/probe node children. We do this prior to
8340 * tran_bus_unconfig in case the unconfig implementation calls back
8341 * into the common code at a different enumeration level, such a
8342 * scsi_device_config, which still creates barrier/probe nodes.
8344 scsi_hba_devi_enter(self
, &circ
);
8345 scsi_hba_barrier_purge(self
);
8346 scsi_hba_devi_exit(self
, circ
);
8348 /* DEBUG: for testing, allow bus_unconfig do drive removal. */
8349 if (scsi_hba_bus_unconfig_remove
)
8350 flags
|= NDI_DEVI_REMOVE
;
8352 /* Check if self is HBA-only node. */
8353 if (tran
->tran_hba_flags
& SCSI_HBA_HBA
) {
8354 /* The bus_config request is to unconfigure iports below HBA. */
8355 if (tran
->tran_iportmap
) {
8356 /* SCSAv3 unconfig based on scsi_hba_iportmap API */
8357 ret
= scsi_hba_bus_unconfig_iportmap(self
,
8359 } else if (tran
->tran_bus_unconfig
) {
8360 /* HBA unconfig based on Sun-private/legacy API */
8361 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8363 /* Standard framework unconfig. */
8364 ret
= ndi_busop_bus_unconfig(self
, flags
, op
, arg
);
8369 /* Check to see how the iport/HBA does target/lun bus unconfig. */
8370 if (tran
->tran_bus_unconfig
) {
8371 /* HBA unconfig based on Sun-private/legacy tran_bus_unconfig */
8372 ret
= tran
->tran_bus_unconfig(self
, flags
, op
, arg
);
8373 } else if (tran
->tran_tgtmap
) {
8374 /* SCSAv3 unconfig based on scsi_hba_tgtmap_*() API */
8375 ret
= scsi_hba_bus_unconfig_tgtmap(self
, flags
, op
, arg
);
8377 /* SCSA unconfig based on SCSI Parallel Interconnect */
8378 ret
= scsi_hba_bus_unconfig_spi(self
, flags
, op
, arg
);
8384 scsi_tgtmap_scsi_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8386 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8387 dev_info_t
*self
= tran
->tran_iport_dip
;
8388 impl_scsi_tgtmap_t
*tgtmap
;
8392 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8393 tgtaddr
= damap_id2addr(mapp
, tgtid
);
8395 if (scsi_lunmap_create(self
, tgtmap
, tgtaddr
) != DDI_SUCCESS
) {
8396 SCSI_HBA_LOG((_LOG_NF(WARN
),
8397 "failed to create lunmap for %s", tgtaddr
));
8400 mt
= ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8401 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8403 mt
|= scsi_hba_log_mt_disable
;
8405 cfg_status
= scsi_hba_bus_config_taddr(self
, tgtaddr
, mt
, SE_HP
);
8406 if (cfg_status
!= NDI_SUCCESS
) {
8407 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s config status %d",
8408 damap_name(mapp
), tgtaddr
, cfg_status
));
8409 scsi_lunmap_destroy(self
, tgtmap
, tgtaddr
);
8410 return (DAM_FAILURE
);
8413 return (DAM_SUCCESS
);
8418 scsi_tgtmap_scsi_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8420 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8421 dev_info_t
*self
= tran
->tran_iport_dip
;
8422 impl_scsi_tgtmap_t
*tgtmap
;
8425 tgtmap
= (impl_scsi_tgtmap_t
*)tran
->tran_tgtmap
;
8426 tgt_addr
= damap_id2addr(mapp
, tgtid
);
8428 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
),
8430 scsi_lunmap_destroy(self
, tgtmap
, tgt_addr
);
8431 return (DAM_SUCCESS
);
8435 scsi_tgtmap_smp_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8437 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8438 dev_info_t
*self
= tran
->tran_iport_dip
;
8441 addr
= damap_id2addr(mapp
, tgtid
);
8442 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8444 return ((smp_hba_bus_config_taddr(self
, addr
) == NDI_SUCCESS
) ?
8445 DAM_SUCCESS
: DAM_FAILURE
);
8449 scsi_tgtmap_smp_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
8451 scsi_hba_tran_t
*tran
= (scsi_hba_tran_t
*)arg
;
8452 dev_info_t
*self
= tran
->tran_iport_dip
;
8455 char nameaddr
[SCSI_MAXNAMELEN
];
8458 addr
= damap_id2addr(mapp
, tgtid
);
8459 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
8461 (void) snprintf(nameaddr
, sizeof (nameaddr
), "smp@%s", addr
);
8462 scsi_hba_devi_enter(self
, &circ
);
8463 if ((child
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
8464 scsi_hba_devi_exit(self
, circ
);
8465 return (DAM_SUCCESS
);
8468 if (ndi_devi_offline(child
,
8469 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
8470 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8471 "devinfo smp@%s offlined and removed", addr
));
8472 } else if (ndi_devi_device_remove(child
)) {
8473 /* Offline/remove failed, note new device_remove */
8474 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
8475 "devinfo smp@%s offline failed, device_remove",
8478 scsi_hba_devi_exit(self
, circ
);
8479 return (DAM_SUCCESS
);
8484 scsi_tgtmap_smp_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8487 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8488 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8490 if (tgtmap
->tgtmap_activate_cb
) {
8491 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8492 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8495 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8496 tgt_addr
, SCSI_TGT_SMP_DEVICE
, tgt_privp
);
8502 scsi_tgtmap_smp_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8503 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8505 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8506 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8507 boolean_t tgtmap_rereport
;
8508 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8510 if (tgtmap
->tgtmap_deactivate_cb
) {
8511 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8512 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8513 tgt_addr
, damap_rsn
));
8515 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8516 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8517 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8518 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8519 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8520 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8522 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8523 "%s @%s deactivated with unknown rsn",
8524 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
]),
8529 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8530 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8531 SCSI_TGT_SMP_DEVICE
, tgt_privp
, tgtmap_rsn
);
8533 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8534 (tgtmap_rereport
== B_FALSE
)) {
8535 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8536 "%s enumeration failed, no more retries until "
8537 "config change occurs", tgt_addr
));
8544 scsi_tgtmap_scsi_activate(void *map_priv
, char *tgt_addr
, int addrid
,
8547 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8548 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8550 if (tgtmap
->tgtmap_activate_cb
) {
8551 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s activated",
8552 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8555 (*tgtmap
->tgtmap_activate_cb
)(tgtmap
->tgtmap_mappriv
,
8556 tgt_addr
, SCSI_TGT_SCSI_DEVICE
, tgt_privp
);
8562 scsi_tgtmap_scsi_deactivate(void *map_priv
, char *tgt_addr
, int addrid
,
8563 void *tgt_privp
, damap_deact_rsn_t damap_rsn
)
8565 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)map_priv
;
8566 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8567 boolean_t tgtmap_rereport
;
8568 scsi_tgtmap_deact_rsn_t tgtmap_rsn
;
8570 if (tgtmap
->tgtmap_deactivate_cb
) {
8571 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s @%s deactivated %d",
8572 damap_name(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8573 tgt_addr
, damap_rsn
));
8575 if (damap_rsn
== DAMAP_DEACT_RSN_GONE
)
8576 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_GONE
;
8577 else if (damap_rsn
== DAMAP_DEACT_RSN_CFG_FAIL
)
8578 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_CFG_FAIL
;
8579 else if (damap_rsn
== DAMAP_DEACT_RSN_UNSTBL
)
8580 tgtmap_rsn
= SCSI_TGT_DEACT_RSN_UNSTBL
;
8582 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
8583 "%s @%s deactivated with unknown rsn", damap_name(
8584 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]),
8589 tgtmap_rereport
= (*tgtmap
->tgtmap_deactivate_cb
)
8590 (tgtmap
->tgtmap_mappriv
, tgt_addr
,
8591 SCSI_TGT_SCSI_DEVICE
, tgt_privp
, tgtmap_rsn
);
8593 if ((tgtmap_rsn
== SCSI_TGT_DEACT_RSN_CFG_FAIL
) &&
8594 (tgtmap_rereport
== B_FALSE
)) {
8595 SCSI_HBA_LOG((_LOG(WARN
), NULL
, self
,
8596 "%s enumeration failed, no more retries until "
8597 "config change occurs", tgt_addr
));
8604 scsi_hba_tgtmap_create(dev_info_t
*self
, scsi_tgtmap_mode_t mode
,
8605 int csync_usec
, int settle_usec
, void *tgtmap_priv
,
8606 scsi_tgt_activate_cb_t activate_cb
, scsi_tgt_deactivate_cb_t deactivate_cb
,
8607 scsi_hba_tgtmap_t
**handle
)
8609 scsi_hba_tran_t
*tran
;
8612 impl_scsi_tgtmap_t
*tgtmap
;
8613 damap_rptmode_t rpt_style
;
8614 char *scsi_binding_set
;
8617 if (self
== NULL
|| csync_usec
== 0 ||
8618 settle_usec
== 0 || handle
== NULL
)
8619 return (DDI_FAILURE
);
8623 if (scsi_hba_iport_unit_address(self
) == NULL
)
8624 return (DDI_FAILURE
);
8627 case SCSI_TM_FULLSET
:
8628 rpt_style
= DAMAP_REPORT_FULLSET
;
8630 case SCSI_TM_PERADDR
:
8631 rpt_style
= DAMAP_REPORT_PERADDR
;
8634 return (DDI_FAILURE
);
8637 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
8640 return (DDI_FAILURE
);
8642 tgtmap
= kmem_zalloc(sizeof (*tgtmap
), KM_SLEEP
);
8643 tgtmap
->tgtmap_tran
= tran
;
8644 tgtmap
->tgtmap_activate_cb
= activate_cb
;
8645 tgtmap
->tgtmap_deactivate_cb
= deactivate_cb
;
8646 tgtmap
->tgtmap_mappriv
= tgtmap_priv
;
8648 tgtmap
->tgtmap_create_window
= 1; /* start with window */
8649 tgtmap
->tgtmap_create_time
= ddi_get_lbolt64();
8650 tgtmap
->tgtmap_create_csync_usec
= csync_usec
;
8651 tgtmap
->tgtmap_settle_usec
= settle_usec
;
8652 tgtmap
->tgtmap_sync_cnt
= 0;
8654 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
8655 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
8656 scsi_enumeration
) & SCSI_ENUMERATION_MT_TARGET_DISABLE
) ?
8657 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
8659 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.scsi",
8660 ddi_driver_name(self
), ddi_get_instance(self
));
8661 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8662 if (damap_create(context
, rpt_style
, optflags
, settle_usec
,
8663 tgtmap
, scsi_tgtmap_scsi_activate
, scsi_tgtmap_scsi_deactivate
,
8664 tran
, scsi_tgtmap_scsi_config
, scsi_tgtmap_scsi_unconfig
,
8665 &mapp
) != DAM_SUCCESS
) {
8666 kmem_free(tgtmap
, sizeof (*tgtmap
));
8667 return (DDI_FAILURE
);
8669 tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
] = mapp
;
8671 (void) snprintf(context
, sizeof (context
), "%s%d.tgtmap.smp",
8672 ddi_driver_name(self
), ddi_get_instance(self
));
8673 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8674 if (damap_create(context
, rpt_style
, optflags
,
8675 settle_usec
, tgtmap
, scsi_tgtmap_smp_activate
,
8676 scsi_tgtmap_smp_deactivate
,
8677 tran
, scsi_tgtmap_smp_config
, scsi_tgtmap_smp_unconfig
,
8678 &mapp
) != DAM_SUCCESS
) {
8679 damap_destroy(tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
]);
8680 kmem_free(tgtmap
, sizeof (*tgtmap
));
8681 return (DDI_FAILURE
);
8683 tgtmap
->tgtmap_dam
[SCSI_TGT_SMP_DEVICE
] = mapp
;
8685 tran
->tran_tgtmap
= (scsi_hba_tgtmap_t
*)tgtmap
;
8686 *handle
= (scsi_hba_tgtmap_t
*)tgtmap
;
8689 * We have now set tran_tgtmap, marking the tran as using tgtmap
8690 * enumeration services. To prevent the generation of legacy spi
8691 * 'binding-set' compatible forms, remove the 'scsi-binding-set'
8694 if (ddi_prop_lookup_string(DDI_DEV_T_ANY
, self
,
8695 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-binding-set",
8696 &scsi_binding_set
) == DDI_PROP_SUCCESS
) {
8697 if (strcmp(scsi_binding_set
, scsi_binding_set_spi
) == 0)
8698 (void) ndi_prop_remove(DDI_DEV_T_NONE
, self
,
8699 "scsi-binding-set");
8700 ddi_prop_free(scsi_binding_set
);
8702 return (DDI_SUCCESS
);
8706 scsi_hba_tgtmap_destroy(scsi_hba_tgtmap_t
*handle
)
8708 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8709 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8712 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8713 if (tgtmap
->tgtmap_dam
[i
]) {
8714 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8715 "%s", damap_name(tgtmap
->tgtmap_dam
[i
])));
8716 damap_destroy(tgtmap
->tgtmap_dam
[i
]);
8719 kmem_free(tgtmap
, sizeof (*tgtmap
));
8722 /* return 1 if all maps ended up syned */
8724 scsi_tgtmap_sync(scsi_hba_tgtmap_t
*handle
, int sync_usec
)
8726 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8727 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8732 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8733 if (tgtmap
->tgtmap_dam
[i
]) {
8734 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync begin",
8735 damap_name(tgtmap
->tgtmap_dam
[i
])));
8736 synced
= damap_sync(tgtmap
->tgtmap_dam
[i
], sync_usec
);
8737 all_synced
&= synced
;
8738 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s sync end %d",
8739 damap_name(tgtmap
->tgtmap_dam
[i
]), synced
));
8743 return (all_synced
);
8746 /* return 1 if all maps ended up empty */
8748 scsi_tgtmap_is_empty(scsi_hba_tgtmap_t
*handle
)
8750 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8751 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8756 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8757 if (tgtmap
->tgtmap_dam
[i
]) {
8758 empty
= damap_is_empty(tgtmap
->tgtmap_dam
[i
]);
8760 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s is_empty %d",
8761 damap_name(tgtmap
->tgtmap_dam
[i
]), empty
));
8769 scsi_tgtmap_beginf(scsi_hba_tgtmap_t
*handle
, boolean_t do_begin
)
8771 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8772 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8774 int rv
= DAM_SUCCESS
;
8777 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8778 if (tgtmap
->tgtmap_dam
[i
] == NULL
) {
8782 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8783 if (do_begin
== B_TRUE
) {
8784 if (i
== SCSI_TGT_SCSI_DEVICE
) {
8786 * In scsi_device context, so we have the
8787 * 'context' string, diagnose the case where
8788 * the tgtmap caller is failing to make
8789 * forward progress, i.e. the caller is never
8790 * completing an observation by calling
8791 * scsi_hbg_tgtmap_set_end. If this occurs,
8792 * the solaris target/lun state may be out
8793 * of sync with hardware.
8795 if (tgtmap
->tgtmap_reports
++ >=
8796 scsi_hba_tgtmap_reports_max
) {
8797 tgtmap
->tgtmap_noisy
++;
8798 if (tgtmap
->tgtmap_noisy
== 1) {
8799 SCSI_HBA_LOG((_LOG(WARN
),
8801 "%s: failing tgtmap begin",
8807 rv
= damap_addrset_begin(tgtmap
->tgtmap_dam
[i
]);
8809 rv
= damap_addrset_flush(tgtmap
->tgtmap_dam
[i
]);
8812 if (rv
!= DAM_SUCCESS
) {
8813 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8815 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8819 return ((rv
== DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8824 scsi_hba_tgtmap_set_begin(scsi_hba_tgtmap_t
*handle
)
8826 return (scsi_tgtmap_beginf(handle
, B_TRUE
));
8830 scsi_hba_tgtmap_set_flush(scsi_hba_tgtmap_t
*handle
)
8832 return (scsi_tgtmap_beginf(handle
, B_FALSE
));
8836 scsi_hba_tgtmap_set_add(scsi_hba_tgtmap_t
*handle
,
8837 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8839 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8840 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8842 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8843 return (DDI_FAILURE
);
8845 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8846 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8848 return ((damap_addrset_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
,
8849 NULL
, NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8854 scsi_hba_tgtmap_set_end(scsi_hba_tgtmap_t
*handle
, uint_t flags
)
8856 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8857 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8859 int rv
= DDI_SUCCESS
;
8862 tgtmap
->tgtmap_reports
= tgtmap
->tgtmap_noisy
= 0;
8864 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8865 if (tgtmap
->tgtmap_dam
[i
] == NULL
)
8867 context
= damap_name(tgtmap
->tgtmap_dam
[i
]);
8868 if (damap_addrset_end(
8869 tgtmap
->tgtmap_dam
[i
], 0) != DAM_SUCCESS
) {
8870 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s FAIL", context
));
8875 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
, "%s", context
));
8881 scsi_hba_tgtmap_tgt_add(scsi_hba_tgtmap_t
*handle
,
8882 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
, void *tgt_priv
)
8885 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8886 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8888 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8889 return (DDI_FAILURE
);
8891 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8892 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8894 return ((damap_addr_add(tgtmap
->tgtmap_dam
[tgt_type
], tgt_addr
, NULL
,
8895 NULL
, tgt_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8899 scsi_hba_tgtmap_tgt_remove(scsi_hba_tgtmap_t
*handle
,
8900 scsi_tgtmap_tgt_type_t tgt_type
, char *tgt_addr
)
8902 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8903 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8905 if (tgt_type
>= SCSI_TGT_NTYPES
|| !tgtmap
->tgtmap_dam
[tgt_type
])
8906 return (DDI_FAILURE
);
8908 SCSI_HBA_LOG((_LOGTGT
, self
, NULL
,
8909 "%s @%s", damap_name(tgtmap
->tgtmap_dam
[tgt_type
]), tgt_addr
));
8911 return ((damap_addr_del(tgtmap
->tgtmap_dam
[tgt_type
],
8912 tgt_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
8916 scsi_hba_tgtmap_lookup(scsi_hba_tgtmap_t
*handle
,
8917 char *tgt_addr
, scsi_tgtmap_tgt_type_t
*r_type
)
8919 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)handle
;
8920 dev_info_t
*self
= tgtmap
->tgtmap_tran
->tran_iport_dip
;
8924 for (i
= 0; i
< SCSI_TGT_NTYPES
; i
++) {
8925 tgtid
= damap_lookup(tgtmap
->tgtmap_dam
[i
], tgt_addr
);
8926 if (tgtid
!= NODAM
) {
8928 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8929 "%s @%s found: type %d",
8930 damap_name(tgtmap
->tgtmap_dam
[i
]), tgt_addr
, i
));
8931 damap_id_rele(tgtmap
->tgtmap_dam
[i
], tgtid
);
8932 return (DDI_SUCCESS
);
8936 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
8937 "%s%d.tgtmap @%s not found",
8938 ddi_driver_name(self
), ddi_get_instance(self
), tgt_addr
));
8939 return (DDI_FAILURE
);
8943 * Return the unit-address of an 'iport' node, or NULL for non-iport node.
8946 scsi_hba_iport_unit_address(dev_info_t
*self
)
8949 * NOTE: Since 'self' could be a SCSA iport node or a SCSA HBA node,
8950 * we can't use SCSA flavors: the flavor of a SCSA HBA node is not
8951 * established/owned by SCSA, it is established by the nexus that
8952 * created the SCSA HBA node (PCI) as a child.
8954 * NOTE: If we want to support a node_name other than "iport" for
8955 * an iport node then we can add support for a "scsa-iport-node-name"
8956 * property on the SCSA HBA node. A SCSA HBA driver would set this
8957 * property on the SCSA HBA node prior to using the iport API.
8959 if (strcmp(ddi_node_name(self
), "iport") == 0)
8960 return (ddi_get_name_addr(self
));
8966 * Define a SCSI initiator port (bus/channel) for an HBA card that needs to
8967 * support multiple SCSI ports, but only has a single HBA devinfo node. This
8968 * function should be called from the HBA's attach(9E) implementation (when
8969 * processing the HBA devinfo node attach) after the number of SCSI ports on
8970 * the card is known or when the HBA driver DR handler detects a new port.
8971 * The function returns 0 on failure and 1 on success.
8973 * The implementation will add the port value into the "scsi-iports" property
8974 * value maintained on the HBA node as. These properties are used by the generic
8975 * scsi bus_config implementation to dynamicaly enumerate the specified iport
8976 * children. The enumeration code will, on demand, create the appropriate
8977 * iport children with a SCSI_ADDR_PROP_IPORTUA unit address. This node will
8978 * bind to the same driver as the HBA node itself. This means that an HBA
8979 * driver that uses iports should expect probe(9E), attach(9E), and detach(9E)
8980 * calls on the iport children of the HBA. If configuration for all ports was
8981 * already done during HBA node attach, the driver should just return
8982 * DDI_SUCCESS when confronted with an iport node.
8984 * A maximum of 32 iport ports are supported per HBA devinfo node.
8986 * A NULL "port" can be used to indicate that the framework should enumerate
8987 * target children on the HBA node itself, in addition to enumerating target
8988 * children on any iport nodes declared. There are two reasons that an HBA may
8989 * wish to have target children enumerated on both the HBA node and iport
8992 * o If, in the past, HBA hardware had only a single physical port but now
8993 * supports multiple physical ports, the updated driver that supports
8994 * multiple physical ports may want to avoid /devices path upgrade issues
8995 * by enumerating the first physical port under the HBA instead of as a
8998 * o Some hardware RAID HBA controllers (mlx, chs, etc) support multiple
8999 * SCSI physical ports configured so that various physical devices on
9000 * the physical ports are amalgamated into virtual devices on a virtual
9001 * port. Amalgamated physical devices no longer appear to the host OS
9002 * on the physical ports, but other non-amalgamated devices may still be
9003 * visible on the physical ports. These drivers use a model where the
9004 * physical ports are iport nodes and the HBA node is the virtual port to
9005 * the configured virtual devices.
9008 scsi_hba_iport_register(dev_info_t
*self
, char *port
)
9010 unsigned int ports
= 0;
9012 char **iports
, **newiports
;
9016 return (DDI_FAILURE
);
9018 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9019 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9022 if (ports
>= SCSI_HBA_MAX_IPORTS
) {
9023 ddi_prop_free(iports
);
9024 return (DDI_FAILURE
);
9027 if (rval
== DDI_PROP_SUCCESS
) {
9028 for (i
= 0; i
< ports
; i
++) {
9029 if (strcmp(port
, iports
[i
]) == 0) {
9030 /* iport already registered */
9031 ddi_prop_free(iports
);
9032 return (DDI_SUCCESS
);
9037 newiports
= kmem_alloc((sizeof (char *) * (ports
+ 1)), KM_SLEEP
);
9039 for (i
= 0; i
< ports
; i
++) {
9040 newiports
[i
] = strdup(iports
[i
]);
9042 newiports
[ports
] = strdup(port
);
9045 if (ddi_prop_update_string_array(DDI_DEV_T_NONE
, self
,
9046 "scsi-iports", newiports
, ports
) != DDI_PROP_SUCCESS
) {
9047 SCSI_HBA_LOG((_LOG(WARN
), self
, NULL
,
9048 "failed to establish %s %s",
9049 SCSI_ADDR_PROP_IPORTUA
, port
));
9055 /* If there is iport exist, free property */
9057 ddi_prop_free(iports
);
9058 for (i
= 0; i
< ports
; i
++) {
9059 strfree(newiports
[i
]);
9061 kmem_free(newiports
, (sizeof (char *)) * ports
);
9067 * Check if the HBA has any scsi_hba_iport_register()ed children.
9070 scsi_hba_iport_exist(dev_info_t
*self
)
9072 unsigned int ports
= 0;
9076 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9077 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9080 if (rval
!= DDI_PROP_SUCCESS
)
9083 /* If there is now at least 1 iport, then iports is valid */
9088 ddi_prop_free(iports
);
9094 scsi_hba_iport_find(dev_info_t
*self
, char *portnm
)
9098 unsigned int num_iports
= 0;
9099 int rval
= DDI_FAILURE
;
9101 dev_info_t
*child
= NULL
;
9103 /* check to see if this is an HBA that defined scsi iports */
9104 rval
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9105 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9108 if (rval
!= DDI_SUCCESS
) {
9111 ASSERT(num_iports
> 0);
9113 /* check to see if this port was registered */
9114 for (i
= 0; i
< num_iports
; i
++) {
9115 if (strcmp(iports
[i
], portnm
) == 0)
9119 if (i
== num_iports
) {
9124 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9125 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s", portnm
);
9126 rval
= ndi_devi_config_one(self
, addr
, &child
, NDI_NO_EVENT
);
9127 kmem_free(addr
, SCSI_MAXNAMELEN
);
9129 if (rval
!= DDI_SUCCESS
) {
9133 ddi_prop_free(iports
);
9138 * Search/create the specified iport node
9141 scsi_hba_bus_config_port(dev_info_t
*self
, char *nameaddr
, scsi_enum_t se
)
9143 dev_info_t
*child
; /* iport child of HBA node */
9144 scsi_hba_tran_t
*tran
;
9149 * See if the iport node already exists.
9151 addr
= nameaddr
+ strlen("iport@");
9152 if (child
= ndi_devi_findchild(self
, nameaddr
)) {
9153 if (ndi_devi_device_isremoved(child
)) {
9154 if ((se
== SE_HP
) || !ndi_dev_is_hotplug_node(child
)) {
9155 if (ndi_devi_device_insert(child
))
9156 SCSI_HBA_LOG((_LOGCFG
, self
, NULL
,
9157 "devinfo iport@%s device_reinsert",
9167 * If config based on scsi_hba_iportmap API, only allow create
9170 tran
= ndi_flavorv_get(self
, SCSA_FLAVOR_SCSI_DEVICE
);
9172 if (tran
->tran_iportmap
&& (se
!= SE_HP
))
9175 /* allocate and initialize a new "iport" node */
9176 ndi_devi_alloc_sleep(self
, "iport",
9177 (se
== SE_HP
) ? DEVI_SID_HP_NODEID
: DEVI_SID_NODEID
,
9181 * Set the flavor of the child to be IPORT flavored
9183 ndi_flavor_set(child
, SCSA_FLAVOR_IPORT
);
9186 * Add the SCSI_ADDR_PROP_IPORTUA addressing property for this child.
9187 * This property is used to identify a iport node, and to represent the
9188 * nodes @addr form via node properties.
9190 * Add "compatible" property to the "scsi-iport" node to cause it bind
9191 * to the same driver as the HBA driver. Use the "driver" name
9192 * instead of the "binding name" to distinguish from hw node.
9194 * Give the HBA a chance, via tran_set_name_prop, to set additional
9195 * iport node properties or to change the "compatible" binding
9196 * prior to init_child.
9198 * NOTE: the order of these operations is important so that
9199 * scsi_hba_iport works when called.
9201 compat
= (char *)ddi_driver_name(self
);
9202 if ((ndi_prop_update_string(DDI_DEV_T_NONE
, child
,
9203 SCSI_ADDR_PROP_IPORTUA
, addr
) != DDI_PROP_SUCCESS
) ||
9204 (ndi_prop_update_string_array(DDI_DEV_T_NONE
, child
,
9205 "compatible", &compat
, 1) != DDI_PROP_SUCCESS
) ||
9206 ddi_pathname_obp_set(child
, NULL
) != DDI_SUCCESS
) {
9207 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s failed dynamic decoration",
9209 (void) ddi_remove_child(child
, 0);
9213 * Online/attach in order to get events so devfsadm will
9214 * create public names.
9216 ndi_hold_devi(child
);
9217 if (ndi_devi_online(child
, 0) != NDI_SUCCESS
) {
9218 ndi_rele_devi(child
);
9219 ndi_prop_remove_all(child
);
9220 (void) ndi_devi_free(child
);
9223 ndi_rele_devi(child
);
9231 * Future: When iportmap boot support is added, consider rewriting this to
9232 * perform a scsi_hba_bus_config(BUS_CONFIG_ALL) on self (HBA) followed by
9233 * a scsi_hba_bus_config(BUS_CONFIG_ONE) on each child of self (each iport).
9237 scsi_hba_bus_config_prom_node(dev_info_t
*self
, uint_t flags
,
9238 void *arg
, dev_info_t
**childp
)
9242 int ret
= NDI_FAILURE
;
9243 unsigned int num_iports
= 0;
9244 dev_info_t
*pdip
= NULL
;
9247 /* check to see if this is an HBA that defined scsi iports */
9248 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9249 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9252 if (ret
!= DDI_SUCCESS
) {
9256 ASSERT(num_iports
> 0);
9258 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9262 scsi_hba_devi_enter(self
, &circ
);
9264 /* create iport nodes for each scsi port/bus */
9265 for (i
= 0; i
< num_iports
; i
++) {
9266 bzero(addr
, SCSI_MAXNAMELEN
);
9267 /* Prepend the iport name */
9268 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9270 if (pdip
= scsi_hba_bus_config_port(self
, addr
, SE_BUSCONFIG
)) {
9271 if (ndi_busop_bus_config(self
, NDI_NO_EVENT
,
9272 BUS_CONFIG_ONE
, addr
, &pdip
, 0) !=
9277 * Try to configure child under iport see wehter
9278 * request node is the child of the iport node
9280 if (ndi_devi_config_one(pdip
, arg
, childp
,
9281 NDI_NO_EVENT
) == NDI_SUCCESS
) {
9288 scsi_hba_devi_exit(self
, circ
);
9290 kmem_free(addr
, SCSI_MAXNAMELEN
);
9292 ddi_prop_free(iports
);
9299 * Perform iport port/bus bus_config.
9302 scsi_hba_bus_config_iports(dev_info_t
*self
, uint_t flags
,
9303 ddi_bus_config_op_t op
, void *arg
, dev_info_t
**childp
)
9305 char *nameaddr
, *addr
;
9308 int ret
= NDI_FAILURE
;
9309 unsigned int num_iports
= 0;
9311 /* check to see if this is an HBA that defined scsi iports */
9312 ret
= ddi_prop_lookup_string_array(DDI_DEV_T_ANY
, self
,
9313 DDI_PROP_DONTPASS
| DDI_PROP_NOTPROM
, "scsi-iports", &iports
,
9316 if (ret
!= DDI_SUCCESS
) {
9320 ASSERT(num_iports
> 0);
9322 scsi_hba_devi_enter(self
, &circ
);
9325 case BUS_CONFIG_ONE
:
9326 /* return if this operation is not against an iport node */
9327 nameaddr
= (char *)arg
;
9328 if ((nameaddr
== NULL
) ||
9329 (strncmp(nameaddr
, "iport@", strlen("iport@")) != 0)) {
9331 scsi_hba_devi_exit(self
, circ
);
9332 ddi_prop_free(iports
);
9336 /* parse the port number from "iport@%s" */
9337 addr
= nameaddr
+ strlen("iport@");
9339 /* check to see if this port was registered */
9340 for (i
= 0; i
< num_iports
; i
++) {
9341 if (strcmp((iports
[i
]), addr
) == 0)
9345 if (i
== num_iports
) {
9350 /* create the iport node child */
9351 if (scsi_hba_bus_config_port(self
, nameaddr
, SE_BUSCONFIG
)) {
9356 case BUS_CONFIG_ALL
:
9357 case BUS_CONFIG_DRIVER
:
9358 addr
= kmem_zalloc(SCSI_MAXNAMELEN
, KM_SLEEP
);
9359 /* create iport nodes for each scsi port/bus */
9360 for (i
= 0; i
< num_iports
; i
++) {
9361 bzero(addr
, SCSI_MAXNAMELEN
);
9362 /* Prepend the iport name */
9363 (void) snprintf(addr
, SCSI_MAXNAMELEN
, "iport@%s",
9365 (void) scsi_hba_bus_config_port(self
, addr
,
9369 kmem_free(addr
, SCSI_MAXNAMELEN
);
9373 if (ret
== NDI_SUCCESS
) {
9376 * Mask NDI_PROMNAME since PROM doesn't have iport
9379 flags
&= (~NDI_PROMNAME
);
9381 flags
|= NDI_MDI_FALLBACK
; /* devinfo&pathinfo children */
9382 ret
= ndi_busop_bus_config(self
, flags
, op
,
9385 scsi_hba_devi_exit(self
, circ
);
9387 ddi_prop_free(iports
);
9393 scsi_iportmap_config(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9395 dev_info_t
*self
= (dev_info_t
*)arg
;
9397 char nameaddr
[SCSI_MAXNAMELEN
];
9401 scsi_hba_devi_enter(self
, &circ
);
9403 iport_addr
= damap_id2addr(mapp
, tgtid
);
9404 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9405 "%s @%s", damap_name(mapp
), iport_addr
));
9407 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", iport_addr
);
9408 childp
= scsi_hba_bus_config_port(self
, nameaddr
, SE_HP
);
9409 scsi_hba_devi_exit(self
, circ
);
9410 return (childp
!= NULL
? DAM_SUCCESS
: DAM_FAILURE
);
9414 scsi_iportmap_unconfig(void *arg
, damap_t
*mapp
, damap_id_t tgtid
)
9416 dev_info_t
*self
= arg
;
9417 dev_info_t
*childp
; /* iport child of HBA node */
9420 char nameaddr
[SCSI_MAXNAMELEN
];
9421 scsi_hba_tran_t
*tran
;
9423 addr
= damap_id2addr(mapp
, tgtid
);
9424 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s @%s", damap_name(mapp
), addr
));
9426 (void) snprintf(nameaddr
, sizeof (nameaddr
), "iport@%s", addr
);
9427 scsi_hba_devi_enter(self
, &circ
);
9428 if ((childp
= ndi_devi_findchild(self
, nameaddr
)) == NULL
) {
9429 scsi_hba_devi_exit(self
, circ
);
9430 return (DAM_FAILURE
);
9433 tran
= ddi_get_driver_private(childp
);
9436 ndi_hold_devi(childp
);
9437 scsi_hba_devi_exit(self
, circ
);
9440 * A begin/end (clear) against the iport's
9441 * tgtmap will trigger unconfigure of all
9442 * targets on the iport.
9444 * Future: This bit of code only works if the
9445 * target map reporting style is are full
9446 * reports and not per-address. Maybe we
9447 * should plan on handling this by
9448 * auto-unconfiguration when destroying the
9451 (void) scsi_hba_tgtmap_set_begin(tran
->tran_tgtmap
);
9452 (void) scsi_hba_tgtmap_set_end(tran
->tran_tgtmap
, 0);
9454 /* wait for unconfigure */
9455 (void) scsi_tgtmap_sync(tran
->tran_tgtmap
, 0);
9456 empty
= scsi_tgtmap_is_empty(tran
->tran_tgtmap
);
9458 scsi_hba_devi_enter(self
, &circ
);
9459 ndi_rele_devi(childp
);
9461 /* If begin/end/sync ends in empty map, offline/remove. */
9463 if (ndi_devi_offline(childp
,
9464 NDI_DEVFS_CLEAN
| NDI_DEVI_REMOVE
) == DDI_SUCCESS
) {
9465 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9466 "devinfo iport@%s offlined and removed",
9468 } else if (ndi_devi_device_remove(childp
)) {
9469 /* Offline/rem failed, note new device_remove */
9470 SCSI_HBA_LOG((_LOGUNCFG
, self
, NULL
,
9471 "devinfo iport@%s offline failed, "
9472 "device_remove", addr
));
9475 scsi_hba_devi_exit(self
, circ
);
9476 return (empty
? DAM_SUCCESS
: DAM_FAILURE
);
9481 scsi_hba_iportmap_create(dev_info_t
*self
, int csync_usec
, int settle_usec
,
9482 scsi_hba_iportmap_t
**handle
)
9484 scsi_hba_tran_t
*tran
;
9487 impl_scsi_iportmap_t
*iportmap
;
9489 if (self
== NULL
|| csync_usec
== 0 ||
9490 settle_usec
== 0 || handle
== NULL
)
9491 return (DDI_FAILURE
);
9495 if (scsi_hba_iport_unit_address(self
) != NULL
)
9496 return (DDI_FAILURE
);
9498 tran
= (scsi_hba_tran_t
*)ddi_get_driver_private(self
);
9501 return (DDI_FAILURE
);
9503 (void) snprintf(context
, sizeof (context
), "%s%d.iportmap",
9504 ddi_driver_name(self
), ddi_get_instance(self
));
9506 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
9507 settle_usec
, NULL
, NULL
, NULL
, self
,
9508 scsi_iportmap_config
, scsi_iportmap_unconfig
, &mapp
) !=
9510 return (DDI_FAILURE
);
9512 iportmap
= kmem_zalloc(sizeof (*iportmap
), KM_SLEEP
);
9513 iportmap
->iportmap_hba_dip
= self
;
9514 iportmap
->iportmap_dam
= mapp
;
9516 iportmap
->iportmap_create_window
= 1; /* start with window */
9517 iportmap
->iportmap_create_time
= ddi_get_lbolt64();
9518 iportmap
->iportmap_create_csync_usec
= csync_usec
;
9519 iportmap
->iportmap_settle_usec
= settle_usec
;
9520 iportmap
->iportmap_sync_cnt
= 0;
9522 tran
->tran_iportmap
= (scsi_hba_iportmap_t
*)iportmap
;
9523 *handle
= (scsi_hba_iportmap_t
*)iportmap
;
9525 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
, "%s", damap_name(mapp
)));
9526 return (DDI_SUCCESS
);
9530 scsi_hba_iportmap_destroy(scsi_hba_iportmap_t
*handle
)
9532 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9533 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9535 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9536 "%s", damap_name(iportmap
->iportmap_dam
)));
9538 damap_destroy(iportmap
->iportmap_dam
);
9539 kmem_free(iportmap
, sizeof (*iportmap
));
9543 scsi_hba_iportmap_iport_add(scsi_hba_iportmap_t
*handle
,
9544 char *iport_addr
, void *iport_priv
)
9546 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9547 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9549 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9550 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9552 return ((damap_addr_add(iportmap
->iportmap_dam
, iport_addr
, NULL
,
9553 NULL
, iport_priv
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9557 scsi_hba_iportmap_iport_remove(scsi_hba_iportmap_t
*handle
,
9560 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9561 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9563 SCSI_HBA_LOG((_LOGIPT
, self
, NULL
,
9564 "%s @%s", damap_name(iportmap
->iportmap_dam
), iport_addr
));
9566 return ((damap_addr_del(iportmap
->iportmap_dam
,
9567 iport_addr
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9571 scsi_hba_iportmap_lookup(scsi_hba_iportmap_t
*handle
,
9574 impl_scsi_iportmap_t
*iportmap
= (impl_scsi_iportmap_t
*)handle
;
9575 dev_info_t
*self
= iportmap
->iportmap_hba_dip
;
9578 iportid
= damap_lookup(iportmap
->iportmap_dam
, iport_addr
);
9579 if (iportid
!= NODAM
) {
9580 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9582 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9583 damap_id_rele(iportmap
->iportmap_dam
, iportid
);
9584 return (DDI_SUCCESS
);
9587 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9589 damap_name(iportmap
->iportmap_dam
), iport_addr
));
9590 return (DDI_FAILURE
);
9595 scsi_lunmap_config(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9597 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9598 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9599 dev_info_t
*self
= tran
->tran_iport_dip
;
9602 addr
= damap_id2addr(lundam
, lunid
);
9603 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9604 "%s @%s", damap_name(lundam
), addr
));
9605 if (scsi_hba_bus_configone_addr(self
, addr
, SE_HP
) != NULL
)
9606 return (DAM_SUCCESS
);
9608 return (DAM_FAILURE
);
9612 scsi_lunmap_unconfig(void *arg
, damap_t
*lundam
, damap_id_t lunid
)
9614 impl_scsi_tgtmap_t
*tgtmap
= (impl_scsi_tgtmap_t
*)arg
;
9615 scsi_hba_tran_t
*tran
= tgtmap
->tgtmap_tran
;
9616 dev_info_t
*self
= tran
->tran_iport_dip
;
9619 addr
= damap_id2addr(lundam
, lunid
);
9620 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
),
9623 scsi_hba_bus_unconfigone_addr(self
, addr
);
9624 return (DAM_SUCCESS
);
9628 scsi_lunmap_create(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9636 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9637 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9639 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9640 tgtid
= damap_lookup(tgtdam
, taddr
);
9641 if (tgtid
== NODAM
) {
9642 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9643 "target %s not found", context
));
9644 return (DDI_FAILURE
);
9647 lundam
= damap_id_priv_get(tgtdam
, tgtid
);
9649 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9650 "lunmap %s already created", context
));
9651 damap_id_rele(tgtdam
, tgtid
);
9652 return (DDI_FAILURE
);
9655 optflags
= (ddi_prop_get_int(DDI_DEV_T_ANY
, self
,
9656 DDI_PROP_NOTPROM
| DDI_PROP_DONTPASS
, "scsi-enumeration",
9657 scsi_enumeration
) & SCSI_ENUMERATION_MT_LUN_DISABLE
) ?
9658 DAMAP_SERIALCONFIG
: DAMAP_MTCONFIG
;
9660 /* NOTE: expected ref at tgtid/taddr: 2: caller + lookup. */
9661 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 2);
9662 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s creat, id %d ref %d",
9663 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9666 if (damap_create(context
, DAMAP_REPORT_FULLSET
, optflags
, 1,
9667 NULL
, NULL
, NULL
, tgtmap
, scsi_lunmap_config
, scsi_lunmap_unconfig
,
9668 &lundam
) != DAM_SUCCESS
) {
9669 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9670 "%s create failed, id %d ref %d",
9671 context
, tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9672 damap_id_rele(tgtdam
, tgtid
);
9673 return (DDI_FAILURE
);
9677 * Return with damap_id_hold at tgtid/taddr from damap_lookup to
9678 * account for damap_id_prv_set below.
9680 damap_id_priv_set(tgtdam
, tgtid
, lundam
);
9681 return (DDI_SUCCESS
);
9685 scsi_lunmap_destroy(dev_info_t
*self
, impl_scsi_tgtmap_t
*tgtmap
, char *taddr
)
9692 (void) snprintf(context
, sizeof (context
), "%s%d.%s.lunmap",
9693 ddi_driver_name(self
), ddi_get_instance(self
), taddr
);
9695 tgtdam
= tgtmap
->tgtmap_dam
[SCSI_TGT_SCSI_DEVICE
];
9696 tgtid
= damap_lookup(tgtdam
, taddr
);
9697 if (tgtid
== NODAM
) {
9698 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9699 "target %s not found", context
));
9703 lundam
= (damap_t
*)damap_id_priv_get(tgtdam
, tgtid
);
9704 if (lundam
== NULL
) {
9705 damap_id_rele(tgtdam
, tgtid
); /* from damap_lookup */
9706 SCSI_HBA_LOG((_LOG(1), self
, NULL
,
9707 "lunmap %s already destroyed", context
));
9711 /* NOTE: expected ref at tgtid/taddr: 3: priv_set + caller + lookup. */
9712 ASSERT(damap_id_ref(tgtdam
, tgtid
) == 3);
9713 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s, id %d ref %d",
9714 damap_name(lundam
), tgtid
, damap_id_ref(tgtdam
, tgtid
)));
9717 * A begin/end (clear) against a target's lunmap will trigger
9718 * unconfigure of all LUNs on the target.
9720 scsi_lunmap_set_begin(self
, lundam
);
9721 scsi_lunmap_set_end(self
, lundam
);
9723 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9724 "%s sync begin", damap_name(lundam
)));
9726 (void) damap_sync(lundam
, 0); /* wait for unconfigure */
9728 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
,
9729 "%s sync end", damap_name(lundam
)));
9731 damap_id_priv_set(tgtdam
, tgtid
, NULL
);
9733 /* release hold established by damap_lookup above */
9734 damap_id_rele(tgtdam
, tgtid
);
9736 /* release hold established since scsi_lunmap_create() */
9737 damap_id_rele(tgtdam
, tgtid
);
9739 damap_destroy(lundam
);
9743 scsi_lunmap_set_begin(dev_info_t
*self
, damap_t
*lundam
)
9745 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9747 (void) damap_addrset_begin(lundam
);
9751 scsi_lunmap_set_add(dev_info_t
*self
, damap_t
*lundam
,
9752 char *taddr
, scsi_lun64_t lun64
, int sfunc
)
9754 char ua
[SCSI_MAXNAMELEN
];
9756 /* make unit address string form of "@taddr,lun[,sfunc]" */
9758 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
, taddr
, lun64
);
9760 (void) snprintf(ua
, sizeof (ua
), "%s,%" PRIx64
",%x",
9761 taddr
, lun64
, sfunc
);
9763 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s @%s", damap_name(lundam
), ua
));
9765 return ((damap_addrset_add(lundam
, ua
, NULL
, NULL
,
9766 NULL
) == DAM_SUCCESS
) ? DDI_SUCCESS
: DDI_FAILURE
);
9770 scsi_lunmap_set_end(dev_info_t
*self
, damap_t
*lundam
)
9772 SCSI_HBA_LOG((_LOGLUN
, self
, NULL
, "%s", damap_name(lundam
)));
9774 (void) damap_addrset_end(lundam
, 0);
9778 scsi_lunmap_lookup(dev_info_t
*self
, damap_t
*lundam
, char *addr
)
9782 if ((lunid
= damap_lookup(lundam
, addr
)) != NODAM
) {
9783 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9784 "%s @%s found", damap_name(lundam
), addr
));
9785 damap_id_rele(lundam
, lunid
);
9786 return (DDI_SUCCESS
);
9789 SCSI_HBA_LOG((_LOG(3), self
, NULL
,
9790 "%s @%s not found", damap_name(lundam
), addr
));
9791 return (DDI_FAILURE
);
9795 * phymap implementation
9797 * We manage the timed aggregation of phys into a phy map * by creating a
9798 * SAS port construct (based upon 'name' of "local,remote" SAS addresses)
9799 * upon the first link up. As time goes on additional phys may join that port.
9800 * After an appropriate amount of settle time, we trigger the activation
9801 * callback which will then take the resultant bit mask of phys (phymask) in
9802 * the SAS port and use that to call back to the callback function
9803 * provided by the additional caller.
9805 * We cross check to make sure that phys only exist in one SAS port at a
9806 * time by having soft state for each phy point back to the created
9809 * NOTE: Make SAS_PHY_UA_LEN max(SAS_PHY_PHYMASK_LEN, SAS_PHY_NAME_LEN)
9810 * so we have enough space if sas_phymap_bitset2phymaskua phymask address
9811 * is already in use, and we end up using port name as unit address.
9813 #define SAS_PHY_NAME_FMT "%" PRIx64 ",%" PRIx64
9814 #define SAS_PHY_NAME_LEN (16 + 1 + 16 + 1)
9815 #define SAS_PHY_NPHY (SAS2_PHYNUM_MAX + 1)
9816 #define SAS_PHY_PHYMASK_LEN ((roundup(SAS_PHY_NPHY, 4)) / 4)
9817 #if (SAS_PHY_PHYMASK_LEN > SAS_PHY_NAME_LEN)
9818 #define SAS_PHY_UA_LEN SAS_PHY_PHYMASK_LEN
9820 #define SAS_PHY_UA_LEN SAS_PHY_NAME_LEN
9822 typedef struct impl_sas_physet
{ /* needed for name2phys destroy */
9823 struct impl_sas_physet
*physet_next
;
9825 bitset_t
*physet_phys
;
9826 } impl_sas_physet_t
;
9827 typedef struct impl_sas_phymap
{
9828 dev_info_t
*phymap_self
;
9830 kmutex_t phymap_lock
;
9831 damap_t
*phymap_dam
;
9832 void *phymap_phy2name
;
9833 ddi_soft_state_bystr
*phymap_name2phys
; /* bitset */
9834 ddi_soft_state_bystr
*phymap_name2ua
;
9835 ddi_soft_state_bystr
*phymap_ua2name
;
9837 /* Noisy phy information - ensure forward progress for noisy phys */
9838 int phymap_phy_max
; /* max phy# */
9839 int phymap_reports
; /* per period */
9840 int phymap_reports_max
; /* scales */
9841 int phymap_phys_noisy
; /* detected */
9843 /* These are for callbacks to the consumer. */
9844 sas_phymap_activate_cb_t phymap_acp
;
9845 sas_phymap_deactivate_cb_t phymap_dcp
;
9846 void *phymap_private
;
9848 struct impl_sas_physet
*phymap_physets
;
9849 } impl_sas_phymap_t
;
9851 /* Detect noisy phy: max changes per stabilization period per phy. */
9852 static int sas_phymap_phy_max_factor
= 16;
9855 * Convert bitset into a unit-address string. The maximum string length would
9856 * be the maximum number of phys, rounded up by 4 and divided by 4.
9859 sas_phymap_bitset2phymaskua(bitset_t
*phys
, char *buf
)
9866 bit
= roundup(SAS_PHY_NPHY
, 4);
9873 if (bitset_in_set(phys
, bit
)) {
9878 if (cur
|| ptr
!= buf
) {
9879 *ptr
++ = "0123456789abcdef"[cur
];
9892 sas_phymap_config(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
9894 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
9895 char *context
= damap_name(phymap
->phymap_dam
);
9904 mutex_enter(&phymap
->phymap_lock
);
9905 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
9907 /* Get the name ("local,remote" address string) from damap. */
9908 damn
= damap_id2addr(phydam
, phyid
);
9910 /* Get the bitset of phys currently forming the port. */
9911 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, damn
);
9913 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: no phys",
9915 mutex_exit(&phymap
->phymap_lock
);
9916 return (DAM_FAILURE
);
9919 /* allocate, get, and initialize name index of name2ua map */
9920 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2ua
, damn
) !=
9922 SCSI_HBA_LOG((_LOG_NF(WARN
),
9923 "%s: %s: failed name2ua alloc", context
, damn
));
9924 mutex_exit(&phymap
->phymap_lock
);
9925 return (DAM_FAILURE
);
9927 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
9928 SCSI_HBA_LOG((_LOG_NF(WARN
),
9929 "%s: %s: no name2ua", context
, damn
));
9930 mutex_exit(&phymap
->phymap_lock
);
9931 return (DAM_FAILURE
);
9933 sas_phymap_bitset2phymaskua(phys
, ua
); /* set ua */
9935 /* see if phymask ua index already allocated in ua2name map */
9936 if (name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
)) {
9938 * The 'phymask' sas_phymap_bitset2phymaskua ua is
9939 * already in use. This means that original phys have
9940 * formed into a new port, and that the original port
9941 * still exists (it has migrated to some completely
9942 * different set of phys). In this corner-case we use
9943 * "local,remote" name as a 'temporary' unit address.
9944 * Reset ua in name2ua map.
9946 (void) strlcpy(ua
, damn
, SAS_PHY_NAME_LEN
);
9947 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9949 /* The "local,remote" ua should be new... */
9950 SCSI_HBA_LOG((_LOG_NF(WARN
),
9951 "%s: %s ua already configured",
9953 mutex_exit(&phymap
->phymap_lock
);
9954 return (DAM_SUCCESS
);
9958 /* allocate, get, and init ua index of ua2name map */
9959 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_ua2name
, ua
) !=
9961 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9962 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: failed ua2name alloc",
9964 mutex_exit(&phymap
->phymap_lock
);
9965 return (DAM_FAILURE
);
9967 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
9969 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
9970 SCSI_HBA_LOG((_LOG_NF(WARN
),
9971 "%s: %s: no ua2name", context
, ua
));
9972 mutex_exit(&phymap
->phymap_lock
);
9973 return (DAM_FAILURE
);
9976 /* set name in ua2name map */
9977 (void) strlcpy(name
, damn
, SAS_PHY_NAME_LEN
);
9979 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
9980 "%s: %s: ua %s: activate", context
, damn
, ua
));
9982 if (phymap
->phymap_acp
) {
9984 * drop our lock and invoke the activation callback
9986 mutex_exit(&phymap
->phymap_lock
);
9988 (phymap
->phymap_acp
)(phymap
->phymap_private
, ua
, &ua_priv
);
9989 mutex_enter(&phymap
->phymap_lock
);
9990 damap_id_priv_set(phydam
, phyid
, ua_priv
);
9992 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
9993 "%s: %s: ua %s: activate complete", context
, damn
, ua
));
9994 mutex_exit(&phymap
->phymap_lock
);
9995 return (DAM_SUCCESS
);
10000 sas_phymap_unconfig(void *arg
, damap_t
*phydam
, damap_id_t phyid
)
10002 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)arg
;
10003 char *context
= damap_name(phymap
->phymap_dam
);
10010 mutex_enter(&phymap
->phymap_lock
);
10011 phymap
->phymap_reports
= phymap
->phymap_phys_noisy
= 0;
10013 /* Get the name ("local,remote" address string) from damap. */
10014 damn
= damap_id2addr(phydam
, phyid
);
10016 if (!(ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, damn
))) {
10017 SCSI_HBA_LOG((_LOG_NF(WARN
),
10018 "%s: %s: no name2ua", context
, damn
));
10019 mutex_exit(&phymap
->phymap_lock
);
10020 return (DAM_FAILURE
);
10023 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10024 "%s: %s: ua %s: deactivate", context
, damn
, ua
));
10025 if (phymap
->phymap_dcp
) {
10026 ua_priv
= damap_id_priv_get(phydam
, phyid
);
10027 mutex_exit(&phymap
->phymap_lock
);
10028 (phymap
->phymap_dcp
)(phymap
->phymap_private
, ua
, ua_priv
);
10029 mutex_enter(&phymap
->phymap_lock
);
10031 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10032 "%s: %s: ua %s: deactivate complete", context
, damn
, ua
));
10034 /* delete ua<->name mappings */
10035 ddi_soft_state_bystr_free(phymap
->phymap_ua2name
, ua
);
10036 ddi_soft_state_bystr_free(phymap
->phymap_name2ua
, damn
);
10037 mutex_exit(&phymap
->phymap_lock
);
10038 return (DAM_SUCCESS
);
10042 sas_phymap_create(dev_info_t
*self
, int settle_usec
,
10043 sas_phymap_mode_t mode
, void *mode_argument
, void *phymap_priv
,
10044 sas_phymap_activate_cb_t activate_cb
,
10045 sas_phymap_deactivate_cb_t deactivate_cb
,
10046 sas_phymap_t
**handlep
)
10048 _NOTE(ARGUNUSED(mode_argument
));
10050 impl_sas_phymap_t
*phymap
;
10052 if (self
== NULL
|| settle_usec
== 0 || handlep
== NULL
)
10053 return (DDI_FAILURE
);
10055 if (mode
!= PHYMAP_MODE_SIMPLE
)
10056 return (DDI_FAILURE
);
10058 phymap
= kmem_zalloc(sizeof (*phymap
), KM_SLEEP
);
10059 phymap
->phymap_self
= self
;
10060 phymap
->phymap_reports_max
= 1 * sas_phymap_phy_max_factor
;
10061 phymap
->phymap_acp
= activate_cb
;
10062 phymap
->phymap_dcp
= deactivate_cb
;
10063 phymap
->phymap_private
= phymap_priv
;
10064 mutex_init(&phymap
->phymap_lock
, NULL
, MUTEX_DRIVER
, NULL
);
10066 (void) snprintf(context
, sizeof (context
), "%s%d.phymap",
10067 ddi_driver_name(self
), ddi_get_instance(self
));
10068 SCSI_HBA_LOG((_LOGPHY
, self
, NULL
, "%s", context
));
10070 if (ddi_soft_state_init(&phymap
->phymap_phy2name
,
10071 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10073 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2phys
,
10074 sizeof (bitset_t
), SAS_PHY_NPHY
) != 0)
10077 if (ddi_soft_state_bystr_init(&phymap
->phymap_name2ua
,
10078 SAS_PHY_UA_LEN
, SAS_PHY_NPHY
) != 0)
10080 if (ddi_soft_state_bystr_init(&phymap
->phymap_ua2name
,
10081 SAS_PHY_NAME_LEN
, SAS_PHY_NPHY
) != 0)
10084 if (damap_create(context
, DAMAP_REPORT_PERADDR
, DAMAP_SERIALCONFIG
,
10085 settle_usec
, NULL
, NULL
, NULL
,
10086 phymap
, sas_phymap_config
, sas_phymap_unconfig
,
10087 &phymap
->phymap_dam
) != DAM_SUCCESS
)
10091 *handlep
= (sas_phymap_t
*)phymap
;
10092 return (DDI_SUCCESS
);
10094 fail
: sas_phymap_destroy((sas_phymap_t
*)phymap
);
10096 return (DDI_FAILURE
);
10100 sas_phymap_destroy(sas_phymap_t
*handle
)
10102 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10104 struct impl_sas_physet
*physet
, *nphyset
;
10108 context
= phymap
->phymap_dam
?
10109 damap_name(phymap
->phymap_dam
) : "unknown";
10110 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s", context
));
10112 if (phymap
->phymap_dam
)
10113 damap_destroy(phymap
->phymap_dam
);
10115 /* free the bitsets of allocated physets */
10116 for (physet
= phymap
->phymap_physets
; physet
; physet
= nphyset
) {
10117 nphyset
= physet
->physet_next
;
10118 phys
= physet
->physet_phys
;
10119 name
= physet
->physet_name
;
10124 ddi_soft_state_bystr_free(
10125 phymap
->phymap_name2phys
, name
);
10128 kmem_free(physet
, sizeof (*physet
));
10131 /* free the maps */
10132 if (phymap
->phymap_ua2name
)
10133 ddi_soft_state_bystr_fini(&phymap
->phymap_ua2name
);
10134 if (phymap
->phymap_name2ua
)
10135 ddi_soft_state_bystr_fini(&phymap
->phymap_name2ua
);
10137 if (phymap
->phymap_name2phys
)
10138 ddi_soft_state_bystr_fini(&phymap
->phymap_name2phys
);
10139 if (phymap
->phymap_phy2name
)
10140 ddi_soft_state_fini(&phymap
->phymap_phy2name
);
10142 mutex_destroy(&phymap
->phymap_lock
);
10143 kmem_free(phymap
, sizeof (*phymap
));
10148 sas_phymap_phy_add(sas_phymap_t
*handle
,
10149 int phy
, uint64_t local
, uint64_t remote
)
10151 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10152 char *context
= damap_name(phymap
->phymap_dam
);
10153 char port
[SAS_PHY_NAME_LEN
];
10155 int phy2name_allocated
= 0;
10157 struct impl_sas_physet
*physet
;
10160 /* Create the SAS port name from the local and remote addresses. */
10161 (void) snprintf(port
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10164 mutex_enter(&phymap
->phymap_lock
);
10165 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: add phy %d",
10166 context
, port
, phy
));
10168 /* Check for conflict in phy2name map */
10169 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10171 if (strcmp(name
, port
) != 0)
10172 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10173 "already in %s", context
, port
, phy
, name
));
10175 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: add phy %d: "
10176 "duplicate add", context
, port
, phy
));
10177 mutex_exit(&phymap
->phymap_lock
);
10178 return (DDI_FAILURE
);
10181 /* allocate, get, and initialize phy index of phy2name map */
10182 if (ddi_soft_state_zalloc(
10183 phymap
->phymap_phy2name
, phy
) != DDI_SUCCESS
) {
10184 SCSI_HBA_LOG((_LOG_NF(WARN
),
10185 "%s: %s: failed phy2name alloc", context
, port
));
10188 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10189 if (name
== NULL
) {
10190 SCSI_HBA_LOG((_LOG_NF(WARN
),
10191 "%s: %s: no phy2name", context
, port
));
10194 phy2name_allocated
= 1;
10195 (void) strlcpy(name
, port
, SAS_PHY_NAME_LEN
); /* set name */
10197 /* Find/alloc, initialize name index of name2phys map */
10198 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10199 if (phys
== NULL
) {
10200 if (ddi_soft_state_bystr_zalloc(phymap
->phymap_name2phys
,
10201 name
) != DDI_SUCCESS
) {
10202 SCSI_HBA_LOG((_LOG_NF(WARN
),
10203 "%s: %s: failed name2phys alloc", context
, name
));
10206 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10207 if (phys
== NULL
) {
10208 SCSI_HBA_LOG((_LOG_NF(WARN
),
10209 "%s: %s: no name2phys", context
, name
));
10213 /* Initialize bitset of phys. */
10215 bitset_resize(phys
, SAS_PHY_NPHY
);
10217 /* Keep a list of information for destroy. */
10218 physet
= kmem_zalloc(sizeof (*physet
), KM_SLEEP
);
10219 physet
->physet_name
= strdup(name
);
10220 physet
->physet_phys
= phys
;
10221 physet
->physet_next
= phymap
->phymap_physets
;
10222 phymap
->phymap_physets
= physet
;
10226 /* Reflect 'add' in phys bitset. */
10227 if (bitset_atomic_test_and_add(phys
, phy
) < 0) {
10228 /* It is an error if the phy was already recorded. */
10229 SCSI_HBA_LOG((_LOG_NF(WARN
),
10230 "%s: %s: phy bit %d already in port", context
, name
, phy
));
10235 * Check to see if we have a new phy_max for this map, and if so
10236 * scale phymap_reports_max to the new number of phys.
10238 if (phy
> phymap
->phymap_phy_max
) {
10239 phymap
->phymap_phy_max
= phy
+ 1;
10240 phymap
->phymap_reports_max
= phymap
->phymap_phy_max
*
10241 sas_phymap_phy_max_factor
;
10245 * If we have not reached phymap_reports_max, start/restart the
10246 * activate timer. Otherwise, if phymap->phymap_reports add/rem reports
10247 * ever exceeds phymap_reports_max due to noisy phys, then report the
10248 * noise and force stabilization by stopping reports into the damap.
10250 * The first config/unconfig callout out of the damap will reset
10251 * phymap->phymap_reports.
10254 if (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
) {
10255 if (damap_addr_add(phymap
->phymap_dam
, name
,
10256 NULL
, NULL
, NULL
) == DAM_SUCCESS
) {
10257 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10258 "%s: %s: damap_addr_add", context
, name
));
10260 SCSI_HBA_LOG((_LOG_NF(WARN
),
10261 "%s: %s: damap_addr_add failed", context
, name
));
10265 phymap
->phymap_phys_noisy
++;
10266 if (phymap
->phymap_phys_noisy
== 1)
10267 SCSI_HBA_LOG((_LOG_NF(WARN
),
10268 "%s: %s: noisy phys", context
, name
));
10270 mutex_exit(&phymap
->phymap_lock
);
10273 fail
: if (phy2name_allocated
)
10274 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
);
10275 mutex_exit(&phymap
->phymap_lock
);
10276 return (DDI_FAILURE
);
10280 sas_phymap_phy_rem(sas_phymap_t
*handle
, int phy
)
10282 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10283 char *context
= damap_name(phymap
->phymap_dam
);
10286 int rv
= DDI_FAILURE
;
10290 mutex_enter(&phymap
->phymap_lock
);
10291 phymap
->phymap_reports
++;
10293 /* Find and free phy index of phy2name map */
10294 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10295 if (name
== NULL
) {
10296 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: rem phy %d: never added",
10300 /* NOTE: always free phy index of phy2name map before return... */
10302 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
, "%s: %s: rem phy %d",
10303 context
, name
, phy
));
10305 /* Get bitset of phys currently associated with named port. */
10306 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10307 if (phys
== NULL
) {
10308 SCSI_HBA_LOG((_LOG_NF(WARN
), "%s: %s: name2phys failed",
10313 /* Reflect 'rem' in phys bitset. */
10314 if (bitset_atomic_test_and_del(phys
, phy
) < 0) {
10315 /* It is an error if the phy wasn't one of the port's phys. */
10316 SCSI_HBA_LOG((_LOG_NF(WARN
),
10317 "%s: %s: phy bit %d not in port", context
, name
, phy
));
10321 /* If this was the last phy in the port, start the deactivate timer. */
10322 if (bitset_is_null(phys
) &&
10323 (phymap
->phymap_reports
++ < phymap
->phymap_reports_max
)) {
10324 if (damap_addr_del(phymap
->phymap_dam
, name
) == DAM_SUCCESS
) {
10325 SCSI_HBA_LOG((_LOGPHY
, phymap
->phymap_self
, NULL
,
10326 "%s: %s: damap_addr_del", context
, name
));
10328 SCSI_HBA_LOG((_LOG_NF(WARN
),
10329 "%s: %s: damap_addr_del failure", context
, name
));
10335 /* free phy index of phy2name map */
10337 ddi_soft_state_free(phymap
->phymap_phy2name
, phy
); /* free */
10338 mutex_exit(&phymap
->phymap_lock
);
10343 sas_phymap_lookup_ua(sas_phymap_t
*handle
, uint64_t local
, uint64_t remote
)
10345 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10346 char *context
= damap_name(phymap
->phymap_dam
);
10347 char name
[SAS_PHY_NAME_LEN
];
10352 (void) snprintf(name
, SAS_PHY_NAME_LEN
, SAS_PHY_NAME_FMT
,
10355 mutex_enter(&phymap
->phymap_lock
);
10356 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10357 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10358 "%s: %s: ua %s", context
, name
, ua
? ua
: "NULL"));
10359 mutex_exit(&phymap
->phymap_lock
);
10364 sas_phymap_lookup_uapriv(sas_phymap_t
*handle
, char *ua
)
10366 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10367 char *context
= damap_name(phymap
->phymap_dam
);
10370 void *ua_priv
= NULL
;
10374 mutex_enter(&phymap
->phymap_lock
);
10375 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10377 phyid
= damap_lookup(phymap
->phymap_dam
, name
);
10378 if (phyid
!= NODAM
) {
10379 ua_priv
= damap_id_priv_get(phymap
->phymap_dam
, phyid
);
10380 damap_id_rele(phymap
->phymap_dam
, phyid
);
10384 SCSI_HBA_LOG((_LOG(3), phymap
->phymap_self
, NULL
,
10385 "%s: %s: ua %s ua_priv %p", context
, name
,
10386 ua
? ua
: "NULL", ua_priv
));
10387 mutex_exit(&phymap
->phymap_lock
);
10392 sas_phymap_uahasphys(sas_phymap_t
*handle
, char *ua
)
10394 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10399 mutex_enter(&phymap
->phymap_lock
);
10400 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10402 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10404 n
= bitset_is_null(phys
) ? 0 : 1;
10406 mutex_exit(&phymap
->phymap_lock
);
10410 sas_phymap_phys_t
*
10411 sas_phymap_ua2phys(sas_phymap_t
*handle
, char *ua
)
10413 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10416 bitset_t
*cphys
= NULL
;
10418 mutex_enter(&phymap
->phymap_lock
);
10419 name
= ddi_soft_state_bystr_get(phymap
->phymap_ua2name
, ua
);
10423 phys
= ddi_soft_state_bystr_get(phymap
->phymap_name2phys
, name
);
10427 /* dup the phys and return */
10428 cphys
= kmem_alloc(sizeof (*cphys
), KM_SLEEP
);
10429 bitset_init(cphys
);
10430 bitset_resize(cphys
, SAS_PHY_NPHY
);
10431 bitset_copy(phys
, cphys
);
10433 fail
: mutex_exit(&phymap
->phymap_lock
);
10434 return ((sas_phymap_phys_t
*)cphys
);
10438 sas_phymap_phys_next(sas_phymap_phys_t
*phys
)
10440 bitset_t
*cphys
= (bitset_t
*)phys
;
10443 phy
= bitset_find(cphys
);
10445 bitset_del(cphys
, phy
);
10450 sas_phymap_phys_free(sas_phymap_phys_t
*phys
)
10452 bitset_t
*cphys
= (bitset_t
*)phys
;
10455 bitset_fini(cphys
);
10456 kmem_free(cphys
, sizeof (*cphys
));
10461 sas_phymap_phy2ua(sas_phymap_t
*handle
, int phy
)
10463 impl_sas_phymap_t
*phymap
= (impl_sas_phymap_t
*)handle
;
10468 mutex_enter(&phymap
->phymap_lock
);
10469 name
= ddi_get_soft_state(phymap
->phymap_phy2name
, phy
);
10472 ua
= ddi_soft_state_bystr_get(phymap
->phymap_name2ua
, name
);
10476 /* dup the ua and return */
10479 fail
: mutex_exit(&phymap
->phymap_lock
);
10484 sas_phymap_ua_free(char *ua
)