xref: /illumos-gate/usr/src/uts/common/io/scsi/conf/scsi_confsubr.c (revision 7247f8883be6bcac5fe4735b6f87f873387dbbef)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Utility SCSI configuration routines
30  */
31 /*
32  * Many routines in this file have built in parallel bus assumption
33  * which might need to change as other interconnect evolve.
34  */
35 
36 
37 #include <sys/scsi/scsi.h>
38 #include <sys/modctl.h>
39 
40 /*
41  * macro for filling in lun value for scsi-1 support
42  */
43 
44 #define	FILL_SCSI1_LUN(devp, pkt) \
45 	if ((devp->sd_address.a_lun > 0) && \
46 	    (devp->sd_inq->inq_ansi == 0x1)) { \
47 		((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = \
48 		    devp->sd_address.a_lun; \
49 	}
50 
51 extern struct mod_ops mod_miscops;
52 
53 static struct modlmisc modlmisc = {
54 	&mod_miscops,	/* Type of module */
55 	"SCSI Bus Utility Routines"
56 };
57 
58 static struct modlinkage modlinkage = {
59 	MODREV_1, (void *)&modlmisc, NULL
60 };
61 
62 static void create_inquiry_props(struct scsi_device *);
63 static int get_inquiry_prop_len(char *, size_t);
64 
65 static int scsi_check_ss2_LUN_limit(struct scsi_device *);
66 static void scsi_establish_LUN_limit(struct scsi_device *);
67 static void scsi_update_parent_ss2_prop(dev_info_t *, int, int);
68 
69 /*
70  * this int-array HBA-node property keeps track of strictly SCSI-2
71  * target IDs
72  */
73 #define	SS2_LUN0_TGT_LIST_PROP	"ss2-targets"
74 
75 /*
76  * for keeping track of nodes for which we do *NOT* want to probe above LUN 7
77  * (i.e. strict SCSI-2 targets)
78  *
79  * note that we could also keep track of dtype (SCSI device type) and
80  * ANSI (SCSI standard conformance level), but all currently-known cases of
81  * this problem are on SCSI-2 PROCESSOR device types
82  */
83 typedef struct ss2_lun0_info {
84 	const char	*sli_vid;	/* SCSI inquiry VID */
85 	const char	*sli_pid;	/* SCSI inquiry PID */
86 	const char	*sli_rev;	/* SCSI inquiry REV */
87 } ss2_lun0_info_t;
88 
89 /*
90  * these two workarounds are for the SCSI-2 GEM2* chips used in the
91  * D1000 and D240
92  */
93 #define	SES_D1000_VID		"SYMBIOS"
94 #define	SES_D1000_PID		"D1000"		/* the D1000 */
95 #define	SES_D1000_REV		"2"
96 
97 #define	SES_D240_VID		"SUN"
98 #define	SES_D240_PID		"D240"		/* the D240 */
99 #define	SES_D240_REV		"2"
100 
101 /*
102  * a static list of targets where we do *not* want to probe above LUN 7
103  */
104 static const ss2_lun0_info_t	scsi_probe_strict_s2_list[] = {
105 	{SES_D1000_VID, SES_D1000_PID, SES_D1000_REV},
106 	{SES_D240_VID, SES_D240_PID, SES_D240_REV},
107 };
108 
109 static const int		scsi_probe_strict_s2_size =
110 	sizeof (scsi_probe_strict_s2_list) / sizeof (struct ss2_lun0_info);
111 
112 
113 #ifdef	DEBUG
114 
115 int	scsi_probe_debug = 0;
116 
117 #define	SCSI_PROBE_DEBUG0(l, s)		\
118 		if (scsi_probe_debug >= (l)) printf(s)
119 #define	SCSI_PROBE_DEBUG1(l, s, a1)	\
120 		if (scsi_probe_debug >= (l)) printf(s, a1)
121 #define	SCSI_PROBE_DEBUG2(l, s, a1, a2)	\
122 		if (scsi_probe_debug >= (l)) printf(s, a1, a2)
123 #define	SCSI_PROBE_DEBUG3(l, s, a1, a2, a3)	\
124 		if (scsi_probe_debug >= (l)) printf(s, a1, a2, a3)
125 
126 #else	/* DEBUG */
127 
128 #define	SCSI_PROBE_DEBUG0(l, s)
129 #define	SCSI_PROBE_DEBUG1(l, s, a1)
130 #define	SCSI_PROBE_DEBUG2(l, s, a1, a2)
131 #define	SCSI_PROBE_DEBUG3(l, s, a1, a2, a3)
132 
133 #endif	/* DEBUG */
134 
135 int	scsi_test_busy_timeout = SCSI_POLL_TIMEOUT;	/* in seconds */
136 int	scsi_test_busy_delay = 10000;			/* 10msec in usec */
137 
138 /*
139  * architecture dependent allocation restrictions. For x86, we'll set
140  * dma_attr_addr_hi to scsi_max_phys_addr and dma_attr_sgllen to
141  * scsi_sgl_size during _init().
142  */
143 #if defined(__sparc)
144 ddi_dma_attr_t scsi_alloc_attr = {
145 	DMA_ATTR_V0,	/* version number */
146 	0x0,		/* lowest usable address */
147 	0xFFFFFFFFull,	/* high DMA address range */
148 	0xFFFFFFFFull,	/* DMA counter register */
149 	1,		/* DMA address alignment */
150 	1,		/* DMA burstsizes */
151 	1,		/* min effective DMA size */
152 	0xFFFFFFFFull,	/* max DMA xfer size */
153 	0xFFFFFFFFull,	/* segment boundary */
154 	1,		/* s/g list length */
155 	512,		/* granularity of device */
156 	0		/* DMA transfer flags */
157 };
158 #elif defined(__x86)
159 ddi_dma_attr_t scsi_alloc_attr = {
160 	DMA_ATTR_V0,	/* version number */
161 	0x0,		/* lowest usable address */
162 	0x0,		/* high DMA address range [set in _init()] */
163 	0xFFFFull,	/* DMA counter register */
164 	1,		/* DMA address alignment */
165 	1,		/* DMA burstsizes */
166 	1,		/* min effective DMA size */
167 	0xFFFFFFFFull,	/* max DMA xfer size */
168 	0xFFFFFFFFull,  /* segment boundary */
169 	0,		/* s/g list length */
170 	512,		/* granularity of device [set in _init()] */
171 	0		/* DMA transfer flags */
172 };
173 uint64_t scsi_max_phys_addr = 0xFFFFFFFFull;
174 int scsi_sgl_size = 0xFF;
175 #endif
176 
177 
178 int
179 _init()
180 {
181 	scsi_initialize_hba_interface();
182 	scsi_watch_init();
183 
184 #if defined(__x86)
185 	/* set the max physical address for iob allocs on x86 */
186 	scsi_alloc_attr.dma_attr_addr_hi = scsi_max_phys_addr;
187 
188 	/*
189 	 * set the sgllen for iob allocs on x86. If this is set less than
190 	 * the number of pages the buffer will take (taking into account
191 	 * alignment), it would force the allocator to try and allocate
192 	 * contiguous pages.
193 	 */
194 	scsi_alloc_attr.dma_attr_sgllen = scsi_sgl_size;
195 #endif
196 
197 	return (mod_install(&modlinkage));
198 }
199 
200 /*
201  * there is no _fini() routine because this module is never unloaded
202  */
203 
204 int
205 _info(struct modinfo *modinfop)
206 {
207 	return (mod_info(&modlinkage, modinfop));
208 }
209 
210 #define	ROUTE	(&devp->sd_address)
211 
212 static int
213 scsi_slave_do_rqsense(struct scsi_device *devp, int (*callback)())
214 {
215 	struct scsi_pkt *rq_pkt = NULL;
216 	struct buf *rq_bp = NULL;
217 	int rval = SCSIPROBE_EXISTS;
218 
219 	/*
220 	 * prepare rqsense packet
221 	 */
222 	rq_bp = scsi_alloc_consistent_buf(ROUTE,
223 	    (struct buf *)NULL,
224 	    (uint_t)SENSE_LENGTH, B_READ, callback, NULL);
225 	if (rq_bp == NULL) {
226 		rval = SCSIPROBE_NOMEM;
227 		goto out;
228 	}
229 
230 	rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
231 	    rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT,
232 	    callback, NULL);
233 
234 	if (rq_pkt == NULL) {
235 		if (rq_bp->b_error == 0)
236 			rval = SCSIPROBE_NOMEM_CB;
237 		else
238 			rval = SCSIPROBE_NOMEM;
239 		goto out;
240 	}
241 	ASSERT(rq_bp->b_error == 0);
242 
243 	(void) scsi_setup_cdb((union scsi_cdb *)rq_pkt->
244 	    pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
245 	FILL_SCSI1_LUN(devp, rq_pkt);
246 	rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY|FLAG_SENSING;
247 
248 	/*
249 	 * The controller type is as yet unknown, so we
250 	 * have to do a throwaway non-extended request sense,
251 	 * and hope that that clears the check condition
252 	 * for that unit until we can find out what kind
253 	 * of drive it is. A non-extended request sense
254 	 * is specified by stating that the sense block
255 	 * has 0 length, which is taken to mean that it
256 	 * is four bytes in length.
257 	 */
258 	if (scsi_poll(rq_pkt) < 0) {
259 		rval = SCSIPROBE_FAILURE;
260 	}
261 
262 out:
263 	if (rq_pkt) {
264 		scsi_destroy_pkt(rq_pkt);
265 	}
266 	if (rq_bp) {
267 		scsi_free_consistent_buf(rq_bp);
268 	}
269 
270 	return (rval);
271 }
272 
273 /*
274  *
275  * SCSI slave probe routine - provided as a service to target drivers
276  *
277  * Mostly attempts to allocate and fill devp inquiry data..
278  */
279 
280 int
281 scsi_slave(struct scsi_device *devp, int (*callback)())
282 {
283 	struct scsi_pkt	*pkt;
284 	int		rval = SCSIPROBE_EXISTS;
285 
286 	/*
287 	 * the first test unit ready will tell us whether a target
288 	 * responded and if there was one, it will clear the unit attention
289 	 * condition
290 	 */
291 	pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL, NULL,
292 	    CDB_GROUP0, sizeof (struct scsi_arq_status), 0, 0, callback, NULL);
293 
294 	if (pkt == NULL) {
295 		return (SCSIPROBE_NOMEM_CB);
296 	}
297 
298 	(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp,
299 	    SCMD_TEST_UNIT_READY, 0, 0, 0);
300 	FILL_SCSI1_LUN(devp, pkt);
301 	pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY;
302 
303 	if (scsi_poll(pkt) < 0) {
304 		if (pkt->pkt_reason == CMD_INCOMPLETE)
305 			rval = SCSIPROBE_NORESP;
306 		else
307 			rval = SCSIPROBE_FAILURE;
308 
309 		if ((pkt->pkt_state & STATE_ARQ_DONE) == 0) {
310 			if (((struct scsi_status *)pkt->pkt_scbp)->sts_chk)
311 				/*
312 				 * scanner and processor devices can return a
313 				 * check condition here
314 				 */
315 				rval = scsi_slave_do_rqsense(devp, callback);
316 		}
317 
318 		if (rval != SCSIPROBE_EXISTS) {
319 			scsi_destroy_pkt(pkt);
320 			return (rval);
321 		}
322 	}
323 
324 	/*
325 	 * the second test unit ready, allows the host adapter to negotiate
326 	 * synchronous transfer period and offset
327 	 */
328 	if (scsi_poll(pkt) < 0) {
329 		if (pkt->pkt_reason == CMD_INCOMPLETE)
330 			rval = SCSIPROBE_NORESP;
331 		else
332 			rval = SCSIPROBE_FAILURE;
333 	}
334 
335 	/*
336 	 * do a rqsense if there was a check condition and ARQ was not done
337 	 */
338 	if ((pkt->pkt_state & STATE_ARQ_DONE) == 0) {
339 		if (((struct scsi_status *)pkt->pkt_scbp)->sts_chk) {
340 			rval = scsi_slave_do_rqsense(devp, callback);
341 		}
342 	}
343 
344 	/*
345 	 * call scsi_probe to do the inquiry
346 	 * XXX there is minor difference with the old scsi_slave implementation:
347 	 * busy conditions are not handled in scsi_probe.
348 	 */
349 	scsi_destroy_pkt(pkt);
350 	if (rval == SCSIPROBE_EXISTS) {
351 		return (scsi_probe(devp, callback));
352 	} else {
353 		return (rval);
354 	}
355 }
356 
357 
358 /*
359  * Undo scsi_slave - older interface, but still supported
360  */
361 void
362 scsi_unslave(struct scsi_device *devp)
363 {
364 	if (devp->sd_inq) {
365 		kmem_free((caddr_t)devp->sd_inq, SUN_INQSIZE);
366 		devp->sd_inq = (struct scsi_inquiry *)NULL;
367 	}
368 }
369 
370 
371 /*
372  * Undo scsi_probe
373  */
374 void
375 scsi_unprobe(struct scsi_device *devp)
376 {
377 	if (devp->sd_inq) {
378 		kmem_free((caddr_t)devp->sd_inq, SUN_INQSIZE);
379 		devp->sd_inq = (struct scsi_inquiry *)NULL;
380 	}
381 }
382 
383 /*
384  * This is like scsi_poll, but only does retry for TRAN_BUSY.
385  */
386 static int
387 scsi_test(struct scsi_pkt *pkt)
388 {
389 	int		rval = -1;
390 	int		wait_usec;
391 	int		rc;
392 	extern int	do_polled_io;
393 
394 	pkt->pkt_flags |= FLAG_NOINTR;
395 	pkt->pkt_time = SCSI_POLL_TIMEOUT;	/* in seconds */
396 
397 	if (scsi_ifgetcap(&pkt->pkt_address, "tagged-qing", 1) == 1) {
398 		pkt->pkt_flags |= FLAG_STAG;
399 	}
400 
401 	/*
402 	 * Each TRAN_BUSY response waits scsi_test_busy_delay usec up to a
403 	 * maximum of scsi_test_busy_timeout.
404 	 */
405 	for (wait_usec = 0; (wait_usec / 1000000) <= scsi_test_busy_timeout;
406 	    wait_usec += scsi_test_busy_delay) {
407 
408 		/* Initialize pkt status variables */
409 		*pkt->pkt_scbp = pkt->pkt_reason = pkt->pkt_state = 0;
410 
411 		rc = scsi_transport(pkt);
412 		if ((rc != TRAN_BUSY) || (scsi_test_busy_delay == 0) ||
413 		    (scsi_test_busy_timeout == 0))
414 			break;
415 
416 		/* transport busy, wait */
417 		if ((curthread->t_flag & T_INTR_THREAD) == 0 && !do_polled_io) {
418 			delay(drv_usectohz(scsi_test_busy_delay));
419 		} else {
420 			/* we busy wait during cpr_dump or interrupt threads */
421 			drv_usecwait(scsi_test_busy_delay);
422 		}
423 	}
424 
425 	if (rc != TRAN_ACCEPT) {
426 		goto exit;
427 	} else if (pkt->pkt_reason == CMD_INCOMPLETE && pkt->pkt_state == 0) {
428 		goto exit;
429 	} else if (pkt->pkt_reason != CMD_CMPLT) {
430 		goto exit;
431 	} else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
432 		rval = 0;
433 	} else {
434 		rval = 0;
435 	}
436 
437 exit:
438 	return (rval);
439 }
440 
441 /*
442  * The implementation of scsi_probe now allows a particular
443  * HBA to intercept the call, for any post- or pre-processing
444  * it may need.  The default, if the HBA does not override it,
445  * is to call scsi_hba_probe(), which retains the old functionality
446  * intact.
447  */
448 int
449 scsi_probe(struct scsi_device *devp, int (*callback)())
450 {
451 	int ret;
452 	scsi_hba_tran_t		*hba_tran = devp->sd_address.a_hba_tran;
453 
454 
455 	if (scsi_check_ss2_LUN_limit(devp) != 0) {
456 		/*
457 		 * caller is trying to probe a strictly-SCSI-2 device
458 		 * with a LUN that is too large, so do not allow it
459 		 */
460 		return (SCSIPROBE_NORESP);	/* skip probing this one */
461 	}
462 
463 	if (hba_tran->tran_tgt_probe != NULL) {
464 		ret = (*hba_tran->tran_tgt_probe)(devp, callback);
465 	} else {
466 		ret = scsi_hba_probe(devp, callback);
467 	}
468 
469 	if (ret == SCSIPROBE_EXISTS) {
470 		create_inquiry_props(devp);
471 		/* is this a strictly-SCSI-2 node ?? */
472 		scsi_establish_LUN_limit(devp);
473 	}
474 
475 	return (ret);
476 }
477 
478 /*
479  * scsi_hba_probe does not do any test unit ready's which access the medium
480  * and could cause busy or not ready conditions.
481  * scsi_hba_probe does 2 inquiries and a rqsense to clear unit attention
482  * and to allow sync negotiation to take place
483  * finally, scsi_hba_probe does one more inquiry which should
484  * reliably tell us what kind of target we have.
485  * A scsi-2 compliant target should be able to	return inquiry with 250ms
486  * and we actually wait more than a second after reset.
487  */
488 int
489 scsi_hba_probe(struct scsi_device *devp, int (*callback)())
490 {
491 	struct scsi_pkt		*inq_pkt = NULL;
492 	struct scsi_pkt		*rq_pkt = NULL;
493 	int			rval = SCSIPROBE_NOMEM;
494 	struct buf		*inq_bp = NULL;
495 	struct buf		*rq_bp = NULL;
496 	int			(*cb_flag)();
497 	int			pass = 1;
498 
499 	if (devp->sd_inq == NULL) {
500 		devp->sd_inq = (struct scsi_inquiry *)
501 		    kmem_alloc(SUN_INQSIZE, ((callback == SLEEP_FUNC) ?
502 		    KM_SLEEP : KM_NOSLEEP));
503 		if (devp->sd_inq == NULL) {
504 			goto out;
505 		}
506 	}
507 
508 	if (callback != SLEEP_FUNC && callback != NULL_FUNC) {
509 		cb_flag = NULL_FUNC;
510 	} else {
511 		cb_flag = callback;
512 	}
513 	inq_bp = scsi_alloc_consistent_buf(ROUTE,
514 	    (struct buf *)NULL, SUN_INQSIZE, B_READ, cb_flag, NULL);
515 	if (inq_bp == NULL) {
516 		goto out;
517 	}
518 
519 	inq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
520 	    inq_bp, CDB_GROUP0, sizeof (struct scsi_arq_status),
521 	    0, PKT_CONSISTENT, callback, NULL);
522 	if (inq_pkt == NULL) {
523 		if (inq_bp->b_error == 0)
524 			rval = SCSIPROBE_NOMEM_CB;
525 		goto out;
526 	}
527 	ASSERT(inq_bp->b_error == 0);
528 
529 	(void) scsi_setup_cdb((union scsi_cdb *)inq_pkt->pkt_cdbp,
530 	    SCMD_INQUIRY, 0, SUN_INQSIZE, 0);
531 	inq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY;
532 
533 	/*
534 	 * the first inquiry will tell us whether a target
535 	 * responded
536 	 *
537 	 * The FILL_SCSI1_LUN below will find "ansi_ver != 1" on first pass
538 	 * because of bzero initilization. If this assumption turns out to be
539 	 * incorrect after we have real sd_inq data (for lun0) we will do a
540 	 * second pass during which FILL_SCSI1_LUN will place lun in CDB.
541 	 */
542 	bzero((caddr_t)devp->sd_inq, SUN_INQSIZE);
543 again:	FILL_SCSI1_LUN(devp, inq_pkt);
544 
545 	if (scsi_test(inq_pkt) < 0) {
546 		if (inq_pkt->pkt_reason == CMD_INCOMPLETE) {
547 			rval = SCSIPROBE_NORESP;
548 			goto out;
549 		} else {
550 			/*
551 			 * retry one more time
552 			 */
553 			if (scsi_test(inq_pkt) < 0) {
554 				rval = SCSIPROBE_FAILURE;
555 				goto out;
556 			}
557 		}
558 	}
559 
560 	/*
561 	 * if we are lucky, this inquiry succeeded
562 	 */
563 	if ((inq_pkt->pkt_reason == CMD_CMPLT) &&
564 	    (((*inq_pkt->pkt_scbp) & STATUS_MASK) == 0)) {
565 		goto done;
566 	}
567 
568 	/*
569 	 * the second inquiry, allows the host adapter to negotiate
570 	 * synchronous transfer period and offset
571 	 */
572 	if (scsi_test(inq_pkt) < 0) {
573 		if (inq_pkt->pkt_reason == CMD_INCOMPLETE)
574 			rval = SCSIPROBE_NORESP;
575 		else
576 			rval = SCSIPROBE_FAILURE;
577 		goto out;
578 	}
579 
580 	/*
581 	 * if target is still busy, give up now
582 	 */
583 	if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) {
584 		rval = SCSIPROBE_BUSY;
585 		goto out;
586 	}
587 
588 	/*
589 	 * do a rqsense if there was a check condition and ARQ was not done
590 	 */
591 	if ((inq_pkt->pkt_state & STATE_ARQ_DONE) == 0) {
592 		if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
593 
594 			/*
595 			 * prepare rqsense packet
596 			 * there is no real need for this because the
597 			 * check condition should have been cleared by now.
598 			 */
599 			rq_bp = scsi_alloc_consistent_buf(ROUTE,
600 			    (struct buf *)NULL,
601 			    (uint_t)SENSE_LENGTH, B_READ, cb_flag, NULL);
602 			if (rq_bp == NULL) {
603 				goto out;
604 			}
605 
606 			rq_pkt = scsi_init_pkt(ROUTE, (struct scsi_pkt *)NULL,
607 			    rq_bp, CDB_GROUP0, 1, 0, PKT_CONSISTENT, callback,
608 			    NULL);
609 
610 			if (rq_pkt == NULL) {
611 				if (rq_bp->b_error == 0)
612 					rval = SCSIPROBE_NOMEM_CB;
613 				goto out;
614 			}
615 			ASSERT(rq_bp->b_error == 0);
616 
617 			(void) scsi_setup_cdb((union scsi_cdb *)rq_pkt->
618 			    pkt_cdbp, SCMD_REQUEST_SENSE, 0, SENSE_LENGTH, 0);
619 			FILL_SCSI1_LUN(devp, rq_pkt);
620 			rq_pkt->pkt_flags = FLAG_NOINTR|FLAG_NOPARITY;
621 
622 			/*
623 			 * The FILL_SCSI1_LUN above will find "inq_ansi != 1"
624 			 * on first pass, see "again" comment above.
625 			 *
626 			 * The controller type is as yet unknown, so we
627 			 * have to do a throwaway non-extended request sense,
628 			 * and hope that that clears the check condition for
629 			 * that unit until we can find out what kind of drive
630 			 * it is. A non-extended request sense is specified
631 			 * by stating that the sense block has 0 length,
632 			 * which is taken to mean that it is four bytes in
633 			 * length.
634 			 */
635 			if (scsi_test(rq_pkt) < 0) {
636 				rval = SCSIPROBE_FAILURE;
637 				goto out;
638 			}
639 		}
640 	}
641 
642 	/*
643 	 * At this point, we are guaranteed that something responded
644 	 * to this scsi bus target id. We don't know yet what
645 	 * kind of device it is, or even whether there really is
646 	 * a logical unit attached (as some SCSI target controllers
647 	 * lie about a unit being ready, e.g., the Emulex MD21).
648 	 */
649 
650 	if (scsi_test(inq_pkt) < 0) {
651 		rval = SCSIPROBE_FAILURE;
652 		goto out;
653 	}
654 
655 	if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_busy) {
656 		rval = SCSIPROBE_BUSY;
657 		goto out;
658 	}
659 
660 	/*
661 	 * Okay we sent the INQUIRY command.
662 	 *
663 	 * If enough data was transferred, we count that the
664 	 * Inquiry command succeeded, else we have to assume
665 	 * that this is a non-CCS scsi target (or a nonexistent
666 	 * target/lun).
667 	 */
668 
669 	if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
670 		/*
671 		 * try a request sense if we have a pkt, otherwise
672 		 * just retry the inquiry one more time
673 		 */
674 		if (rq_pkt) {
675 			(void) scsi_test(rq_pkt);
676 		}
677 
678 		/*
679 		 * retry inquiry
680 		 */
681 		if (scsi_test(inq_pkt) < 0) {
682 			rval = SCSIPROBE_FAILURE;
683 			goto out;
684 		}
685 		if (((struct scsi_status *)inq_pkt->pkt_scbp)->sts_chk) {
686 			rval = SCSIPROBE_FAILURE;
687 			goto out;
688 		}
689 	}
690 
691 done:
692 	/*
693 	 * If we got a parity error on receive of inquiry data,
694 	 * we're just plain out of luck because we told the host
695 	 * adapter to not watch for parity errors.
696 	 */
697 	if ((inq_pkt->pkt_state & STATE_XFERRED_DATA) == 0 ||
698 	    ((SUN_INQSIZE - inq_pkt->pkt_resid) < SUN_MIN_INQLEN)) {
699 		rval = SCSIPROBE_NONCCS;
700 	} else {
701 		bcopy((caddr_t)inq_bp->b_un.b_addr,
702 		    (caddr_t)devp->sd_inq, SUN_INQSIZE);
703 		rval = SCSIPROBE_EXISTS;
704 	}
705 
706 out:
707 	/*
708 	 * If lun > 0 we need to figure out if this is a scsi-1 device where
709 	 * the "real" lun needs to be embeded into the cdb.
710 	 */
711 	if ((rval == SCSIPROBE_EXISTS) && (pass == 1) &&
712 	    (devp->sd_address.a_lun > 0) && (devp->sd_inq->inq_ansi == 0x1)) {
713 		pass++;
714 		if (devp->sd_address.a_lun <= 7)
715 			goto again;
716 
717 		/*
718 		 * invalid lun for scsi-1,
719 		 * return probe failure.
720 		 */
721 		rval = SCSIPROBE_FAILURE;
722 	}
723 
724 	if (rq_pkt) {
725 		scsi_destroy_pkt(rq_pkt);
726 	}
727 	if (inq_pkt) {
728 		scsi_destroy_pkt(inq_pkt);
729 	}
730 	if (rq_bp) {
731 		scsi_free_consistent_buf(rq_bp);
732 	}
733 	if (inq_bp) {
734 		scsi_free_consistent_buf(inq_bp);
735 	}
736 	return (rval);
737 }
738 
739 
740 #define	A_TO_TRAN(ap)	(ap->a_hba_tran)
741 
742 /*
743  * Function to get target and lun identifiers from HBA driver.
744  */
745 int
746 scsi_get_bus_addr(struct scsi_device *devp, char *name, int len)
747 {
748 	struct scsi_address *ap = &devp->sd_address;
749 
750 	if ((A_TO_TRAN(ap)->tran_get_bus_addr) == NULL) {
751 		(void) sprintf(name, "%x,%x", ap->a_target, ap->a_lun);
752 		return (1);
753 	}
754 	return (*A_TO_TRAN(ap)->tran_get_bus_addr)(devp, name, len);
755 }
756 
757 /*
758  * Function to get name from HBA driver.
759  */
760 int
761 scsi_get_name(struct scsi_device *devp, char *name, int len)
762 {
763 	struct scsi_address *ap = &devp->sd_address;
764 
765 	if ((A_TO_TRAN(ap)->tran_get_name) == NULL) {
766 		(void) sprintf(name, "%x,%x", ap->a_target, ap->a_lun);
767 		return (1);
768 	}
769 	return (*A_TO_TRAN(ap)->tran_get_name)(devp, name, len);
770 }
771 
772 void
773 create_inquiry_props(struct scsi_device *devp)
774 {
775 	struct scsi_inquiry *inq = devp->sd_inq;
776 
777 	(void) ndi_prop_update_int(DDI_DEV_T_NONE, devp->sd_dev,
778 	    INQUIRY_DEVICE_TYPE, (int)inq->inq_dtype);
779 
780 	/*
781 	 * Create the following properties:
782 	 *
783 	 * inquiry-vendor-id 	Vendor id (INQUIRY data bytes 8-15)
784 	 * inquiry-product-id 	Product id (INQUIRY data bytes 16-31)
785 	 * inquiry-revision-id 	Product Rev level (INQUIRY data bytes 32-35)
786 	 *
787 	 * Note we don't support creation of these properties for scsi-1
788 	 * devices (as the vid, pid and revision were not defined) and we
789 	 * don't create the property if they are of zero length when
790 	 * stripped of Nulls and spaces.
791 	 */
792 	if (inq->inq_ansi != 1) {
793 		if (ddi_prop_exists(DDI_DEV_T_NONE, devp->sd_dev,
794 		    DDI_PROP_TYPE_STRING, INQUIRY_VENDOR_ID) == 0)
795 			(void) scsi_hba_prop_update_inqstring(devp,
796 			    INQUIRY_VENDOR_ID,
797 			    inq->inq_vid, sizeof (inq->inq_vid));
798 
799 		if (ddi_prop_exists(DDI_DEV_T_NONE, devp->sd_dev,
800 		    DDI_PROP_TYPE_STRING, INQUIRY_PRODUCT_ID) == 0)
801 			(void) scsi_hba_prop_update_inqstring(devp,
802 			    INQUIRY_PRODUCT_ID,
803 			    inq->inq_pid, sizeof (inq->inq_pid));
804 
805 		if (ddi_prop_exists(DDI_DEV_T_NONE, devp->sd_dev,
806 		    DDI_PROP_TYPE_STRING, INQUIRY_REVISION_ID) == 0)
807 			(void) scsi_hba_prop_update_inqstring(devp,
808 			    INQUIRY_REVISION_ID,
809 			    inq->inq_revision, sizeof (inq->inq_revision));
810 	}
811 }
812 
813 /*
814  * Create 'inquiry' string properties.  An 'inquiry' string gets special
815  * treatment to trim trailing blanks (etc) and ensure null termination.
816  */
817 int
818 scsi_hba_prop_update_inqstring(struct scsi_device *devp,
819     char *name, char *data, size_t len)
820 {
821 	int	ilen;
822 	char	*data_string;
823 	int	rv;
824 
825 	ilen = get_inquiry_prop_len(data, len);
826 	ASSERT(ilen <= (int)len);
827 	if (ilen <= 0)
828 		return (DDI_PROP_INVAL_ARG);
829 
830 	/* ensure null termination */
831 	data_string = kmem_zalloc(ilen + 1, KM_SLEEP);
832 	bcopy(data, data_string, ilen);
833 	rv = ndi_prop_update_string(DDI_DEV_T_NONE,
834 	    devp->sd_dev, name, data_string);
835 	kmem_free(data_string, ilen + 1);
836 	return (rv);
837 }
838 
839 /*
840  * This routine returns the true length of the inquiry properties that are to
841  * be created by removing the padded spaces at the end of the inquiry data.
842  * This routine was designed for trimming spaces from the vid, pid and revision
843  * which are defined as being left aligned.  In addition, we return 0 length
844  * if the property is full of all 0's or spaces, indicating to the caller that
845  * the device was not ready to return the proper inquiry data as per note 65 in
846  * the scsi-2 spec.
847  */
848 static int
849 get_inquiry_prop_len(char *property, size_t length)
850 {
851 	int retval;
852 	int trailer;
853 	char *p;
854 
855 	retval = length;
856 
857 	/*
858 	 * The vid, pid and revision are left-aligned ascii fields within the
859 	 * inquiry data.  Here we trim the end of these fields by discounting
860 	 * length associated with trailing spaces or NULL bytes.  The remaining
861 	 * bytes shall be only graphics codes - 0x20 through 0x7e as per the
862 	 * scsi spec definition.  If we have all 0's or spaces, we return 0
863 	 * length.  For devices that store inquiry data on the device, they
864 	 * can return 0's or spaces in these fields until the data is avail-
865 	 * able from the device (See NOTE 65 in the scsi-2 specification
866 	 * around the inquiry command.)  We don't want to create a property in
867 	 * the case of a device not able to return valid data.
868 	 */
869 	trailer = 1;
870 	for (p = property + length - 1; p >= property; p--) {
871 		if (trailer) {
872 			if ((*p == ' ') || (*p == '\0')) {
873 				retval--;
874 				continue;
875 			}
876 			trailer = 0;
877 		}
878 
879 		/* each char must be within 0x20 - 0x7e */
880 		if (*p < 0x20 || *p > 0x7e) {
881 			retval = -1;
882 			break;
883 		}
884 
885 	}
886 
887 	return (retval);
888 }
889 
890 
891 /*
892  * this routine is called from the start of scsi_probe() if a tgt/LUN to be
893  * probed *may* be a request to probe a strictly SCSI-2 target (with respect
894  * to LUNs) -- and this probe may be for a LUN number greater than 7,
895  * which can cause a hardware hang
896  *
897  * return 0 if the probe can proceed,
898  * else return 1, meaning do *NOT* probe this target/LUN
899  */
900 static int
901 scsi_check_ss2_LUN_limit(struct scsi_device *devp)
902 {
903 	struct scsi_address	*ap = &(devp->sd_address);
904 	dev_info_t		*pdevi =
905 	    (dev_info_t *)DEVI(devp->sd_dev)->devi_parent;
906 	int			ret_val = 0;	/* default return value */
907 	uchar_t			*tgt_list;
908 	uint_t			tgt_nelements;
909 	int			i;
910 
911 
912 	/*
913 	 * check for what *might* be a problem probe, only we don't
914 	 * know yet what's really at the destination target/LUN
915 	 */
916 	if ((ap->a_target >= NTARGETS_WIDE) ||
917 	    (ap->a_lun < NLUNS_PER_TARGET)) {
918 		return (0);		/* okay to probe this target */
919 	}
920 
921 	/*
922 	 * this *might* be a problematic probe, so look to see
923 	 * if the inquiry data matches
924 	 */
925 	SCSI_PROBE_DEBUG2(1, "SCSA pre-probe: checking tgt.LUN=%d.%d\n",
926 	    ap->a_target, ap->a_lun);
927 	SCSI_PROBE_DEBUG1(2,
928 	    "SCSA pre-probe: scanning parent node name: %s ...\n",
929 	    ddi_node_name(pdevi));
930 
931 	/*
932 	 * look for a special property of our parent node that lists
933 	 * the targets under it for which we do *NOT* want to probe
934 	 * if LUN>7 -- if the property is found, look to see if our
935 	 * target ID is on that list
936 	 */
937 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY,
938 	    pdevi, DDI_PROP_DONTPASS, SS2_LUN0_TGT_LIST_PROP,
939 	    &tgt_list, &tgt_nelements) != DDI_PROP_SUCCESS) {
940 		/*
941 		 * no list, so it must be okay to probe this target.LUN
942 		 */
943 		SCSI_PROBE_DEBUG0(3,
944 		    "SCSA pre-probe: NO parent prop found\n");
945 	} else {
946 		for (i = 0; i < tgt_nelements; i++) {
947 			if (tgt_list[i] == ap->a_target) {
948 				/*
949 				 * we found a match, which means we do *NOT*
950 				 * want to probe the specified target.LUN
951 				 */
952 				ret_val = 1;
953 				break;
954 			}
955 		}
956 		ddi_prop_free(tgt_list);
957 #ifdef	DEBUG
958 		if (ret_val == 1) {
959 			SCSI_PROBE_DEBUG2(1,
960 			    "SCSA pre-probe: marker node FOUND for "
961 			    "tgt.LUN=%d.%d, so SKIPPING it\n",
962 			    ap->a_target, ap->a_lun);
963 		} else {
964 			SCSI_PROBE_DEBUG0(2,
965 			    "SCSA pre-probe: NO marker node found"
966 			    " -- OK to probe\n");
967 		}
968 #endif
969 	}
970 	return (ret_val);
971 }
972 
973 
974 /*
975  * this routine is called from near the end of scsi_probe(),
976  * to see if the just-probed node is on our list of strictly-SCSI-2 nodes,
977  * and if it is we mark our parent node with this information
978  */
979 static void
980 scsi_establish_LUN_limit(struct scsi_device *devp)
981 {
982 	struct scsi_address	*ap = &(devp->sd_address);
983 	struct scsi_inquiry	*inq = devp->sd_inq;
984 	dev_info_t		*devi = devp->sd_dev;
985 	char			*vid = NULL;
986 	char			*pid = NULL;
987 	char			*rev = NULL;
988 	int			i;
989 	const ss2_lun0_info_t	*p;
990 	int			bad_target_found = 0;
991 
992 
993 	/*
994 	 * if this inquiry data shows that we have a strictly-SCSI-2 device
995 	 * at LUN 0, then add it to our list of strictly-SCSI-2 devices,
996 	 * so that we can avoid probes where LUN>7 on this device later
997 	 */
998 	if ((ap->a_lun != 0) ||
999 	    (ap->a_target >= NTARGETS_WIDE) ||
1000 	    (inq->inq_dtype != DTYPE_PROCESSOR) ||
1001 	    (inq->inq_ansi != 2)) {
1002 		/*
1003 		 * this can't possibly be a node we want to look at, since
1004 		 * either LUN is greater than 0, target is greater than or
1005 		 * eqaual to 16, device type
1006 		 * is not processor, or SCSI level is not SCSI-2,
1007 		 * so don't bother checking for a strictly SCSI-2
1008 		 * (only 8 LUN) target
1009 		 */
1010 		return;				/* don't care */
1011 	}
1012 
1013 	SCSI_PROBE_DEBUG2(1, "SCSA post-probe: LUN limit on tgt.LUN=%d.%d, "
1014 	    "SCSI-2 PROCESSOR?\n", ap->a_target, ap->a_lun);
1015 
1016 	ASSERT(devi != NULL);
1017 
1018 	/*
1019 	 * we have a node that has been probed that is: LUN=0, target<16,
1020 	 * PROCESSOR-type SCSI target, and at the SCSI-2 level, so
1021 	 * check INQ properties to see if it's in our list of strictly
1022 	 * SCSI-2 targets
1023 	 *
1024 	 * first we have to get the VID/PID/REV INQUIRY properties for
1025 	 * comparison
1026 	 */
1027 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1028 	    INQUIRY_VENDOR_ID, &vid) != DDI_PROP_SUCCESS) {
1029 		SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n",
1030 		    INQUIRY_VENDOR_ID);
1031 		goto dun;
1032 	}
1033 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1034 	    INQUIRY_PRODUCT_ID, &pid) != DDI_PROP_SUCCESS) {
1035 		SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n",
1036 		    INQUIRY_PRODUCT_ID);
1037 		goto dun;
1038 	}
1039 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
1040 	    INQUIRY_REVISION_ID, &rev) != DDI_PROP_SUCCESS) {
1041 		SCSI_PROBE_DEBUG1(2, "SCSA post-probe: prop \"%s\" missing\n",
1042 		    INQUIRY_REVISION_ID);
1043 		goto dun;
1044 	}
1045 
1046 	SCSI_PROBE_DEBUG3(3, "SCSA post-probe: looking for vid/pid/rev = "
1047 	    "\"%s\"/\"%s\"/\"%s\"\n", vid, pid, rev);
1048 
1049 	/*
1050 	 * now that we have the INQUIRY properties from the device node,
1051 	 * compare them with our known offenders
1052 	 *
1053 	 * Note: comparison is *CASE* *SENSITIVE*
1054 	 */
1055 	for (i = 0; i < scsi_probe_strict_s2_size; i++) {
1056 		p = &scsi_probe_strict_s2_list[i];
1057 
1058 		if ((strcmp(p->sli_vid, vid) == 0) &&
1059 		    (strcmp(p->sli_pid, pid) == 0) &&
1060 		    (strcmp(p->sli_rev, rev) == 0)) {
1061 			/*
1062 			 * we found a match -- do NOT want to probe this one
1063 			 */
1064 			SCSI_PROBE_DEBUG3(1,
1065 			    "SCSA post-probe: recording strict SCSI-2 node "
1066 			    "vid/pid/rev = \"%s\"/\"%s\"/\"%s\"\n",
1067 			    vid, pid, rev);
1068 
1069 			/*
1070 			 * set/update private parent-node property,
1071 			 * so we can find out about this node later
1072 			 */
1073 			bad_target_found = 1;
1074 			break;
1075 		}
1076 	}
1077 
1078 	/*
1079 	 * either add remove target number from parent property
1080 	 */
1081 	scsi_update_parent_ss2_prop(devi, ap->a_target, bad_target_found);
1082 
1083 dun:
1084 	if (vid != NULL) {
1085 		ddi_prop_free(vid);
1086 	}
1087 	if (pid != NULL) {
1088 		ddi_prop_free(pid);
1089 	}
1090 	if (rev != NULL) {
1091 		ddi_prop_free(rev);
1092 	}
1093 }
1094 
1095 
1096 /*
1097  * update the parent node to add in the supplied tgt number to the target
1098  * list property already present (if any)
1099  *
1100  * since the target list can never be longer than 16, and each target
1101  * number is also small, we can save having to alloc memory by putting
1102  * a 16-byte array on the stack and using it for property memory
1103  *
1104  * if "add_tgt" is set then add the target to the parent's property, else
1105  * remove it (if present)
1106  */
1107 static void
1108 scsi_update_parent_ss2_prop(dev_info_t *devi, int tgt, int add_tgt)
1109 {
1110 	dev_info_t	*pdevi = (dev_info_t *)DEVI(devi)->devi_parent;
1111 	uchar_t		*tgt_list;
1112 	uint_t		nelements;
1113 	uint_t		new_nelements;
1114 	int		i;
1115 	int		update_result;
1116 	uchar_t		new_tgt_list[NTARGETS_WIDE];
1117 
1118 
1119 	ASSERT(pdevi != NULL);
1120 
1121 	SCSI_PROBE_DEBUG3(3,
1122 	    "SCSA post-probe: updating parent=%s property to %s tgt=%d\n",
1123 	    ddi_node_name(pdevi), add_tgt ? "add" : "remove", tgt);
1124 
1125 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, pdevi, DDI_PROP_DONTPASS,
1126 	    SS2_LUN0_TGT_LIST_PROP, &tgt_list, &nelements) ==
1127 	    DDI_PROP_SUCCESS) {
1128 
1129 		if (add_tgt) {
1130 			/*
1131 			 * we found an existing property -- we might need
1132 			 *	to add to it
1133 			 */
1134 			for (i = 0; i < nelements; i++) {
1135 				if (tgt_list[i] == tgt) {
1136 					/* target already in list */
1137 					SCSI_PROBE_DEBUG1(2, "SCSA post-probe:"
1138 					    " tgt %d already listed\n", tgt);
1139 					ddi_prop_free(tgt_list);
1140 					return;
1141 				}
1142 			}
1143 
1144 			/*
1145 			 * need to append our target number to end of list
1146 			 *	(no need sorting list, as it's so short)
1147 			 */
1148 
1149 			/*
1150 			 * will this new entry fit ?? -- it should, since
1151 			 *	the array is 16-wide and only keep track of
1152 			 *	16 targets, but check just in case
1153 			 */
1154 			new_nelements = nelements + 1;
1155 			if (new_nelements >= NTARGETS_WIDE) {
1156 				SCSI_PROBE_DEBUG0(1, "SCSA post-probe: "
1157 				    "internal error: no room "
1158 				    "for more targets?\n");
1159 				ddi_prop_free(tgt_list);
1160 				return;
1161 			}
1162 
1163 			/* copy existing list then add our tgt number to end */
1164 			bcopy((void *)tgt_list, (void *)new_tgt_list,
1165 			    sizeof (uchar_t) * nelements);
1166 			new_tgt_list[new_nelements - 1] = (uchar_t)tgt;
1167 		} else {
1168 			/*
1169 			 * we need to remove our target number from the list,
1170 			 *	so copy all of the other target numbers,
1171 			 *	skipping ours
1172 			 */
1173 			int	tgt_removed = 0;
1174 
1175 			new_nelements = 0;
1176 			for (i = 0; i < nelements; i++) {
1177 				if (tgt_list[i] != tgt) {
1178 					new_tgt_list[new_nelements++] =
1179 					    tgt_list[i];
1180 				} else {
1181 					/* skip this target */
1182 					tgt_removed++;
1183 				}
1184 			}
1185 
1186 			if (!tgt_removed) {
1187 				SCSI_PROBE_DEBUG1(2, "SCSA post-probe:"
1188 				    " no need to remove tgt %d\n", tgt);
1189 				ddi_prop_free(tgt_list);
1190 				return;
1191 			}
1192 		}
1193 
1194 		update_result = ddi_prop_update_byte_array(DDI_DEV_T_NONE,
1195 		    pdevi, SS2_LUN0_TGT_LIST_PROP, new_tgt_list,
1196 		    new_nelements);
1197 
1198 		ddi_prop_free(tgt_list);
1199 	} else {
1200 		/*
1201 		 * no property yet
1202 		 */
1203 		if (add_tgt) {
1204 			/*
1205 			 * create a property with just our tgt
1206 			 */
1207 			new_tgt_list[0] = (uchar_t)tgt;
1208 			new_nelements = 1;	/* just one element */
1209 
1210 			update_result = ddi_prop_update_byte_array(
1211 			    DDI_DEV_T_NONE, pdevi, SS2_LUN0_TGT_LIST_PROP,
1212 			    new_tgt_list, new_nelements);
1213 		} else {
1214 			/*
1215 			 * no list so no need to remove tgt from that list
1216 			 */
1217 			return;
1218 		}
1219 	}
1220 
1221 #ifdef	DEBUG
1222 	/*
1223 	 * if we get here we have tried to add/update properties
1224 	 */
1225 	if (update_result != DDI_PROP_SUCCESS) {
1226 		SCSI_PROBE_DEBUG2(1, "SCSA post-probe: can't update parent "
1227 		    "property with tgt=%d (%d)\n", tgt, update_result);
1228 	} else {
1229 		if (add_tgt) {
1230 			SCSI_PROBE_DEBUG3(2,
1231 			    "SCSA post-probe: added tgt=%d to parent "
1232 			    "prop=\"%s\" (now %d entries)\n",
1233 			    tgt, SS2_LUN0_TGT_LIST_PROP, new_nelements);
1234 		} else {
1235 			SCSI_PROBE_DEBUG3(2,
1236 			    "SCSA post-probe: removed tgt=%d from parent "
1237 			    "prop=\"%s\" (now %d entries)\n",
1238 			    tgt, SS2_LUN0_TGT_LIST_PROP, new_nelements);
1239 		}
1240 	}
1241 #endif
1242 }
1243