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