xref: /titanic_50/usr/src/uts/common/io/scsi/targets/sgen.c (revision 193974072f41a843678abf5f61979c748687e66b)
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 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright Siemens 1999
29  * All rights reserved.
30  */
31 
32 
33 /*
34  * sgen - SCSI generic device driver
35  *
36  * The sgen driver provides user programs access to SCSI devices that
37  * are not supported by other drivers by providing the USCSI(7I) interface.
38  */
39 
40 #include <sys/modctl.h>
41 #include <sys/file.h>
42 #include <sys/scsi/scsi.h>
43 #include <sys/scsi/targets/sgendef.h>
44 
45 /* The name of the driver, established from the module name in _init. */
46 static	char *sgen_label	= NULL;
47 
48 #define	DDI_NT_SGEN		"ddi_generic:scsi"
49 
50 static char *sgen_devtypes[] = {
51 	"direct",		/* 0x00 -- disks */
52 	"sequential",		/* 0x01 */
53 	"printer",		/* 0x02 */
54 	"processor",		/* 0x03 */
55 	"worm",			/* 0x04 */
56 	"rodirect",		/* 0x05 */
57 	"scanner",		/* 0x06 */
58 	"optical",		/* 0x07 */
59 	"changer",		/* 0x08 */
60 	"comm",			/* 0x09 */
61 	"prepress1",		/* 0x0a -- reserved for prepress (ASC IT8) */
62 	"prepress2",		/* 0x0b -- reserved for prepress (ASC IT8) */
63 	"array_ctrl",		/* 0x0c -- storage array */
64 	"ses",			/* 0x0d -- enclosure services */
65 	"rbc",			/* 0x0e -- simplified block */
66 	"ocrw",			/* 0x0f -- optical card read/write */
67 	"bridge",		/* 0x10 -- reserved for bridging expanders */
68 	"type_0x11",		/* 0x11 */
69 	"type_0x12",		/* 0x12 */
70 	"type_0x13",		/* 0x13 */
71 	"type_0x14",		/* 0x14 */
72 	"type_0x15",		/* 0x15 */
73 	"type_0x16",		/* 0x16 */
74 	"type_0x17",		/* 0x17 */
75 	"type_0x18",		/* 0x18 */
76 	"type_0x19",		/* 0x19 */
77 	"type_0x1a",		/* 0x1a */
78 	"type_0x1b",		/* 0x1b */
79 	"type_0x1c",		/* 0x1c */
80 	"type_0x1d",		/* 0x1d */
81 	"type_0x1e",		/* 0x1e */
82 	"type_unknown"		/* 0x1f is "no device type" or "unknown" */
83 };
84 
85 #define	SGEN_NDEVTYPES ((sizeof (sgen_devtypes) / sizeof (char *)))
86 
87 #define	SGEN_INQSTRLEN 24
88 #define	SGEN_VENDID_MAX 8
89 #define	SGEN_PRODID_MAX 16
90 
91 #define	FILL_SCSI1_LUN(devp, pkt) 					\
92 	if ((devp)->sd_inq->inq_ansi == 0x1) {				\
93 		int _lun;						\
94 		_lun = ddi_prop_get_int(DDI_DEV_T_ANY, (devp)->sd_dev,	\
95 		    DDI_PROP_DONTPASS, SCSI_ADDR_PROP_LUN, 0);		\
96 		if (_lun > 0) {						\
97 			((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun =	\
98 			    _lun;					\
99 		}							\
100 	}
101 
102 #define	SGEN_DO_ERRSTATS(sg_state, x)  \
103 	if (sg_state->sgen_kstats) { \
104 		struct sgen_errstats *sp; \
105 		sp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data; \
106 		sp->x.value.ui32++; \
107 	}
108 
109 #define	SCBP_C(pkt)	((*(pkt)->pkt_scbp) & STATUS_MASK)
110 
111 /*
112  * Standard entrypoints
113  */
114 static int sgen_attach(dev_info_t *, ddi_attach_cmd_t);
115 static int sgen_detach(dev_info_t *, ddi_detach_cmd_t);
116 static int sgen_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
117 static int sgen_probe(dev_info_t *);
118 static int sgen_open(dev_t *, int, int, cred_t *);
119 static int sgen_close(dev_t, int, int, cred_t *);
120 static int sgen_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
121 
122 /*
123  * Configuration routines
124  */
125 static int sgen_do_attach(dev_info_t *);
126 static int sgen_setup_sense(sgen_state_t *);
127 static void sgen_create_errstats(sgen_state_t *, int);
128 static int sgen_do_suspend(dev_info_t *);
129 static int sgen_do_detach(dev_info_t *);
130 static void sgen_setup_binddb(dev_info_t *);
131 static void sgen_cleanup_binddb();
132 
133 /*
134  * Packet transport routines
135  */
136 static int  sgen_uscsi_cmd(dev_t, struct uscsi_cmd *, int);
137 static int sgen_start(struct buf *);
138 static int sgen_hold_cmdbuf(sgen_state_t *);
139 static void sgen_rele_cmdbuf(sgen_state_t *);
140 static int sgen_make_uscsi_cmd(sgen_state_t *, struct buf *);
141 static void sgen_restart(void *);
142 static void sgen_callback(struct scsi_pkt *);
143 static int sgen_handle_autosense(sgen_state_t *, struct scsi_pkt *);
144 static int sgen_handle_sense(sgen_state_t *);
145 static int sgen_handle_incomplete(sgen_state_t *, struct scsi_pkt *);
146 static int sgen_check_error(sgen_state_t *, struct buf *);
147 static int sgen_initiate_sense(sgen_state_t *, int);
148 static int sgen_scsi_transport(struct scsi_pkt *);
149 static int sgen_tur(dev_t);
150 
151 /*
152  * Logging/debugging routines
153  */
154 static void sgen_log(sgen_state_t  *, int,  const char *, ...);
155 static int sgen_diag_ok(sgen_state_t *, int);
156 static void sgen_dump_cdb(sgen_state_t *, const char *, union scsi_cdb *, int);
157 static void sgen_dump_sense(sgen_state_t *, size_t, uchar_t *);
158 
159 int sgen_diag = 0;
160 int sgen_sporadic_failures = 0;
161 int sgen_force_manual_sense = 0;
162 struct sgen_binddb sgen_binddb;
163 
164 static struct cb_ops sgen_cb_ops = {
165 	sgen_open,			/* open */
166 	sgen_close,			/* close */
167 	nodev,				/* strategy */
168 	nodev,				/* print */
169 	nodev,				/* dump */
170 	nodev,				/* read */
171 	nodev,				/* write */
172 	sgen_ioctl,			/* ioctl */
173 	nodev,				/* devmap */
174 	nodev,				/* mmap */
175 	nodev,				/* segmap */
176 	nochpoll,			/* poll */
177 	ddi_prop_op,			/* cb_prop_op */
178 	0,				/* streamtab  */
179 	D_MP | D_NEW | D_HOTPLUG	/* Driver compatibility flag */
180 };
181 
182 static struct dev_ops sgen_dev_ops = {
183 	DEVO_REV,		/* devo_rev, */
184 	0,			/* refcnt  */
185 	sgen_getinfo,		/* info */
186 	nodev,			/* identify */
187 	sgen_probe,		/* probe */
188 	sgen_attach,		/* attach */
189 	sgen_detach,		/* detach */
190 	nodev,			/* reset */
191 	&sgen_cb_ops,		/* driver operations */
192 	(struct bus_ops *)0,	/* bus operations */
193 	NULL,			/* power */
194 	ddi_quiesce_not_supported,	/* devo_quiesce */
195 };
196 
197 static void *sgen_soft_state = NULL;
198 
199 static struct modldrv modldrv = {
200 	&mod_driverops, "SCSI generic driver", &sgen_dev_ops
201 };
202 
203 static struct modlinkage modlinkage = {
204 	MODREV_1, &modldrv, NULL
205 };
206 
207 int
_init(void)208 _init(void)
209 {
210 	int err;
211 
212 	/* establish driver name from module name */
213 	sgen_label = (char *)mod_modname(&modlinkage);
214 
215 	sgen_log(NULL, SGEN_DIAG2, "in sgen_init()");
216 	if ((err = ddi_soft_state_init(&sgen_soft_state,
217 	    sizeof (sgen_state_t), SGEN_ESTIMATED_NUM_DEVS)) != 0) {
218 		goto done;
219 	}
220 
221 	if ((err = mod_install(&modlinkage)) != 0) {
222 		ddi_soft_state_fini(&sgen_soft_state);
223 		goto done;
224 	}
225 
226 done:
227 	sgen_log(NULL, SGEN_DIAG2, "%s sgen_init()", err ? "failed" : "done");
228 	return (err);
229 }
230 
231 int
_fini(void)232 _fini(void)
233 {
234 	int err;
235 	sgen_log(NULL, SGEN_DIAG2, "in sgen_fini()");
236 
237 	if ((err = mod_remove(&modlinkage)) != 0) {
238 		goto done;
239 	}
240 
241 	ddi_soft_state_fini(&sgen_soft_state);
242 	sgen_cleanup_binddb();
243 
244 done:
245 	sgen_log(NULL, SGEN_DIAG2, "%s sgen_fini()", err ? "failed" : "done");
246 	return (err);
247 }
248 
249 int
_info(struct modinfo * modinfop)250 _info(struct modinfo *modinfop)
251 {
252 	return (mod_info(&modlinkage, modinfop));
253 }
254 
255 /*
256  * sgen_typename()
257  * 	return a device type's name by looking it up in the sgen_devtypes table.
258  */
259 static char *
sgen_typename(uchar_t typeno)260 sgen_typename(uchar_t typeno)
261 {
262 	if (typeno >= SGEN_NDEVTYPES)
263 		return ("type_unknown");
264 	return (sgen_devtypes[typeno]);
265 }
266 
267 /*
268  * sgen_typenum()
269  * 	return a device type's number by looking it up in the sgen_devtypes
270  * 	table.
271  */
272 static int
sgen_typenum(const char * typename,uchar_t * typenum)273 sgen_typenum(const char *typename, uchar_t *typenum)
274 {
275 	int i;
276 	for (i = 0; i < SGEN_NDEVTYPES; i++) {
277 		if (strcasecmp(sgen_devtypes[i], typename) == 0) {
278 			*typenum = (uchar_t)i;
279 			return (0);
280 		}
281 	}
282 	return (-1);
283 }
284 
285 /*
286  * sgen_setup_binddb()
287  * 	initialize a data structure which stores all of the information about
288  * 	which devices and device types the driver should bind to.
289  */
290 static void
sgen_setup_binddb(dev_info_t * dip)291 sgen_setup_binddb(dev_info_t *dip)
292 {
293 	char **strs = NULL, *cp, *pcp, *vcp;
294 	uint_t nelems, pcplen, vcplen, idx;
295 
296 	ASSERT(sgen_binddb.sdb_init == 0);
297 	ASSERT(MUTEX_HELD(&sgen_binddb.sdb_lock));
298 
299 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
300 	    "device-type-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
301 		/*
302 		 * for each device type specifier make a copy and put it into a
303 		 * node in the binddb.
304 		 */
305 		for (idx = 0; idx < nelems; idx++) {
306 			sgen_type_node_t *nodep;
307 			uchar_t devtype;
308 			cp = strs[idx];
309 			if (sgen_typenum(cp, &devtype) != 0) {
310 				sgen_log(NULL, CE_WARN,
311 				    "unknown device type '%s', "
312 				    "device unit-address @%s",
313 				    cp, ddi_get_name_addr(dip));
314 				continue;
315 			}
316 			nodep = kmem_zalloc(sizeof (sgen_type_node_t),
317 			    KM_SLEEP);
318 			nodep->node_type = devtype;
319 			nodep->node_next = sgen_binddb.sdb_type_nodes;
320 			sgen_binddb.sdb_type_nodes = nodep;
321 
322 			sgen_log(NULL, SGEN_DIAG2, "found device type "
323 			    "'%s' in device-type-config-list, "
324 			    "device unit-address @%s",
325 			    cp, ddi_get_name_addr(dip));
326 		}
327 		ddi_prop_free(strs);
328 	}
329 
330 	/*
331 	 * for each Vendor/Product inquiry pair, build a node and put it
332 	 * into the the binddb.
333 	 */
334 	if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
335 	    "inquiry-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
336 
337 		if (nelems % 2 == 1) {
338 			sgen_log(NULL, CE_WARN, "inquiry-config-list must "
339 			    "contain Vendor/Product pairs, "
340 			    "device unit-address @%s",
341 			    ddi_get_name_addr(dip));
342 			nelems--;
343 		}
344 		for (idx = 0; idx < nelems; idx += 2) {
345 			sgen_inq_node_t *nodep;
346 			/*
347 			 * Grab vendor and product ID.
348 			 */
349 			vcp = strs[idx];
350 			vcplen = strlen(vcp);
351 			if (vcplen == 0 || vcplen > SGEN_VENDID_MAX) {
352 				sgen_log(NULL, CE_WARN,
353 				    "Invalid vendor ID '%s', "
354 				    "device unit-address @%s",
355 				    vcp, ddi_get_name_addr(dip));
356 				continue;
357 			}
358 
359 			pcp = strs[idx + 1];
360 			pcplen = strlen(pcp);
361 			if (pcplen == 0 || pcplen > SGEN_PRODID_MAX) {
362 				sgen_log(NULL, CE_WARN,
363 				    "Invalid product ID '%s', "
364 				    "device unit-address @%s",
365 				    pcp, ddi_get_name_addr(dip));
366 				continue;
367 			}
368 
369 			nodep = kmem_zalloc(sizeof (sgen_inq_node_t),
370 			    KM_SLEEP);
371 			nodep->node_vendor = kmem_alloc(vcplen + 1, KM_SLEEP);
372 			(void) strcpy(nodep->node_vendor, vcp);
373 			nodep->node_product = kmem_alloc(pcplen + 1, KM_SLEEP);
374 			(void) strcpy(nodep->node_product, pcp);
375 
376 			nodep->node_next = sgen_binddb.sdb_inq_nodes;
377 			sgen_binddb.sdb_inq_nodes = nodep;
378 
379 			sgen_log(NULL, SGEN_DIAG2, "found inquiry string "
380 			    "'%s' '%s' in device-type-config-list, "
381 			    "device unit-address @%s",
382 			    nodep->node_vendor, nodep->node_product,
383 			    ddi_get_name_addr(dip));
384 		}
385 		ddi_prop_free(strs);
386 	}
387 
388 	sgen_binddb.sdb_init = 1;
389 }
390 
391 /*
392  * sgen_cleanup_binddb()
393  * 	deallocate data structures for binding database.
394  */
395 static void
sgen_cleanup_binddb()396 sgen_cleanup_binddb()
397 {
398 	sgen_inq_node_t *inqp, *inqnextp;
399 	sgen_type_node_t *typep, *typenextp;
400 
401 	mutex_enter(&sgen_binddb.sdb_lock);
402 	if (sgen_binddb.sdb_init == 0) {
403 		mutex_exit(&sgen_binddb.sdb_lock);
404 		return;
405 	}
406 
407 	for (inqp = sgen_binddb.sdb_inq_nodes; inqp != NULL; inqp = inqnextp) {
408 		inqnextp = inqp->node_next;
409 		ASSERT(inqp->node_vendor && inqp->node_product);
410 		kmem_free(inqp->node_vendor,
411 		    strlen(inqp->node_vendor) + 1);
412 		kmem_free(inqp->node_product,
413 		    strlen(inqp->node_product) + 1);
414 		kmem_free(inqp, sizeof (sgen_inq_node_t));
415 	}
416 
417 	for (typep = sgen_binddb.sdb_type_nodes; typep != NULL;
418 	    typep = typenextp) {
419 		typenextp = typep->node_next;
420 		kmem_free(typep, sizeof (sgen_type_node_t));
421 	}
422 	mutex_exit(&sgen_binddb.sdb_lock);
423 }
424 
425 /*
426  * sgen_bind_byinq()
427  * 	lookup a device in the binding database by its inquiry data.
428  */
429 static int
sgen_bind_byinq(dev_info_t * dip)430 sgen_bind_byinq(dev_info_t *dip)
431 {
432 	sgen_inq_node_t *nodep;
433 	char vend_str[SGEN_VENDID_MAX+1];
434 	char prod_str[SGEN_PRODID_MAX+1];
435 	struct scsi_device *scsidevp;
436 
437 	scsidevp = ddi_get_driver_private(dip);
438 
439 	/*
440 	 * inq_vid and inq_pid are laid out by the protocol in order in the
441 	 * inquiry structure, and are not delimited by \0.
442 	 */
443 	bcopy(scsidevp->sd_inq->inq_vid, vend_str, SGEN_VENDID_MAX);
444 	vend_str[SGEN_VENDID_MAX] = '\0';
445 	bcopy(scsidevp->sd_inq->inq_pid, prod_str, SGEN_PRODID_MAX);
446 	prod_str[SGEN_PRODID_MAX] = '\0';
447 
448 	for (nodep = sgen_binddb.sdb_inq_nodes; nodep != NULL;
449 	    nodep = nodep->node_next) {
450 		/*
451 		 * Allow the "*" wildcard to match all vendor IDs.
452 		 */
453 		if (strcmp(nodep->node_vendor, "*") != 0) {
454 			if (strncasecmp(nodep->node_vendor, vend_str,
455 			    strlen(nodep->node_vendor)) != 0) {
456 				continue;
457 			}
458 		}
459 
460 		/*
461 		 * Using strncasecmp() with the key length allows substring
462 		 * matching for product data.
463 		 */
464 		if (strncasecmp(nodep->node_product, prod_str,
465 		    strlen(nodep->node_product)) == 0) {
466 			return (0);
467 		}
468 	}
469 	return (-1);
470 }
471 
472 /*
473  * sgen_bind_bytype()
474  * 	lookup a device type in the binding database; if found, return a
475  * 	format string corresponding to the string in the .conf file.
476  */
477 static int
sgen_bind_bytype(dev_info_t * dip)478 sgen_bind_bytype(dev_info_t *dip)
479 {
480 	sgen_type_node_t *nodep;
481 	struct scsi_device *scsidevp;
482 
483 	scsidevp = ddi_get_driver_private(dip);
484 
485 	for (nodep = sgen_binddb.sdb_type_nodes; nodep != NULL;
486 	    nodep = nodep->node_next) {
487 		if (nodep->node_type == scsidevp->sd_inq->inq_dtype) {
488 			return (0);
489 		}
490 	}
491 	return (-1);
492 }
493 
494 /*
495  * sgen_get_binding()
496  * 	Check to see if the device in question matches the criteria for
497  * 	sgen to bind.
498  *
499  * 	Either the .conf file must specify a device_type entry which
500  * 	matches the SCSI device type of this device, or the inquiry
501  * 	string provided by the device must match an inquiry string specified
502  * 	in the .conf file.  Inquiry data is matched first.
503  */
504 static int
sgen_get_binding(dev_info_t * dip)505 sgen_get_binding(dev_info_t *dip)
506 {
507 	int retval = 0;
508 
509 	mutex_enter(&sgen_binddb.sdb_lock);
510 	if (sgen_binddb.sdb_init == 0)
511 		sgen_setup_binddb(dip);
512 	mutex_exit(&sgen_binddb.sdb_lock);
513 
514 
515 	/*
516 	 * Check device-type-config-list for a match by device type.
517 	 */
518 	if (sgen_bind_bytype(dip) == 0)
519 		goto done;
520 
521 	/*
522 	 * Check inquiry-config-list for a match by Vendor/Product ID.
523 	 */
524 	if (sgen_bind_byinq(dip) == 0)
525 		goto done;
526 
527 	retval = -1;
528 done:
529 	return (retval);
530 }
531 
532 /*
533  * sgen_attach()
534  * 	attach(9e) entrypoint.
535  */
536 static int
sgen_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)537 sgen_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
538 {
539 	int err;
540 
541 	sgen_log(NULL, SGEN_DIAG2, "in sgen_attach(), device unit-address @%s",
542 	    ddi_get_name_addr(dip));
543 
544 	switch (cmd) {
545 	case DDI_ATTACH:
546 		err = sgen_do_attach(dip);
547 		break;
548 	case DDI_RESUME:
549 		err = DDI_SUCCESS;
550 		break;
551 	case DDI_PM_RESUME:
552 	default:
553 		err = DDI_FAILURE;
554 		break;
555 	}
556 
557 done:
558 	sgen_log(NULL, SGEN_DIAG2, "%s sgen_attach(), device unit-address @%s",
559 	    err == DDI_SUCCESS ? "done" : "failed", ddi_get_name_addr(dip));
560 	return (err);
561 }
562 
563 /*
564  * sgen_do_attach()
565  *	handle the nitty details of attach.
566  */
567 static int
sgen_do_attach(dev_info_t * dip)568 sgen_do_attach(dev_info_t *dip)
569 {
570 	int instance;
571 	struct scsi_device *scsidevp;
572 	sgen_state_t *sg_state;
573 	uchar_t devtype;
574 	struct scsi_inquiry *inq;
575 
576 	instance = ddi_get_instance(dip);
577 
578 	scsidevp = ddi_get_driver_private(dip);
579 	ASSERT(scsidevp);
580 
581 	sgen_log(NULL, SGEN_DIAG2, "sgen_do_attach: instance = %d, "
582 	    "device unit-address @%s", instance, ddi_get_name_addr(dip));
583 
584 	/*
585 	 * Probe the device in order to get its device type to name the minor
586 	 * node.
587 	 */
588 	if (scsi_probe(scsidevp, NULL_FUNC) != SCSIPROBE_EXISTS) {
589 		scsi_unprobe(scsidevp);
590 		return (DDI_FAILURE);
591 	}
592 
593 	if (ddi_soft_state_zalloc(sgen_soft_state, instance) != DDI_SUCCESS) {
594 		sgen_log(NULL, SGEN_DIAG1,
595 		    "sgen_do_attach: failed to allocate softstate, "
596 		    "device unit-address @%s", ddi_get_name_addr(dip));
597 		scsi_unprobe(scsidevp);
598 		return (DDI_FAILURE);
599 	}
600 
601 	inq = scsidevp->sd_inq;		/* valid while device is probed... */
602 	devtype = inq->inq_dtype;
603 
604 	sg_state = ddi_get_soft_state(sgen_soft_state, instance);
605 	sg_state->sgen_scsidev = scsidevp;
606 	scsidevp->sd_dev = dip;
607 
608 	/*
609 	 * Now that sg_state->sgen_scsidev is initialized, it's ok to
610 	 * call sgen_log with sg_state instead of NULL.
611 	 */
612 
613 	/*
614 	 * If the user specified the sgen_diag property, override the global
615 	 * sgen_diag setting by setting sg_state's sgen_diag value.  If the
616 	 * user gave a value out of range, default to '0'.
617 	 */
618 	sg_state->sgen_diag = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
619 	    "sgen-diag", -1);
620 
621 	if (sg_state->sgen_diag != -1) {
622 		if (sg_state->sgen_diag < 0 || sg_state->sgen_diag > 3)
623 			sg_state->sgen_diag = 0;
624 	}
625 
626 	sgen_log(sg_state, SGEN_DIAG2,
627 	    "sgen_do_attach: sgen_soft_state=0x%p, instance=%d, "
628 	    "device unit-address @%s",
629 	    sgen_soft_state, instance, ddi_get_name_addr(dip));
630 
631 	/*
632 	 * For simplicity, the minor number == the instance number
633 	 */
634 	if (ddi_create_minor_node(dip, sgen_typename(devtype), S_IFCHR,
635 	    instance, DDI_NT_SGEN, NULL) == DDI_FAILURE) {
636 		scsi_unprobe(scsidevp);
637 		ddi_prop_remove_all(dip);
638 		sgen_log(sg_state, SGEN_DIAG1,
639 		    "sgen_do_attach: minor node creation failed, "
640 		    "device unit-address @%s", ddi_get_name_addr(dip));
641 		ddi_soft_state_free(sgen_soft_state, instance);
642 		return (DDI_FAILURE);
643 	}
644 
645 	/*
646 	 * Allocate the command buffer, then create a condition variable for
647 	 * managing it; mark the command buffer as free.
648 	 */
649 	sg_state->sgen_cmdbuf = getrbuf(KM_SLEEP);
650 	cv_init(&sg_state->sgen_cmdbuf_cv, NULL, CV_DRIVER, NULL);
651 
652 	SGEN_CLR_BUSY(sg_state);
653 	SGEN_CLR_OPEN(sg_state);
654 	SGEN_CLR_SUSP(sg_state);
655 
656 	/*
657 	 * If the hba and the target both support wide xfers, enable them.
658 	 */
659 	if (scsi_ifgetcap(&sg_state->sgen_scsiaddr, "wide-xfer", 1) != -1) {
660 		int wide = 0;
661 		if ((inq->inq_rdf == RDF_SCSI2) &&
662 		    (inq->inq_wbus16 || inq->inq_wbus32))
663 			wide = 1;
664 		if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "wide-xfer",
665 		    wide, 1) == 1) {
666 			sgen_log(sg_state, SGEN_DIAG1,
667 			    "sgen_attach: wide xfer %s, "
668 			    "device unit-address @%s",
669 			    wide ? "enabled" : "disabled",
670 			    ddi_get_name_addr(dip));
671 		}
672 	}
673 
674 	/*
675 	 * This is a little debugging code-- since the codepath for auto-sense
676 	 * and 'manual' sense is split, toggling this variable will make
677 	 * sgen act as though the adapter in question can't do auto-sense.
678 	 */
679 	if (sgen_force_manual_sense) {
680 		if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "auto-rqsense",
681 		    0, 1) == 1) {
682 			sg_state->sgen_arq_enabled = 0;
683 		} else {
684 			sg_state->sgen_arq_enabled = 1;
685 		}
686 	} else {
687 		/*
688 		 * Enable autorequest sense, if supported
689 		 */
690 		if (scsi_ifgetcap(&sg_state->sgen_scsiaddr,
691 		    "auto-rqsense", 1) != 1) {
692 			if (scsi_ifsetcap(&sg_state->sgen_scsiaddr,
693 			    "auto-rqsense", 1, 1) == 1) {
694 				sg_state->sgen_arq_enabled = 1;
695 				sgen_log(sg_state, SGEN_DIAG1,
696 				    "sgen_attach: auto-request-sense enabled, "
697 				    "device unit-address @%s",
698 				    ddi_get_name_addr(dip));
699 			} else {
700 				sg_state->sgen_arq_enabled = 0;
701 				sgen_log(sg_state, SGEN_DIAG1,
702 				    "sgen_attach: auto-request-sense disabled, "
703 				    "device unit-address @%s",
704 				    ddi_get_name_addr(dip));
705 			}
706 		} else {
707 			sg_state->sgen_arq_enabled = 1;	/* already enabled */
708 			sgen_log(sg_state, SGEN_DIAG1,
709 			    "sgen_attach: auto-request-sense enabled, "
710 			    "device unit-address @%s", ddi_get_name_addr(dip));
711 		}
712 	}
713 
714 	/*
715 	 * Allocate plumbing for manually fetching sense.
716 	 */
717 	if (sgen_setup_sense(sg_state) != 0) {
718 		freerbuf(sg_state->sgen_cmdbuf);
719 		ddi_prop_remove_all(dip);
720 		ddi_remove_minor_node(dip, NULL);
721 		scsi_unprobe(scsidevp);
722 		sgen_log(sg_state, SGEN_DIAG1,
723 		    "sgen_do_attach: failed to setup request-sense, "
724 		    "device unit-address @%s", ddi_get_name_addr(dip));
725 		ddi_soft_state_free(sgen_soft_state, instance);
726 		return (DDI_FAILURE);
727 	}
728 
729 	sgen_create_errstats(sg_state, instance);
730 
731 	ddi_report_dev(dip);
732 
733 	return (DDI_SUCCESS);
734 }
735 
736 /*
737  * sgen_setup_sense()
738  * 	Allocate a request sense packet so that if sgen needs to fetch sense
739  * 	data for the user, it will have a pkt ready to send.
740  */
741 static int
sgen_setup_sense(sgen_state_t * sg_state)742 sgen_setup_sense(sgen_state_t *sg_state)
743 {
744 	struct buf *bp;
745 	struct scsi_pkt *rqpkt;
746 
747 	if ((bp = scsi_alloc_consistent_buf(&sg_state->sgen_scsiaddr, NULL,
748 	    MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) {
749 		return (-1);
750 	}
751 
752 	if ((rqpkt = scsi_init_pkt(&sg_state->sgen_scsiaddr, NULL, bp,
753 	    CDB_GROUP0, 1, 0, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) {
754 		scsi_free_consistent_buf(bp);
755 		return (-1);
756 	}
757 
758 	/*
759 	 * Make the results of running a SENSE available by filling out the
760 	 * sd_sense field of the scsi device (sgen_sense is just an alias).
761 	 */
762 	sg_state->sgen_sense = (struct scsi_extended_sense *)bp->b_un.b_addr;
763 
764 	(void) scsi_setup_cdb((union scsi_cdb *)rqpkt->pkt_cdbp,
765 	    SCMD_REQUEST_SENSE, 0, MAX_SENSE_LENGTH, 0);
766 	FILL_SCSI1_LUN(sg_state->sgen_scsidev, rqpkt);
767 
768 	rqpkt->pkt_comp = sgen_callback;
769 	rqpkt->pkt_time = SGEN_IO_TIME;
770 	rqpkt->pkt_flags |= FLAG_SENSING;
771 	rqpkt->pkt_private = sg_state;
772 
773 	sg_state->sgen_rqspkt = rqpkt;
774 	sg_state->sgen_rqsbuf = bp;
775 
776 	return (0);
777 }
778 
779 /*
780  * sgen_create_errstats()
781  * 	create named kstats for tracking occurrence of errors.
782  */
783 static void
sgen_create_errstats(sgen_state_t * sg_state,int instance)784 sgen_create_errstats(sgen_state_t *sg_state, int instance)
785 {
786 	char kstatname[KSTAT_STRLEN];
787 	struct sgen_errstats *stp;
788 
789 	(void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,err",
790 	    sgen_label, instance);
791 	sg_state->sgen_kstats = kstat_create("sgenerr", instance,
792 	    kstatname, "device_error", KSTAT_TYPE_NAMED,
793 	    sizeof (struct sgen_errstats) / sizeof (kstat_named_t),
794 	    KSTAT_FLAG_PERSISTENT);
795 
796 	if (sg_state->sgen_kstats == NULL)
797 		return;
798 
799 	stp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data;
800 	kstat_named_init(&stp->sgen_trans_err, "transport_errors",
801 	    KSTAT_DATA_UINT32);
802 	kstat_named_init(&stp->sgen_restart, "command_restarts",
803 	    KSTAT_DATA_UINT32);
804 	kstat_named_init(&stp->sgen_incmp_err, "incomplete_commands",
805 	    KSTAT_DATA_UINT32);
806 	kstat_named_init(&stp->sgen_autosen_rcv, "autosense_occurred",
807 	    KSTAT_DATA_UINT32);
808 	kstat_named_init(&stp->sgen_autosen_bad, "autosense_undecipherable",
809 	    KSTAT_DATA_UINT32);
810 	kstat_named_init(&stp->sgen_sense_rcv, "sense_fetches",
811 	    KSTAT_DATA_UINT32);
812 	kstat_named_init(&stp->sgen_sense_bad, "sense_data_undecipherable",
813 	    KSTAT_DATA_UINT32);
814 	kstat_named_init(&stp->sgen_recov_err, "recoverable_error",
815 	    KSTAT_DATA_UINT32);
816 	kstat_named_init(&stp->sgen_nosen_err, "NO_SENSE_sense_key",
817 	    KSTAT_DATA_UINT32);
818 	kstat_named_init(&stp->sgen_unrecov_err, "unrecoverable_sense_error",
819 	    KSTAT_DATA_UINT32);
820 	sg_state->sgen_kstats->ks_private = sg_state;
821 	sg_state->sgen_kstats->ks_update = nulldev;
822 	kstat_install(sg_state->sgen_kstats);
823 }
824 
825 /*
826  * sgen_detach()
827  * 	detach(9E) entrypoint
828  */
829 static int
sgen_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)830 sgen_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
831 {
832 	int instance;
833 	sgen_state_t *sg_state;
834 
835 	instance = ddi_get_instance(dip);
836 	sg_state = ddi_get_soft_state(sgen_soft_state, instance);
837 
838 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_detach(), "
839 	    "device unit-address @%s", ddi_get_name_addr(dip));
840 
841 	if (sg_state == NULL) {
842 		sgen_log(NULL, SGEN_DIAG1,
843 		    "sgen_detach: failed, no softstate found (%d), "
844 		    "device unit-address @%s",
845 		    instance, ddi_get_name_addr(dip));
846 		return (DDI_FAILURE);
847 	}
848 
849 	switch (cmd) {
850 	case DDI_DETACH:
851 		return (sgen_do_detach(dip));
852 	case DDI_SUSPEND:
853 		return (sgen_do_suspend(dip));
854 	case DDI_PM_SUSPEND:
855 	default:
856 		return (DDI_FAILURE);
857 	}
858 }
859 
860 /*
861  * sgen_do_detach()
862  * 	detach the driver, tearing down resources.
863  */
864 static int
sgen_do_detach(dev_info_t * dip)865 sgen_do_detach(dev_info_t *dip)
866 {
867 	int instance;
868 	sgen_state_t *sg_state;
869 	struct scsi_device *devp;
870 
871 	instance = ddi_get_instance(dip);
872 	sg_state = ddi_get_soft_state(sgen_soft_state, instance);
873 	ASSERT(sg_state);
874 
875 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_detach(), "
876 	    "device unit-address @%s", ddi_get_name_addr(dip));
877 	devp = ddi_get_driver_private(dip);
878 
879 	mutex_enter(&sg_state->sgen_mutex);
880 	if (SGEN_IS_BUSY(sg_state)) {
881 		mutex_exit(&sg_state->sgen_mutex);
882 		sgen_log(sg_state, SGEN_DIAG1, "sgen_do_detach: failed because "
883 		    "device is busy, device unit-address @%s",
884 		    ddi_get_name_addr(dip));
885 		return (DDI_FAILURE);
886 	}
887 	mutex_exit(&sg_state->sgen_mutex);
888 
889 	/*
890 	 * Final approach for detach.  Free data allocated by scsi_probe()
891 	 * in attach.
892 	 */
893 	if (sg_state->sgen_restart_timeid)
894 		(void) untimeout(sg_state->sgen_restart_timeid);
895 	sg_state->sgen_restart_timeid = 0;
896 	scsi_unprobe(devp);
897 
898 	/*
899 	 * Free auto-request plumbing.
900 	 */
901 	scsi_free_consistent_buf(sg_state->sgen_rqsbuf);
902 	scsi_destroy_pkt(sg_state->sgen_rqspkt);
903 
904 	if (sg_state->sgen_kstats) {
905 		kstat_delete(sg_state->sgen_kstats);
906 		sg_state->sgen_kstats = NULL;
907 	}
908 
909 	/*
910 	 * Free command buffer and clean up
911 	 */
912 	freerbuf(sg_state->sgen_cmdbuf);
913 	cv_destroy(&sg_state->sgen_cmdbuf_cv);
914 
915 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_detach(), "
916 	    "device unit-address @%s", ddi_get_name_addr(dip));
917 
918 	ddi_soft_state_free(sgen_soft_state, instance);
919 	ddi_prop_remove_all(dip);
920 	ddi_remove_minor_node(dip, NULL);
921 	return (DDI_SUCCESS);
922 }
923 
924 /*
925  * sgen_do_suspend()
926  * 	suspend the driver.  This sets the "suspend" bit for this target if it
927  * 	is currently open; once resumed, the suspend bit will cause
928  * 	subsequent I/Os to fail.  We want user programs to close and
929  * 	reopen the device to acknowledge that they need to reexamine its
930  * 	state and do the right thing.
931  */
932 static int
sgen_do_suspend(dev_info_t * dip)933 sgen_do_suspend(dev_info_t *dip)
934 {
935 	int instance;
936 	sgen_state_t *sg_state;
937 
938 	instance = ddi_get_instance(dip);
939 	sg_state = ddi_get_soft_state(sgen_soft_state, instance);
940 	ASSERT(sg_state);
941 
942 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_suspend(), "
943 	    "device unit-address @%s", ddi_get_name_addr(dip));
944 
945 	if (sg_state->sgen_restart_timeid) {
946 		(void) untimeout(sg_state->sgen_restart_timeid);
947 	}
948 	sg_state->sgen_restart_timeid = 0;
949 
950 	mutex_enter(&sg_state->sgen_mutex);
951 	if (SGEN_IS_OPEN(sg_state))
952 		SGEN_SET_SUSP(sg_state);
953 	mutex_exit(&sg_state->sgen_mutex);
954 
955 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_suspend(), "
956 	    "device unit-address @%s", ddi_get_name_addr(dip));
957 	return (DDI_SUCCESS);
958 }
959 
960 /*
961  * sgen_getinfo()
962  *	getinfo(9e) entrypoint.
963  */
964 /*ARGSUSED*/
965 static int
sgen_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)966 sgen_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
967 {
968 	dev_t dev;
969 	sgen_state_t *sg_state;
970 	int instance, error;
971 	switch (infocmd) {
972 	case DDI_INFO_DEVT2DEVINFO:
973 		dev = (dev_t)arg;
974 		instance = getminor(dev);
975 		if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance))
976 		    == NULL)
977 			return (DDI_FAILURE);
978 		*result = (void *) sg_state->sgen_scsidev->sd_dev;
979 		error = DDI_SUCCESS;
980 		break;
981 	case DDI_INFO_DEVT2INSTANCE:
982 		dev = (dev_t)arg;
983 		instance = getminor(dev);
984 		*result = (void *)(uintptr_t)instance;
985 		error = DDI_SUCCESS;
986 		break;
987 	default:
988 		error = DDI_FAILURE;
989 	}
990 	return (error);
991 }
992 
993 /*
994  * sgen_probe()
995  * 	probe(9e) entrypoint.  sgen *never* returns DDI_PROBE_PARTIAL, in
996  * 	order to avoid leaving around extra devinfos.  If sgen's binding
997  * 	rules indicate that it should bind, it returns DDI_PROBE_SUCCESS.
998  */
999 static int
sgen_probe(dev_info_t * dip)1000 sgen_probe(dev_info_t *dip)
1001 {
1002 	struct scsi_device *scsidevp;
1003 	int instance;
1004 	int rval;
1005 
1006 	scsidevp = ddi_get_driver_private(dip);
1007 	instance = ddi_get_instance(dip);
1008 	sgen_log(NULL, SGEN_DIAG2, "in sgen_probe(): instance = %d, "
1009 	    "device unit-address @%s", instance, ddi_get_name_addr(dip));
1010 
1011 	if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
1012 		return (DDI_PROBE_DONTCARE);
1013 
1014 	if (ddi_get_soft_state(sgen_soft_state, instance) != NULL)
1015 		return (DDI_PROBE_FAILURE);
1016 
1017 	mutex_enter(&sgen_binddb.sdb_lock);
1018 	if (sgen_binddb.sdb_init == 0) {
1019 		sgen_setup_binddb(dip);
1020 	}
1021 	mutex_exit(&sgen_binddb.sdb_lock);
1022 
1023 	/*
1024 	 * A small optimization: if it's impossible for sgen to bind to
1025 	 * any devices, don't bother probing, just fail.
1026 	 */
1027 	if ((sgen_binddb.sdb_inq_nodes == NULL) &&
1028 	    (sgen_binddb.sdb_type_nodes == NULL)) {
1029 		return (DDI_PROBE_FAILURE);
1030 	}
1031 
1032 	if (scsi_probe(scsidevp, NULL_FUNC) == SCSIPROBE_EXISTS) {
1033 		if (sgen_get_binding(dip) == 0) {
1034 			rval = DDI_PROBE_SUCCESS;
1035 		}
1036 	} else {
1037 		rval = DDI_PROBE_FAILURE;
1038 	}
1039 	scsi_unprobe(scsidevp);
1040 
1041 	sgen_log(NULL, SGEN_DIAG2, "sgen_probe() %s, device unit-address @%s",
1042 	    rval == DDI_PROBE_SUCCESS ? "succeeded" : "failed",
1043 	    ddi_get_name_addr(dip));
1044 	return (rval);
1045 }
1046 
1047 /*
1048  * sgen_open()
1049  * 	open(9e) entrypoint.  sgen enforces a strict exclusive open policy per
1050  * 	target.
1051  */
1052 /*ARGSUSED1*/
1053 static int
sgen_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)1054 sgen_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
1055 {
1056 	dev_t dev = *dev_p;
1057 	sgen_state_t *sg_state;
1058 	int instance;
1059 
1060 	instance = getminor(dev);
1061 
1062 	if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1063 		return (ENXIO);
1064 
1065 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_open(): instance = %d",
1066 	    instance);
1067 
1068 	mutex_enter(&sg_state->sgen_mutex);
1069 
1070 	/*
1071 	 * Don't allow new opens of a suspended device until the last close has
1072 	 * happened.  This is rather simplistic, but keeps the implementation
1073 	 * straightforward.
1074 	 */
1075 	if (SGEN_IS_SUSP(sg_state)) {
1076 		mutex_exit(&sg_state->sgen_mutex);
1077 		return (EIO);
1078 	}
1079 
1080 	/*
1081 	 * Enforce exclusive access.
1082 	 */
1083 	if (SGEN_IS_EXCL(sg_state) ||
1084 	    (SGEN_IS_OPEN(sg_state) && (flag & FEXCL))) {
1085 		mutex_exit(&sg_state->sgen_mutex);
1086 		return (EBUSY);
1087 	}
1088 
1089 	if (flag & FEXCL)
1090 		SGEN_SET_EXCL(sg_state);
1091 
1092 	SGEN_SET_OPEN(sg_state);
1093 
1094 	mutex_exit(&sg_state->sgen_mutex);
1095 
1096 	return (0);
1097 }
1098 
1099 /*
1100  * sgen_close()
1101  * 	close(9e) entrypoint.
1102  */
1103 /*ARGSUSED1*/
1104 static int
sgen_close(dev_t dev,int flag,int otyp,cred_t * cred_p)1105 sgen_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
1106 {
1107 	sgen_state_t *sg_state;
1108 	int instance;
1109 
1110 	instance = getminor(dev);
1111 
1112 	if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1113 		return (ENXIO);
1114 
1115 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_close(): instance = %d",
1116 	    instance);
1117 
1118 	mutex_enter(&sg_state->sgen_mutex);
1119 	SGEN_CLR_OPEN(sg_state);
1120 	SGEN_CLR_EXCL(sg_state);
1121 	SGEN_CLR_SUSP(sg_state); /* closing clears the 'I was suspended' bit */
1122 	mutex_exit(&sg_state->sgen_mutex);
1123 
1124 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_close()");
1125 
1126 	return (0);
1127 }
1128 
1129 /*
1130  * sgen_ioctl()
1131  * 	sgen supports the USCSI(7I) ioctl interface.
1132  */
1133 /*ARGSUSED4*/
1134 static int
sgen_ioctl(dev_t dev,int cmd,intptr_t arg,int flag,cred_t * cred_p,int * rval_p)1135 sgen_ioctl(dev_t dev,
1136     int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
1137 {
1138 	int retval = 0;
1139 	sgen_state_t *sg_state;
1140 	int instance;
1141 
1142 	instance = getminor(dev);
1143 
1144 	if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1145 		return (ENXIO);
1146 
1147 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_ioctl(): instance = %d",
1148 	    instance);
1149 
1150 	/*
1151 	 * If the driver has been suspended since the last open, fail all
1152 	 * subsequent IO's so that the userland consumer reinitializes state.
1153 	 */
1154 	mutex_enter(&sg_state->sgen_mutex);
1155 	if (SGEN_IS_SUSP(sg_state)) {
1156 		mutex_exit(&sg_state->sgen_mutex);
1157 		sgen_log(sg_state, SGEN_DIAG1, "sgen_ioctl: returning EIO: "
1158 		    "driver instance %d was previously suspended", instance);
1159 		return (EIO);
1160 	}
1161 	mutex_exit(&sg_state->sgen_mutex);
1162 
1163 	switch (cmd) {
1164 	case SGEN_IOC_DIAG: {
1165 		if (arg > 3) {
1166 			arg = 0;
1167 		}
1168 		sg_state->sgen_diag = (int)arg;
1169 		retval = 0;
1170 		break;
1171 	}
1172 
1173 	case SGEN_IOC_READY: {
1174 		if (sgen_tur(dev) != 0) {
1175 			retval = EIO;
1176 		} else {
1177 			retval = 0;
1178 		}
1179 		break;
1180 	}
1181 
1182 	case USCSICMD:
1183 		retval = sgen_uscsi_cmd(dev, (struct uscsi_cmd *)arg, flag);
1184 		break;
1185 
1186 	default:
1187 		retval = ENOTTY;
1188 	}
1189 
1190 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_ioctl(), returning %d",
1191 	    retval);
1192 
1193 	return (retval);
1194 }
1195 
1196 /*
1197  * sgen_uscsi_cmd()
1198  * 	Setup, configuration and teardown for a uscsi(7I) command
1199  */
1200 /*ARGSUSED*/
1201 static int
sgen_uscsi_cmd(dev_t dev,struct uscsi_cmd * ucmd,int flag)1202 sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
1203 {
1204 	struct uscsi_cmd	*uscmd;
1205 	struct buf	*bp;
1206 	sgen_state_t	*sg_state;
1207 	enum uio_seg	uioseg;
1208 	int	instance;
1209 	int	flags;
1210 	int	err;
1211 
1212 	instance = getminor(dev);
1213 
1214 	sg_state = ddi_get_soft_state(sgen_soft_state, instance);
1215 	ASSERT(sg_state);
1216 
1217 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_uscsi_cmd(): instance = %d",
1218 	    instance);
1219 
1220 	/*
1221 	 * At this point, we start affecting state relevant to the target,
1222 	 * so access needs to be serialized.
1223 	 */
1224 	if (sgen_hold_cmdbuf(sg_state) != 0) {
1225 		sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: interrupted");
1226 		return (EINTR);
1227 	}
1228 
1229 	err = scsi_uscsi_alloc_and_copyin((intptr_t)ucmd, flag,
1230 	    &sg_state->sgen_scsiaddr, &uscmd);
1231 	if (err != 0) {
1232 		sgen_rele_cmdbuf(sg_state);
1233 		sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: "
1234 		    "scsi_uscsi_alloc_and_copyin failed\n");
1235 		return (err);
1236 	}
1237 
1238 	/*
1239 	 * Clear out undesirable command flags
1240 	 */
1241 	flags = (uscmd->uscsi_flags & ~(USCSI_NOINTR | USCSI_NOPARITY |
1242 	    USCSI_OTAG | USCSI_HTAG | USCSI_HEAD));
1243 	if (flags != uscmd->uscsi_flags) {
1244 		sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: cleared "
1245 		    "unsafe uscsi_flags 0x%x", uscmd->uscsi_flags & ~flags);
1246 		uscmd->uscsi_flags = flags;
1247 	}
1248 
1249 	if (uscmd->uscsi_cdb != NULL) {
1250 		sgen_dump_cdb(sg_state, "sgen_uscsi_cmd: ",
1251 		    (union scsi_cdb *)uscmd->uscsi_cdb, uscmd->uscsi_cdblen);
1252 	}
1253 
1254 	/*
1255 	 * Stash the sense buffer into sgen_rqs_sen for convenience.
1256 	 */
1257 	sg_state->sgen_rqs_sen = uscmd->uscsi_rqbuf;
1258 
1259 	bp = sg_state->sgen_cmdbuf;
1260 	bp->av_back = NULL;
1261 	bp->av_forw = NULL;
1262 	bp->b_private = (struct buf *)uscmd;
1263 	uioseg = (flag & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
1264 
1265 	err = scsi_uscsi_handle_cmd(dev, uioseg, uscmd, sgen_start, bp, NULL);
1266 
1267 	if (sg_state->sgen_cmdpkt != NULL) {
1268 		uscmd->uscsi_status = SCBP_C(sg_state->sgen_cmdpkt);
1269 	} else {
1270 		uscmd->uscsi_status = 0;
1271 	}
1272 
1273 	sgen_log(sg_state, SGEN_DIAG3, "sgen_uscsi_cmd: awake from waiting "
1274 	    "for command.  Status is 0x%x", uscmd->uscsi_status);
1275 
1276 	if (uscmd->uscsi_rqbuf != NULL) {
1277 		int rqlen = uscmd->uscsi_rqlen - uscmd->uscsi_rqresid;
1278 		sgen_dump_sense(sg_state, rqlen,
1279 		    (uchar_t *)uscmd->uscsi_rqbuf);
1280 	}
1281 
1282 	(void) scsi_uscsi_copyout_and_free((intptr_t)ucmd, uscmd);
1283 
1284 	if (sg_state->sgen_cmdpkt != NULL) {
1285 		scsi_destroy_pkt(sg_state->sgen_cmdpkt);
1286 		sg_state->sgen_cmdpkt = NULL;
1287 	}
1288 
1289 	/*
1290 	 * After this point, we can't touch per-target state.
1291 	 */
1292 	sgen_rele_cmdbuf(sg_state);
1293 
1294 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_uscsi_cmd()");
1295 
1296 	return (err);
1297 }
1298 
1299 /*
1300  * sgen_hold_cmdbuf()
1301  * 	Acquire a lock on the command buffer for the given target.  Returns
1302  * 	non-zero if interrupted.
1303  */
1304 static int
sgen_hold_cmdbuf(sgen_state_t * sg_state)1305 sgen_hold_cmdbuf(sgen_state_t *sg_state)
1306 {
1307 	mutex_enter(&sg_state->sgen_mutex);
1308 	while (SGEN_IS_BUSY(sg_state)) {
1309 		if (!cv_wait_sig(&sg_state->sgen_cmdbuf_cv,
1310 		    &sg_state->sgen_mutex)) {
1311 			mutex_exit(&sg_state->sgen_mutex);
1312 			return (-1);
1313 		}
1314 	}
1315 	SGEN_SET_BUSY(sg_state);
1316 	mutex_exit(&sg_state->sgen_mutex);
1317 	return (0);
1318 }
1319 
1320 /*
1321  * sgen_rele_cmdbuf()
1322  * 	release the command buffer for a particular target.
1323  */
1324 static void
sgen_rele_cmdbuf(sgen_state_t * sg_state)1325 sgen_rele_cmdbuf(sgen_state_t *sg_state)
1326 {
1327 	mutex_enter(&sg_state->sgen_mutex);
1328 	SGEN_CLR_BUSY(sg_state);
1329 	cv_signal(&sg_state->sgen_cmdbuf_cv);
1330 	mutex_exit(&sg_state->sgen_mutex);
1331 }
1332 
1333 /*
1334  * sgen_start()
1335  * 	Transport a uscsi command; this is invoked by physio() or directly
1336  * 	by sgen_uscsi_cmd().
1337  */
1338 static int
sgen_start(struct buf * bp)1339 sgen_start(struct buf *bp)
1340 {
1341 	sgen_state_t *sg_state;
1342 	dev_t dev = bp->b_edev;
1343 	int trans_err;
1344 
1345 	if ((sg_state = ddi_get_soft_state(sgen_soft_state,
1346 	    getminor(dev))) == NULL) {
1347 		bp->b_resid = bp->b_bcount;
1348 		bioerror(bp, ENXIO);
1349 		biodone(bp);
1350 		return (ENXIO);
1351 	}
1352 
1353 	/*
1354 	 * Sanity checks - command should not be complete, no packet should
1355 	 * be allocated, and there ought to be a uscsi cmd in b_private
1356 	 */
1357 	ASSERT(bp == sg_state->sgen_cmdbuf && sg_state->sgen_cmdpkt == NULL);
1358 	ASSERT((bp->b_flags & B_DONE) == 0);
1359 	ASSERT(bp->b_private);
1360 	if (sgen_make_uscsi_cmd(sg_state, bp) != 0) {
1361 		bp->b_resid = bp->b_bcount;
1362 		bioerror(bp, EFAULT);
1363 		biodone(bp);
1364 		return (EFAULT);
1365 	}
1366 
1367 	ASSERT(sg_state->sgen_cmdpkt != NULL);
1368 
1369 	/*
1370 	 * Clear out the residual and error fields
1371 	 */
1372 	bp->b_resid = 0;
1373 	bp->b_error = 0;
1374 
1375 	trans_err = sgen_scsi_transport(sg_state->sgen_cmdpkt);
1376 	switch (trans_err) {
1377 	case TRAN_ACCEPT:
1378 		break;
1379 	case TRAN_BUSY:
1380 		sgen_log(sg_state, SGEN_DIAG2,
1381 		    "sgen_start: scsi_transport() returned TRAN_BUSY");
1382 		sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1383 		    SGEN_BSY_TIMEOUT);
1384 		break;
1385 	default:
1386 		/*
1387 		 * Indicate there has been an I/O transfer error.
1388 		 * Be done with the command.
1389 		 */
1390 		mutex_enter(&sg_state->sgen_mutex);
1391 		SGEN_DO_ERRSTATS(sg_state, sgen_trans_err);
1392 		mutex_exit(&sg_state->sgen_mutex);
1393 		sgen_log(sg_state, SGEN_DIAG2, "sgen_start: scsi_transport() "
1394 		    "returned %d", trans_err);
1395 		bioerror(bp, EIO);
1396 		biodone(bp);
1397 		return (EIO);
1398 	}
1399 	sgen_log(sg_state, SGEN_DIAG2, "sgen_start: b_flags 0x%x", bp->b_flags);
1400 	return (0);
1401 }
1402 
1403 /*
1404  * sgen_scsi_transport()
1405  * 	a simple scsi_transport() wrapper which can be configured to inject
1406  * 	sporadic errors for testing.
1407  */
1408 static int
sgen_scsi_transport(struct scsi_pkt * pkt)1409 sgen_scsi_transport(struct scsi_pkt *pkt)
1410 {
1411 	int trans_err;
1412 	static int cnt = 0;
1413 	sgen_state_t *sg_state = pkt->pkt_private;
1414 
1415 	if (sgen_sporadic_failures == 0) {
1416 		return (scsi_transport(pkt));
1417 	}
1418 
1419 	cnt = (cnt * 2416 + 374441) % 1771875;	/* borrowed from kmem.c */
1420 	if (cnt % 40 == 1) {
1421 		sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1422 		    "injecting sporadic BUSY");
1423 		trans_err = TRAN_BUSY;
1424 	} else if (cnt % 40 == 2) {
1425 		sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1426 		    "injecting sporadic BADPKT");
1427 		trans_err = TRAN_BADPKT;
1428 	} else {
1429 		/*
1430 		 * Most of the time we take the normal path
1431 		 */
1432 		trans_err = scsi_transport(pkt);
1433 	}
1434 	return (trans_err);
1435 }
1436 
1437 /*
1438  * sgen_make_uscsi_cmd()
1439  * 	Initialize a SCSI packet usable for USCSI.
1440  */
1441 static int
sgen_make_uscsi_cmd(sgen_state_t * sg_state,struct buf * bp)1442 sgen_make_uscsi_cmd(sgen_state_t *sg_state, struct buf *bp)
1443 {
1444 	struct scsi_pkt	*pkt;
1445 	struct uscsi_cmd *ucmd;
1446 	int stat_size = 1;
1447 	int flags = 0;
1448 
1449 	ASSERT(bp);
1450 
1451 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_make_uscsi_cmd()");
1452 
1453 	ucmd = (struct uscsi_cmd *)bp->b_private;
1454 
1455 	if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1456 		if (ucmd->uscsi_rqlen > SENSE_LENGTH) {
1457 			stat_size = (int)(ucmd->uscsi_rqlen) +
1458 			    sizeof (struct scsi_arq_status) -
1459 			    sizeof (struct scsi_extended_sense);
1460 			flags = PKT_XARQ;
1461 		} else {
1462 			stat_size = sizeof (struct scsi_arq_status);
1463 		}
1464 	}
1465 
1466 	sgen_log(sg_state, SGEN_DIAG3, "sgen_make_uscsi_cmd: b_bcount = %ld",
1467 	    bp->b_bcount);
1468 	pkt = scsi_init_pkt(&sg_state->sgen_scsiaddr,
1469 	    NULL,			/* in_pkt - null so it'll be alloc'd */
1470 	    bp->b_bcount ? bp : NULL,	/* buf structure for data xfer */
1471 	    ucmd->uscsi_cdblen,		/* cmdlen */
1472 	    stat_size,			/* statuslen */
1473 	    0,				/* privatelen */
1474 	    flags,			/* flags */
1475 	    SLEEP_FUNC,			/* callback */
1476 	    (caddr_t)sg_state);		/* callback_arg */
1477 
1478 	if (pkt == NULL) {
1479 		sgen_log(sg_state, SGEN_DIAG2, "failed sgen_make_uscsi_cmd()");
1480 		return (-1);
1481 	}
1482 
1483 	pkt->pkt_comp = sgen_callback;
1484 	pkt->pkt_private = sg_state;
1485 	sg_state->sgen_cmdpkt = pkt;
1486 
1487 	/*
1488 	 * We *don't* call scsi_setup_cdb here, as is customary, since the
1489 	 * user could specify a command from one group, but pass cdblen
1490 	 * as something totally different.  If cdblen is smaller than expected,
1491 	 * this results in scsi_setup_cdb writing past the end of the cdb.
1492 	 */
1493 	bcopy(ucmd->uscsi_cdb, pkt->pkt_cdbp, ucmd->uscsi_cdblen);
1494 	if (ucmd->uscsi_cdblen >= CDB_GROUP0) {
1495 		FILL_SCSI1_LUN(sg_state->sgen_scsidev, pkt);
1496 	}
1497 
1498 	if (ucmd->uscsi_timeout > 0)
1499 		pkt->pkt_time = ucmd->uscsi_timeout;
1500 	else
1501 		pkt->pkt_time = SGEN_IO_TIME;
1502 
1503 	/*
1504 	 * Set packet options
1505 	 */
1506 	if (ucmd->uscsi_flags & USCSI_SILENT)
1507 		pkt->pkt_flags |= FLAG_SILENT;
1508 	if (ucmd->uscsi_flags & USCSI_ISOLATE)
1509 		pkt->pkt_flags |= FLAG_ISOLATE;
1510 	if (ucmd->uscsi_flags & USCSI_DIAGNOSE)
1511 		pkt->pkt_flags |= FLAG_DIAGNOSE;
1512 	if (ucmd->uscsi_flags & USCSI_RENEGOT) {
1513 		pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
1514 	}
1515 
1516 	/* Transfer uscsi information to scsi_pkt */
1517 	(void) scsi_uscsi_pktinit(ucmd, pkt);
1518 
1519 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_make_uscsi_cmd()");
1520 	return (0);
1521 }
1522 
1523 
1524 /*
1525  * sgen_restart()
1526  * 	sgen_restart() is called after a timeout, when a command has been
1527  * 	postponed due to a TRAN_BUSY response from the HBA.
1528  */
1529 static void
sgen_restart(void * arg)1530 sgen_restart(void *arg)
1531 {
1532 	sgen_state_t *sg_state = (sgen_state_t *)arg;
1533 	struct scsi_pkt *pkt;
1534 	struct buf *bp;
1535 
1536 	sgen_log(sg_state, SGEN_DIAG2, "in sgen_restart()");
1537 
1538 	bp = sg_state->sgen_cmdbuf;
1539 	pkt = sg_state->sgen_cmdpkt;
1540 	ASSERT(bp && pkt);
1541 
1542 	SGEN_DO_ERRSTATS(sg_state, sgen_restart);
1543 
1544 	/*
1545 	 * If the packet is marked with the sensing flag, sgen is off running
1546 	 * a request sense, and *that packet* is what needs to be restarted.
1547 	 */
1548 	if (pkt->pkt_flags & FLAG_SENSING) {
1549 		sgen_log(sg_state, SGEN_DIAG3,
1550 		    "sgen_restart: restarting REQUEST SENSE");
1551 		pkt = sg_state->sgen_rqspkt;
1552 	}
1553 
1554 	if (sgen_scsi_transport(pkt) != TRAN_ACCEPT) {
1555 		bp->b_resid = bp->b_bcount;
1556 		bioerror(bp, EIO);
1557 		biodone(bp);
1558 	}
1559 }
1560 
1561 /*
1562  * sgen_callback()
1563  * 	Command completion processing
1564  *
1565  * 	sgen's completion processing is very pessimistic-- it does not retry
1566  * 	failed commands; instead, it allows the user application to make
1567  * 	decisions about what has gone wrong.
1568  */
1569 static void
sgen_callback(struct scsi_pkt * pkt)1570 sgen_callback(struct scsi_pkt *pkt)
1571 {
1572 	sgen_state_t *sg_state;
1573 	struct uscsi_cmd *ucmd;
1574 	struct buf *bp;
1575 	int action;
1576 
1577 	sg_state = pkt->pkt_private;
1578 	/*
1579 	 * bp should always be the command buffer regardless of whether
1580 	 * this is a command completion or a request-sense completion.
1581 	 * This is because there is no need to biodone() the sense buf
1582 	 * when it completes-- we want to biodone() the actual command buffer!
1583 	 */
1584 	bp = sg_state->sgen_cmdbuf;
1585 	if (pkt->pkt_flags & FLAG_SENSING) {
1586 		ASSERT(pkt == sg_state->sgen_rqspkt);
1587 		sgen_log(sg_state, SGEN_DIAG2,
1588 		    "in sgen_callback() (SENSE completion callback)");
1589 	} else {
1590 		ASSERT(pkt == sg_state->sgen_cmdpkt);
1591 		sgen_log(sg_state, SGEN_DIAG2,
1592 		    "in sgen_callback() (command completion callback)");
1593 	}
1594 	ucmd = (struct uscsi_cmd *)bp->b_private;
1595 
1596 	sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: reason=0x%x resid=%ld "
1597 	    "state=0x%x", pkt->pkt_reason, pkt->pkt_resid, pkt->pkt_state);
1598 
1599 	/* Transfer scsi_pkt information to uscsi */
1600 	(void) scsi_uscsi_pktfini(pkt, ucmd);
1601 
1602 	if (pkt->pkt_reason != CMD_CMPLT) {
1603 		/*
1604 		 * The command did not complete.
1605 		 */
1606 		sgen_log(sg_state, SGEN_DIAG3,
1607 		    "sgen_callback: command did not complete");
1608 		action = sgen_handle_incomplete(sg_state, pkt);
1609 	} else if (sg_state->sgen_arq_enabled &&
1610 	    (pkt->pkt_state & STATE_ARQ_DONE)) {
1611 		/*
1612 		 * The auto-rqsense happened, and the packet has a filled-in
1613 		 * scsi_arq_status structure, pointed to by pkt_scbp.
1614 		 */
1615 		sgen_log(sg_state, SGEN_DIAG3,
1616 		    "sgen_callback: received auto-requested sense");
1617 		action = sgen_handle_autosense(sg_state, pkt);
1618 		ASSERT(action != FETCH_SENSE);
1619 	} else if (pkt->pkt_flags & FLAG_SENSING) {
1620 		/*
1621 		 * sgen was running a REQUEST SENSE. Decode the sense data and
1622 		 * decide what to do next.
1623 		 *
1624 		 * Clear FLAG_SENSING on the original packet for completeness.
1625 		 */
1626 		sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: received sense");
1627 		sg_state->sgen_cmdpkt->pkt_flags &= ~FLAG_SENSING;
1628 		action = sgen_handle_sense(sg_state);
1629 		ASSERT(action != FETCH_SENSE);
1630 	} else {
1631 		/*
1632 		 * Command completed and we're not getting sense. Check for
1633 		 * errors and decide what to do next.
1634 		 */
1635 		sgen_log(sg_state, SGEN_DIAG3,
1636 		    "sgen_callback: command appears complete");
1637 		action = sgen_check_error(sg_state, bp);
1638 	}
1639 
1640 	switch (action) {
1641 	case FETCH_SENSE:
1642 		/*
1643 		 * If there is sense to fetch, break out to prevent biodone'ing
1644 		 * until the sense fetch is complete.
1645 		 */
1646 		if (sgen_initiate_sense(sg_state,
1647 		    scsi_pkt_allocated_correctly(pkt) ?
1648 		    pkt->pkt_path_instance : 0) == 0)
1649 			break;
1650 		/*FALLTHROUGH*/
1651 	case COMMAND_DONE_ERROR:
1652 		bp->b_resid = bp->b_bcount;
1653 		bioerror(bp, EIO);
1654 		/*FALLTHROUGH*/
1655 	case COMMAND_DONE:
1656 		biodone(bp);
1657 		break;
1658 	default:
1659 		ASSERT(0);
1660 		break;
1661 	}
1662 
1663 	sgen_log(sg_state, SGEN_DIAG2, "done sgen_callback()");
1664 }
1665 
1666 /*
1667  * sgen_initiate_sense()
1668  *	Send the sgen_rqspkt to the target, thereby requesting sense data.
1669  */
1670 static int
sgen_initiate_sense(sgen_state_t * sg_state,int path_instance)1671 sgen_initiate_sense(sgen_state_t *sg_state, int path_instance)
1672 {
1673 	/* use same path_instance as command */
1674 	if (scsi_pkt_allocated_correctly(sg_state->sgen_rqspkt))
1675 		sg_state->sgen_rqspkt->pkt_path_instance = path_instance;
1676 
1677 	switch (sgen_scsi_transport(sg_state->sgen_rqspkt)) {
1678 	case TRAN_ACCEPT:
1679 		sgen_log(sg_state, SGEN_DIAG3, "sgen_initiate_sense: "
1680 		    "sense fetch transport accepted.");
1681 		return (0);
1682 	case TRAN_BUSY:
1683 		sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1684 		    "sense fetch transport busy, setting timeout.");
1685 		sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1686 		    SGEN_BSY_TIMEOUT);
1687 		return (0);
1688 	default:
1689 		sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1690 		    "sense fetch transport failed or busy.");
1691 		return (-1);
1692 	}
1693 }
1694 
1695 /*
1696  * sgen_handle_incomplete()
1697  * 	sgen is pessimistic, but also careful-- it doesn't try to retry
1698  * 	incomplete commands, but it also doesn't go resetting devices;
1699  * 	it is hard to tell if the device will be tolerant of that sort
1700  * 	of prodding.
1701  *
1702  * 	This routine has been left as a guide for the future--- the
1703  * 	current administration's hands-off policy may need modification.
1704  */
1705 /*ARGSUSED*/
1706 static int
sgen_handle_incomplete(sgen_state_t * sg_state,struct scsi_pkt * pkt)1707 sgen_handle_incomplete(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1708 {
1709 	SGEN_DO_ERRSTATS(sg_state, sgen_incmp_err);
1710 	return (COMMAND_DONE_ERROR);
1711 }
1712 
1713 /*
1714  * sgen_handle_autosense()
1715  * 	Deal with SENSE data acquired automatically via the auto-request-sense
1716  * 	facility.
1717  *
1718  * 	Sgen takes a pessimistic view of things-- it doesn't retry commands,
1719  * 	and unless the device recovered from the problem, this routine returns
1720  * 	COMMAND_DONE_ERROR.
1721  */
1722 static int
sgen_handle_autosense(sgen_state_t * sg_state,struct scsi_pkt * pkt)1723 sgen_handle_autosense(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1724 {
1725 	struct scsi_arq_status *arqstat;
1726 	struct uscsi_cmd *ucmd =
1727 	    (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1728 	int amt;
1729 
1730 	arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp);
1731 
1732 	SGEN_DO_ERRSTATS(sg_state, sgen_autosen_rcv);
1733 
1734 	if (arqstat->sts_rqpkt_reason != CMD_CMPLT) {
1735 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: ARQ"
1736 		    "failed to complete.");
1737 		SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1738 		return (COMMAND_DONE_ERROR);
1739 	}
1740 
1741 	if (pkt->pkt_state & STATE_XARQ_DONE) {
1742 		amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1743 	} else {
1744 		if (arqstat->sts_rqpkt_resid > SENSE_LENGTH) {
1745 			amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1746 		} else {
1747 			amt = SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1748 		}
1749 	}
1750 
1751 	if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1752 		ucmd->uscsi_rqstatus = *((char *)&arqstat->sts_rqpkt_status);
1753 		uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1754 		ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1755 		ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1756 		bcopy(&(arqstat->sts_sensedata), sg_state->sgen_rqs_sen, rqlen);
1757 		sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_autosense: "
1758 		    "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1759 		    ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1760 	}
1761 
1762 	if (arqstat->sts_rqpkt_status.sts_chk) {
1763 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1764 		    "check condition on auto request sense!");
1765 		SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1766 		return (COMMAND_DONE_ERROR);
1767 	}
1768 
1769 	if (((arqstat->sts_rqpkt_state & STATE_XFERRED_DATA) == 0) ||
1770 	    (amt == 0)) {
1771 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1772 		    "auto-sense, but it contains no data!");
1773 		SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1774 		return (COMMAND_DONE_ERROR);
1775 	}
1776 
1777 	/*
1778 	 * Stuff the sense data pointer into sgen_sense for later retrieval
1779 	 */
1780 	sg_state->sgen_sense = &arqstat->sts_sensedata;
1781 
1782 	/*
1783 	 * Now, check to see whether we got enough sense data to make any
1784 	 * sense out if it (heh-heh).
1785 	 */
1786 	if (amt < SUN_MIN_SENSE_LENGTH) {
1787 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: not "
1788 		    "enough auto sense data");
1789 		return (COMMAND_DONE_ERROR);
1790 	}
1791 
1792 	switch (arqstat->sts_sensedata.es_key) {
1793 	case KEY_RECOVERABLE_ERROR:
1794 		SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1795 		break;
1796 	case KEY_NO_SENSE:
1797 		SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1798 		break;
1799 	default:
1800 		SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1801 		break;
1802 	}
1803 
1804 	return (COMMAND_DONE);
1805 }
1806 
1807 /*
1808  * sgen_handle_sense()
1809  * 	Examine sense data that was manually fetched from the target.
1810  */
1811 static int
sgen_handle_sense(sgen_state_t * sg_state)1812 sgen_handle_sense(sgen_state_t *sg_state)
1813 {
1814 	struct scsi_pkt *rqpkt = sg_state->sgen_rqspkt;
1815 	struct scsi_status *rqstatus = (struct scsi_status *)rqpkt->pkt_scbp;
1816 	struct uscsi_cmd *ucmd =
1817 	    (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1818 	int amt;
1819 
1820 	SGEN_DO_ERRSTATS(sg_state, sgen_sense_rcv);
1821 
1822 	amt = MAX_SENSE_LENGTH - rqpkt->pkt_resid;
1823 
1824 	if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1825 		ucmd->uscsi_rqstatus = *((char *)rqstatus);
1826 		uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1827 		ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1828 		ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1829 		bcopy(sg_state->sgen_sense, sg_state->sgen_rqs_sen, rqlen);
1830 		sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_sense: "
1831 		    "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1832 		    ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1833 	}
1834 
1835 	if (rqstatus->sts_busy) {
1836 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got busy "
1837 		    "on request sense");
1838 		SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1839 		return (COMMAND_DONE_ERROR);
1840 	}
1841 
1842 	if (rqstatus->sts_chk) {
1843 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got check "
1844 		    "condition on request sense!");
1845 		SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1846 		return (COMMAND_DONE_ERROR);
1847 	}
1848 
1849 	if ((rqpkt->pkt_state & STATE_XFERRED_DATA) == 0 || amt == 0) {
1850 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got "
1851 		    "sense, but it contains no data");
1852 		SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1853 		return (COMMAND_DONE_ERROR);
1854 	}
1855 
1856 	/*
1857 	 * Now, check to see whether we got enough sense data to make any
1858 	 * sense out if it (heh-heh).
1859 	 */
1860 	if (amt < SUN_MIN_SENSE_LENGTH) {
1861 		sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: not "
1862 		    "enough sense data");
1863 		SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1864 		return (COMMAND_DONE_ERROR);
1865 	}
1866 
1867 	/*
1868 	 * Decode the sense data-- this was deposited here for us by the
1869 	 * setup in sgen_do_attach(). (note that sgen_sense is an alias for
1870 	 * the sd_sense field in the scsi_device).
1871 	 */
1872 	sgen_log(sg_state, SGEN_DIAG1, "Sense key is %s [0x%x]",
1873 	    scsi_sname(sg_state->sgen_sense->es_key),
1874 	    sg_state->sgen_sense->es_key);
1875 	switch (sg_state->sgen_sense->es_key) {
1876 	case KEY_RECOVERABLE_ERROR:
1877 		SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1878 		break;
1879 	case KEY_NO_SENSE:
1880 		SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1881 		break;
1882 	default:
1883 		SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1884 		break;
1885 	}
1886 
1887 	return (COMMAND_DONE);
1888 }
1889 
1890 /*
1891  * sgen_check_error()
1892  * 	examine the command packet for abnormal completion.
1893  *
1894  *	sgen_check_error should only be called at the completion of the
1895  *	command packet.
1896  */
1897 static int
sgen_check_error(sgen_state_t * sg_state,struct buf * bp)1898 sgen_check_error(sgen_state_t *sg_state, struct buf *bp)
1899 {
1900 	struct scsi_pkt *pkt = sg_state->sgen_cmdpkt;
1901 	struct scsi_status *status = (struct scsi_status *)pkt->pkt_scbp;
1902 	struct uscsi_cmd *ucmd =
1903 	    (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1904 
1905 	if (status->sts_busy) {
1906 		sgen_log(sg_state, SGEN_DIAG1,
1907 		    "sgen_check_error: target is busy");
1908 		return (COMMAND_DONE_ERROR);
1909 	}
1910 
1911 	/*
1912 	 * pkt_resid will reflect, at this point, a residual of how many bytes
1913 	 * were not transferred; a non-zero pkt_resid is an error.
1914 	 */
1915 	if (pkt->pkt_resid) {
1916 		bp->b_resid += pkt->pkt_resid;
1917 	}
1918 
1919 	if (status->sts_chk) {
1920 		if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1921 			if (sg_state->sgen_arq_enabled) {
1922 				sgen_log(sg_state, SGEN_DIAG1,
1923 				    "sgen_check_error: strange: target "
1924 				    "indicates CHECK CONDITION with auto-sense "
1925 				    "enabled.");
1926 			}
1927 			sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1928 			    "target ready for sense fetch");
1929 			return (FETCH_SENSE);
1930 		} else {
1931 			sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1932 			    "target indicates CHECK CONDITION");
1933 		}
1934 	}
1935 
1936 	return (COMMAND_DONE);
1937 }
1938 
1939 /*
1940  * sgen_tur()
1941  * 	test if a target is ready to operate by sending it a TUR command.
1942  */
1943 static int
sgen_tur(dev_t dev)1944 sgen_tur(dev_t dev)
1945 {
1946 	char cmdblk[CDB_GROUP0];
1947 	struct uscsi_cmd scmd;
1948 
1949 	bzero(&scmd, sizeof (scmd));
1950 	scmd.uscsi_bufaddr = 0;
1951 	scmd.uscsi_buflen = 0;
1952 	bzero(cmdblk, CDB_GROUP0);
1953 	cmdblk[0] = (char)SCMD_TEST_UNIT_READY;
1954 	scmd.uscsi_flags = USCSI_DIAGNOSE | USCSI_SILENT | USCSI_WRITE;
1955 	scmd.uscsi_cdb = cmdblk;
1956 	scmd.uscsi_cdblen = CDB_GROUP0;
1957 
1958 	return (sgen_uscsi_cmd(dev, &scmd, FKIOCTL));
1959 }
1960 
1961 /*
1962  * sgen_diag_ok()
1963  * 	given an sg_state and a desired diagnostic level, return true if
1964  * 	it is acceptable to output a message.
1965  */
1966 /*ARGSUSED*/
1967 static int
sgen_diag_ok(sgen_state_t * sg_state,int level)1968 sgen_diag_ok(sgen_state_t *sg_state, int level)
1969 {
1970 	int diag_lvl;
1971 
1972 	switch (level) {
1973 	case CE_WARN:
1974 	case CE_NOTE:
1975 	case CE_CONT:
1976 	case CE_PANIC:
1977 		return (1);
1978 	case SGEN_DIAG1:
1979 	case SGEN_DIAG2:
1980 	case SGEN_DIAG3:
1981 		if (sg_state) {
1982 			/*
1983 			 * Check to see if user overrode the diagnostics level
1984 			 * for this instance (either via SGEN_IOC_DIAG or via
1985 			 * .conf file).  If not, fall back to the global diag
1986 			 * level.
1987 			 */
1988 			if (sg_state->sgen_diag != -1)
1989 				diag_lvl = sg_state->sgen_diag;
1990 			else
1991 				diag_lvl = sgen_diag;
1992 		} else {
1993 			diag_lvl = sgen_diag;
1994 		}
1995 		if (((diag_lvl << 8) | CE_CONT) >= level) {
1996 			return (1);
1997 		} else {
1998 			return (0);
1999 		}
2000 	default:
2001 		return (1);
2002 	}
2003 }
2004 
2005 /*PRINTFLIKE3*/
2006 static void
sgen_log(sgen_state_t * sg_state,int level,const char * fmt,...)2007 sgen_log(sgen_state_t *sg_state, int level, const char *fmt, ...)
2008 {
2009 	va_list	ap;
2010 	char buf[256];
2011 
2012 	if (!sgen_diag_ok(sg_state, level))
2013 		return;
2014 
2015 	va_start(ap, fmt);
2016 	(void) vsnprintf(buf, sizeof (buf), fmt, ap);
2017 	va_end(ap);
2018 
2019 	switch (level) {
2020 	case CE_NOTE:
2021 	case CE_CONT:
2022 	case CE_WARN:
2023 	case CE_PANIC:
2024 		if (sg_state == (sgen_state_t *)NULL) {
2025 			cmn_err(level, "%s", buf);
2026 		} else {
2027 			scsi_log(sg_state->sgen_devinfo, sgen_label, level,
2028 			    "%s", buf);
2029 		}
2030 		break;
2031 	case SGEN_DIAG1:
2032 	case SGEN_DIAG2:
2033 	case SGEN_DIAG3:
2034 	default:
2035 		if (sg_state == (sgen_state_t *)NULL) {
2036 			scsi_log(NULL, sgen_label, CE_CONT, "%s", buf);
2037 		} else {
2038 			scsi_log(sg_state->sgen_devinfo, sgen_label, CE_CONT,
2039 			    "%s", buf);
2040 		}
2041 	}
2042 }
2043 
2044 /*
2045  * sgen_dump_cdb()
2046  * 	dump out the contents of a cdb.  Take care that 'label' is not too
2047  * 	large, or 'buf' could overflow.
2048  */
2049 static void
sgen_dump_cdb(sgen_state_t * sg_state,const char * label,union scsi_cdb * cdb,int cdblen)2050 sgen_dump_cdb(sgen_state_t *sg_state, const char *label,
2051     union scsi_cdb *cdb, int cdblen)
2052 {
2053 	static char hex[] = "0123456789abcdef";
2054 	char *buf, *p;
2055 	size_t nbytes;
2056 	int i;
2057 	uchar_t	*cdbp = (uchar_t *)cdb;
2058 
2059 	/*
2060 	 * fastpath-- if we're not able to print out, don't do all of this
2061 	 * extra work.
2062 	 */
2063 	if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2064 		return;
2065 
2066 	/*
2067 	 * 3 characters for each byte (because of the ' '), plus the size of
2068 	 * the label, plus the trailing ']' and the null character.
2069 	 */
2070 	nbytes = 3 * cdblen + strlen(label) + strlen(" CDB = [") + 2;
2071 	buf = kmem_alloc(nbytes, KM_SLEEP);
2072 	(void) sprintf(buf, "%s CDB = [", label);
2073 	p = &buf[strlen(buf)];
2074 	for (i = 0; i < cdblen; i++, cdbp++) {
2075 		if (i > 0)
2076 			*p++ = ' ';
2077 		*p++ = hex[(*cdbp >> 4) & 0x0f];
2078 		*p++ = hex[*cdbp & 0x0f];
2079 	}
2080 	*p++ = ']';
2081 	*p = 0;
2082 	sgen_log(sg_state, SGEN_DIAG3, buf);
2083 	kmem_free(buf, nbytes);
2084 }
2085 
2086 static void
sgen_dump_sense(sgen_state_t * sg_state,size_t rqlen,uchar_t * rqbuf)2087 sgen_dump_sense(sgen_state_t *sg_state, size_t rqlen, uchar_t *rqbuf)
2088 {
2089 	static char hex[] = "0123456789abcdef";
2090 	char *buf, *p;
2091 	size_t nbytes;
2092 	int i;
2093 
2094 	/*
2095 	 * fastpath-- if we're not able to print out, don't do all of this
2096 	 * extra work.
2097 	 */
2098 	if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2099 		return;
2100 
2101 	/*
2102 	 * 3 characters for each byte (because of the ' '), plus the size of
2103 	 * the label, plus the trailing ']' and the null character.
2104 	 */
2105 	nbytes = 3 * rqlen + strlen(" SENSE = [") + 2;
2106 	buf = kmem_alloc(nbytes, KM_SLEEP);
2107 	(void) sprintf(buf, "SENSE = [");
2108 	p = &buf[strlen(buf)];
2109 	for (i = 0; i < rqlen; i++, rqbuf++) {
2110 		if (i > 0)
2111 			*p++ = ' ';
2112 		*p++ = hex[(*rqbuf >> 4) & 0x0f];
2113 		*p++ = hex[*rqbuf & 0x0f];
2114 	}
2115 	*p++ = ']';
2116 	*p = 0;
2117 	sgen_log(sg_state, SGEN_DIAG3, buf);
2118 	kmem_free(buf, nbytes);
2119 }
2120