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