xref: /illumos-gate/usr/src/uts/common/io/scsi/targets/ses.c (revision a99cb9618990662acbd3bab1b4a5b05a6ca62556)
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  * Enclosure Services Device target driver
23  *
24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
27  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
28  */
29 
30 #include <sys/modctl.h>
31 #include <sys/file.h>
32 #include <sys/scsi/scsi.h>
33 #include <sys/scsi/generic/status.h>
34 #include <sys/scsi/targets/sesio.h>
35 #include <sys/scsi/targets/ses.h>
36 
37 
38 
39 /*
40  * Power management defines (should be in a common include file?)
41  */
42 #define	PM_HARDWARE_STATE_PROP		"pm-hardware-state"
43 #define	PM_NEEDS_SUSPEND_RESUME		"needs-suspend-resume"
44 
45 
46 /*
47  * Global Driver Data
48  */
49 int ses_io_time = SES_IO_TIME;
50 
51 static int ses_retry_count = SES_RETRY_COUNT * SES_RETRY_MULTIPLIER;
52 
53 #ifdef	DEBUG
54 int ses_debug = 0;
55 #else	/* DEBUG */
56 #define	ses_debug	0
57 #endif	/* DEBUG */
58 
59 
60 /*
61  * External Enclosure Functions
62  */
63 extern int ses_softc_init(ses_softc_t *, int);
64 extern int ses_init_enc(ses_softc_t *);
65 extern int ses_get_encstat(ses_softc_t *, int);
66 extern int ses_set_encstat(ses_softc_t *, uchar_t, int);
67 extern int ses_get_objstat(ses_softc_t *, ses_objarg *, int);
68 extern int ses_set_objstat(ses_softc_t *, ses_objarg *, int);
69 
70 extern int safte_softc_init(ses_softc_t *, int);
71 extern int safte_init_enc(ses_softc_t *);
72 extern int safte_get_encstat(ses_softc_t *, int);
73 extern int safte_set_encstat(ses_softc_t *, uchar_t, int);
74 extern int safte_get_objstat(ses_softc_t *, ses_objarg *, int);
75 extern int safte_set_objstat(ses_softc_t *, ses_objarg *, int);
76 
77 extern int sen_softc_init(ses_softc_t *, int);
78 extern int sen_init_enc(ses_softc_t *);
79 extern int sen_get_encstat(ses_softc_t *, int);
80 extern int sen_set_encstat(ses_softc_t *, uchar_t, int);
81 extern int sen_get_objstat(ses_softc_t *, ses_objarg *, int);
82 extern int sen_set_objstat(ses_softc_t *, ses_objarg *, int);
83 
84 /*
85  * Local Function prototypes
86  */
87 static int ses_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
88 static int ses_probe(dev_info_t *);
89 static int ses_attach(dev_info_t *, ddi_attach_cmd_t);
90 static int ses_detach(dev_info_t *, ddi_detach_cmd_t);
91 
92 static int is_enc_dev(ses_softc_t *, struct scsi_inquiry *, int, enctyp *);
93 static int ses_doattach(dev_info_t *dip);
94 
95 static int  ses_open(dev_t *, int, int, cred_t *);
96 static int  ses_close(dev_t, int, int, cred_t *);
97 static int  ses_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
98 
99 static encvec vecs[3] = {
100 {
101 	ses_softc_init, ses_init_enc, ses_get_encstat,
102 	ses_set_encstat, ses_get_objstat, ses_set_objstat
103 },
104 {
105 	safte_softc_init, safte_init_enc, safte_get_encstat,
106 	safte_set_encstat, safte_get_objstat, safte_set_objstat,
107 },
108 {
109 	sen_softc_init, sen_init_enc, sen_get_encstat,
110 	sen_set_encstat, sen_get_objstat, sen_set_objstat
111 }
112 };
113 
114 
115 /*
116  * Local Functions
117  */
118 static int ses_start(struct buf *bp);
119 static int ses_decode_sense(struct scsi_pkt *pkt, int *err);
120 
121 static void ses_get_pkt(struct buf *bp, int (*func)(opaque_t));
122 static void ses_callback(struct scsi_pkt *pkt);
123 static void ses_restart(void *arg);
124 
125 
126 /*
127  * Local Static Data
128  */
129 #ifndef	D_HOTPLUG
130 #define	D_HOTPLUG	0
131 #endif /* D_HOTPLUG */
132 
133 static struct cb_ops ses_cb_ops = {
134 	ses_open,			/* open */
135 	ses_close,			/* close */
136 	nodev,				/* strategy */
137 	nodev,				/* print */
138 	nodev,				/* dump */
139 	nodev,				/* read */
140 	nodev,				/* write */
141 	ses_ioctl,			/* ioctl */
142 	nodev,				/* devmap */
143 	nodev,				/* mmap */
144 	nodev,				/* segmap */
145 	nochpoll,			/* poll */
146 	ddi_prop_op,			/* cb_prop_op */
147 	0,				/* streamtab  */
148 #if	!defined(CB_REV)
149 	D_MP | D_NEW | D_HOTPLUG	/* Driver compatibility flag */
150 #else	/* !defined(CB_REV) */
151 	D_MP | D_NEW | D_HOTPLUG,	/* Driver compatibility flag */
152 	CB_REV,				/* cb_ops version number */
153 	nodev,				/* aread */
154 	nodev				/* awrite */
155 #endif	/* !defined(CB_REV) */
156 };
157 
158 static struct dev_ops ses_dev_ops = {
159 	DEVO_REV,		/* devo_rev, */
160 	0,			/* refcnt  */
161 	ses_info,		/* info */
162 	nulldev,		/* identify */
163 	ses_probe,		/* probe */
164 	ses_attach,		/* attach */
165 	ses_detach,		/* detach */
166 	nodev,			/* reset */
167 	&ses_cb_ops,		/* driver operations */
168 	(struct bus_ops *)NULL,	/* bus operations */
169 	NULL,			/* power */
170 	ddi_quiesce_not_needed,		/* quiesce */
171 };
172 
173 static void *estate  = NULL;
174 static const char *Snm = "ses";
175 static const char *Str = "%s\n";
176 static const char *efl = "copyin/copyout EFAULT @ line %d";
177 static const char *fail_msg = "%stransport failed: reason '%s': %s";
178 
179 
180 
181 /*
182  * autoconfiguration routines.
183  */
184 
185 static struct modldrv modldrv = {
186 	&mod_driverops,
187 	"SCSI Enclosure Services",
188 	&ses_dev_ops
189 };
190 
191 static struct modlinkage modlinkage = {
192 	MODREV_1, &modldrv, NULL
193 };
194 
195 
196 int
197 _init(void)
198 {
199 	int status;
200 	status = ddi_soft_state_init(&estate, sizeof (ses_softc_t), 0);
201 	if (status == 0) {
202 		if ((status = mod_install(&modlinkage)) != 0) {
203 			ddi_soft_state_fini(&estate);
204 		}
205 	}
206 	return (status);
207 }
208 
209 int
210 _fini(void)
211 {
212 	int status;
213 	if ((status = mod_remove(&modlinkage)) != 0) {
214 		return (status);
215 	}
216 	ddi_soft_state_fini(&estate);
217 	return (status);
218 }
219 
220 int
221 _info(struct modinfo *modinfop)
222 {
223 	return (mod_info(&modlinkage, modinfop));
224 }
225 
226 static int
227 ses_probe(dev_info_t *dip)
228 {
229 	int			err;
230 	struct scsi_device	*devp;
231 	enctyp			ep;
232 
233 	/*
234 	 * I finally figured out why we return success
235 	 * on every probe. The devices that we attach to
236 	 * don't all report as being the same "device type"
237 	 *
238 	 * 1) A5x00 -- report as Enclosure Services (0xD) SES
239 	 * 2) A1000 -- report as Direct Access (0x0) SES
240 	 *    uses the same target as raid controler.
241 	 * 3) D1000 -- report as processor (0x3) SAFTE
242 	 * 3) D240  -- report as processor (0x3) SAFTE
243 	 *
244 	 * We also reportedly attach to SEN devices which I
245 	 * believe reside in a Tobasco tray.  I have never
246 	 * been able to get one to attach.
247 	 *
248 	 */
249 	if (dip == NULL)
250 		return (DDI_PROBE_FAILURE);
251 	/* SES_LOG(NULL, SES_CE_DEBUG1, "ses_probe: OK"); */
252 	if (ddi_dev_is_sid(dip) == DDI_SUCCESS) {
253 		return (DDI_PROBE_DONTCARE);
254 	}
255 
256 	devp = ddi_get_driver_private(dip);
257 
258 	/* Legacy: prevent driver.conf specified ses nodes on atapi. */
259 	if (scsi_ifgetcap(&devp->sd_address, "interconnect-type", -1) ==
260 	    INTERCONNECT_ATAPI)
261 		return (DDI_PROBE_FAILURE);
262 
263 	/*
264 	 * XXX: Breakage from the x86 folks.
265 	 */
266 	if (strcmp(ddi_get_name(ddi_get_parent(dip)), "ata") == 0) {
267 		return (DDI_PROBE_FAILURE);
268 	}
269 
270 	switch (err = scsi_probe(devp, SLEEP_FUNC)) {
271 	case SCSIPROBE_EXISTS:
272 		if (is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &ep)) {
273 			break;
274 		}
275 		/* FALLTHROUGH */
276 	case SCSIPROBE_NORESP:
277 		scsi_unprobe(devp);
278 		return (DDI_PROBE_FAILURE);
279 	default:
280 		SES_LOG(NULL, SES_CE_DEBUG9,
281 		    "ses_probe: probe error %d", err);
282 		scsi_unprobe(devp);
283 		return (DDI_PROBE_FAILURE);
284 	}
285 	scsi_unprobe(devp);
286 	return (DDI_PROBE_SUCCESS);
287 }
288 
289 static int
290 ses_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
291 {
292 	int inst, err;
293 	ses_softc_t *ssc;
294 
295 	inst = ddi_get_instance(dip);
296 	switch (cmd) {
297 	case DDI_ATTACH:
298 		SES_LOG(NULL, SES_CE_DEBUG9, "ses_attach: DDI_ATTACH ses%d",
299 		    inst);
300 
301 		err = ses_doattach(dip);
302 
303 		if (err == DDI_FAILURE) {
304 			return (DDI_FAILURE);
305 		}
306 		SES_LOG(NULL, SES_CE_DEBUG4,
307 		    "ses_attach: DDI_ATTACH OK ses%d", inst);
308 		break;
309 
310 	case DDI_RESUME:
311 		if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
312 			return (DDI_FAILURE);
313 		}
314 		SES_LOG(ssc, SES_CE_DEBUG1, "ses_attach: DDI_ATTACH ses%d",
315 		    inst);
316 		ssc->ses_suspended = 0;
317 		break;
318 
319 	default:
320 		return (DDI_FAILURE);
321 	}
322 	return (DDI_SUCCESS);
323 }
324 
325 static int
326 is_enc_dev(ses_softc_t *ssc, struct scsi_inquiry *inqp, int iqlen, enctyp *ep)
327 {
328 	uchar_t dt = (inqp->inq_dtype & DTYPE_MASK);
329 	uchar_t *iqd = (uchar_t *)inqp;
330 
331 	if (dt == DTYPE_ESI) {
332 		if (strncmp(inqp->inq_vid, SEN_ID, SEN_ID_LEN) == 0) {
333 			SES_LOG(ssc, SES_CE_DEBUG3, "SEN device found");
334 			*ep = SEN_TYPE;
335 		} else if (inqp->inq_rdf == RDF_SCSI2) {
336 			/*
337 			 * Per SPC4 #6.4.2 Standard Inquiry Data, response
338 			 * data format (RDF) values of 0 and 1 are Obsolete,
339 			 * whereas values greater than 2 are Reserved
340 			 */
341 			SES_LOG(ssc, SES_CE_DEBUG3, "SES device found");
342 			*ep = SES_TYPE;
343 		} else {
344 			SES_LOG(ssc, SES_CE_DEBUG3, "Pre-SCSI3 SES device");
345 			*ep = SES_TYPE;
346 		}
347 		return (1);
348 	}
349 	if ((iqd[6] & 0x40) && inqp->inq_rdf >= RDF_SCSI2) {
350 		/*
351 		 * PassThrough Device.
352 		 */
353 		*ep = SES_TYPE;
354 		SES_LOG(ssc, SES_CE_DEBUG3, "Passthru SES device");
355 		return (1);
356 	}
357 
358 	if (iqlen < 47) {
359 		SES_LOG(ssc, CE_NOTE,
360 		    "INQUIRY data too short to determine SAF-TE");
361 		return (0);
362 	}
363 	if (strncmp((char *)&iqd[44], "SAF-TE", 4) == 0) {
364 		*ep = SAFT_TYPE;
365 		SES_LOG(ssc, SES_CE_DEBUG3, "SAF-TE device found");
366 		return (1);
367 	}
368 	return (0);
369 }
370 
371 
372 /*
373  * Attach ses device.
374  *
375  * XXX:  Power management is NOT supported.  A token framework
376  *       is provided that will need to be extended assuming we have
377  *       ses devices we can power down.  Currently, we don't have any.
378  */
379 static int
380 ses_doattach(dev_info_t *dip)
381 {
382 	int inst, err;
383 	Scsidevp devp;
384 	ses_softc_t *ssc;
385 	enctyp etyp;
386 
387 	inst = ddi_get_instance(dip);
388 	/*
389 	 * Workaround for bug #4154979- for some reason we can
390 	 * be called with identical instance numbers but for
391 	 * different dev_info_t-s- all but one are bogus.
392 	 *
393 	 * Bad Dog! No Biscuit!
394 	 *
395 	 * A quick workaround might be to call ddi_soft_state_zalloc
396 	 * unconditionally, as the implementation fails these calls
397 	 * if there's an item already allocated. A more reasonable
398 	 * and longer term change is to move the allocation past
399 	 * the probe for the device's existence as most of these
400 	 * 'bogus' calls are for nonexistent devices.
401 	 */
402 
403 	devp  = ddi_get_driver_private(dip);
404 	devp->sd_dev = dip;
405 
406 	/*
407 	 * Determine whether the { i, t, l } we're called
408 	 * to start is an enclosure services device.
409 	 */
410 
411 	/*
412 	 * Call the scsi_probe routine to see whether
413 	 * we actually have an Enclosure Services device at
414 	 * this address.
415 	 */
416 	err = scsi_probe(devp, SLEEP_FUNC);
417 	if (err != SCSIPROBE_EXISTS) {
418 		SES_LOG(NULL, SES_CE_DEBUG9,
419 		    "ses_doattach: probe error %d", err);
420 		scsi_unprobe(devp);
421 		return (DDI_FAILURE);
422 	}
423 	/* Call is_enc_dev() to get the etyp */
424 	if (!(is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &etyp))) {
425 		SES_LOG(NULL, CE_WARN,
426 		    "ses_doattach: ses%d: is_enc_dev failure", inst);
427 		scsi_unprobe(devp);
428 		return (DDI_FAILURE);
429 	}
430 
431 	if (ddi_soft_state_zalloc(estate, inst) != DDI_SUCCESS) {
432 		scsi_unprobe(devp);
433 		SES_LOG(NULL, CE_NOTE, "ses%d: softalloc fails", inst);
434 		return (DDI_FAILURE);
435 	}
436 	ssc = ddi_get_soft_state(estate, inst);
437 	if (ssc == NULL) {
438 		scsi_unprobe(devp);
439 		SES_LOG(NULL, CE_NOTE, "ses%d: get_soft_state fails", inst);
440 		return (DDI_FAILURE);
441 	}
442 	devp->sd_private = (opaque_t)ssc;
443 	ssc->ses_devp = devp;
444 	err = ddi_create_minor_node(dip, "0", S_IFCHR, inst,
445 	    DDI_NT_SCSI_ENCLOSURE, 0);
446 	if (err == DDI_FAILURE) {
447 		ddi_remove_minor_node(dip, NULL);
448 		SES_LOG(ssc, CE_NOTE, "minor node creation failed");
449 		ddi_soft_state_free(estate, inst);
450 		scsi_unprobe(devp);
451 		return (DDI_FAILURE);
452 	}
453 
454 	ssc->ses_type = etyp;
455 	ssc->ses_vec = vecs[etyp];
456 
457 	/* Call SoftC Init Routine A bit later... */
458 
459 	ssc->ses_rqbp = scsi_alloc_consistent_buf(SES_ROUTE(ssc),
460 	    NULL, MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL);
461 	if (ssc->ses_rqbp != NULL) {
462 		ssc->ses_rqpkt = scsi_init_pkt(SES_ROUTE(ssc), NULL,
463 		    ssc->ses_rqbp, CDB_GROUP0, 1, 0, PKT_CONSISTENT,
464 		    SLEEP_FUNC, NULL);
465 	}
466 	if (ssc->ses_rqbp == NULL || ssc->ses_rqpkt == NULL) {
467 		ddi_remove_minor_node(dip, NULL);
468 		SES_LOG(ssc, CE_NOTE, "scsi_init_pkt of rqbuf failed");
469 		if (ssc->ses_rqbp != NULL) {
470 			scsi_free_consistent_buf(ssc->ses_rqbp);
471 			ssc->ses_rqbp = NULL;
472 		}
473 		ddi_soft_state_free(estate, inst);
474 		scsi_unprobe(devp);
475 		return (DDI_FAILURE);
476 	}
477 	ssc->ses_rqpkt->pkt_private = (opaque_t)ssc;
478 	ssc->ses_rqpkt->pkt_address = *(SES_ROUTE(ssc));
479 	ssc->ses_rqpkt->pkt_comp = ses_callback;
480 	ssc->ses_rqpkt->pkt_time = ses_io_time;
481 	ssc->ses_rqpkt->pkt_flags = FLAG_NOPARITY|FLAG_NODISCON|FLAG_SENSING;
482 	ssc->ses_rqpkt->pkt_cdbp[0] = SCMD_REQUEST_SENSE;
483 	ssc->ses_rqpkt->pkt_cdbp[1] = 0;
484 	ssc->ses_rqpkt->pkt_cdbp[2] = 0;
485 	ssc->ses_rqpkt->pkt_cdbp[3] = 0;
486 	ssc->ses_rqpkt->pkt_cdbp[4] = MAX_SENSE_LENGTH;
487 	ssc->ses_rqpkt->pkt_cdbp[5] = 0;
488 
489 	switch (scsi_ifgetcap(SES_ROUTE(ssc), "auto-rqsense", 1)) {
490 	case 1:
491 		/* if already set, don't reset it */
492 		ssc->ses_arq = 1;
493 		break;
494 	case 0:
495 		/* try and set it */
496 		ssc->ses_arq = ((scsi_ifsetcap(SES_ROUTE(ssc),
497 		    "auto-rqsense", 1, 1) == 1) ? 1 : 0);
498 		break;
499 	default:
500 		/* probably undefined, so zero it out */
501 		ssc->ses_arq = 0;
502 		break;
503 	}
504 
505 	ssc->ses_sbufp = getrbuf(KM_SLEEP);
506 	cv_init(&ssc->ses_sbufcv, NULL, CV_DRIVER, NULL);
507 
508 	/*
509 	 * If the HBA supports wide, tell it to use wide.
510 	 */
511 	if (scsi_ifgetcap(SES_ROUTE(ssc), "wide-xfer", 1) != -1) {
512 		int wd = ((devp->sd_inq->inq_rdf == RDF_SCSI2) &&
513 		    (devp->sd_inq->inq_wbus16 || devp->sd_inq->inq_wbus32))
514 		    ? 1 : 0;
515 		(void) scsi_ifsetcap(SES_ROUTE(ssc), "wide-xfer", wd, 1);
516 	}
517 
518 	/*
519 	 * Now do ssc init of enclosure specifics.
520 	 * At the same time, check to make sure getrbuf
521 	 * actually succeeded.
522 	 */
523 	if ((*ssc->ses_vec.softc_init)(ssc, 1)) {
524 		SES_LOG(ssc, SES_CE_DEBUG3, "failed softc init");
525 		(void) (*ssc->ses_vec.softc_init)(ssc, 0);
526 		ddi_remove_minor_node(dip, NULL);
527 		scsi_destroy_pkt(ssc->ses_rqpkt);
528 		scsi_free_consistent_buf(ssc->ses_rqbp);
529 		if (ssc->ses_sbufp) {
530 			freerbuf(ssc->ses_sbufp);
531 		}
532 		cv_destroy(&ssc->ses_sbufcv);
533 		ddi_soft_state_free(estate, inst);
534 		scsi_unprobe(devp);
535 		return (DDI_FAILURE);
536 	}
537 
538 	/*
539 	 * create this property so that PM code knows we want
540 	 * to be suspended at PM time
541 	 */
542 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
543 	    PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
544 
545 	/* announce the existence of this device */
546 	ddi_report_dev(dip);
547 	return (DDI_SUCCESS);
548 }
549 
550 
551 /*
552  * Detach ses device.
553  *
554  * XXX:  Power management is NOT supported.  A token framework
555  *       is provided that will need to be extended assuming we have
556  *       ses devices we can power down.  Currently, we don't have any.
557  */
558 static int
559 ses_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
560 {
561 	ses_softc_t *ssc;
562 	int inst;
563 
564 	switch (cmd) {
565 	case DDI_DETACH:
566 		inst = ddi_get_instance(dip);
567 		ssc = ddi_get_soft_state(estate, inst);
568 		if (ssc == NULL) {
569 			cmn_err(CE_NOTE,
570 			    "ses%d: DDI_DETACH, no softstate found", inst);
571 			return (DDI_FAILURE);
572 		}
573 		if (ISOPEN(ssc)) {
574 			return (DDI_FAILURE);
575 		}
576 
577 #if		!defined(lint)
578 		/* LINTED */
579 		_NOTE(COMPETING_THREADS_NOW);
580 #endif		/* !defined(lint) */
581 
582 		if (ssc->ses_vec.softc_init)
583 			(void) (*ssc->ses_vec.softc_init)(ssc, 0);
584 
585 #if		!defined(lint)
586 		_NOTE(NO_COMPETING_THREADS_NOW);
587 #endif		/* !defined(lint) */
588 
589 		(void) scsi_ifsetcap(SES_ROUTE(ssc), "auto-rqsense", 1, 0);
590 		scsi_destroy_pkt(ssc->ses_rqpkt);
591 		scsi_free_consistent_buf(ssc->ses_rqbp);
592 		freerbuf(ssc->ses_sbufp);
593 		cv_destroy(&ssc->ses_sbufcv);
594 		ddi_soft_state_free(estate, inst);
595 		ddi_prop_remove_all(dip);
596 		ddi_remove_minor_node(dip, NULL);
597 		scsi_unprobe(ddi_get_driver_private(dip));
598 		break;
599 
600 	case DDI_SUSPEND:
601 		inst = ddi_get_instance(dip);
602 		if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
603 			cmn_err(CE_NOTE,
604 			    "ses%d: DDI_SUSPEND, no softstate found", inst);
605 			return (DDI_FAILURE);
606 		}
607 
608 		/*
609 		 * If driver idle, accept suspend request.
610 		 * If it's busy, reject it.  This keeps things simple!
611 		 */
612 		mutex_enter(SES_MUTEX);
613 		if (ssc->ses_sbufbsy) {
614 			mutex_exit(SES_MUTEX);
615 			return (DDI_FAILURE);
616 		}
617 		ssc->ses_suspended = 1;
618 		mutex_exit(SES_MUTEX);
619 		break;
620 
621 	default:
622 		return (DDI_FAILURE);
623 	}
624 	return (DDI_SUCCESS);
625 }
626 
627 /* ARGSUSED */
628 static int
629 ses_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
630 {
631 	dev_t dev;
632 	ses_softc_t *ssc;
633 	int inst, error;
634 
635 	switch (infocmd) {
636 	case DDI_INFO_DEVT2DEVINFO:
637 		dev = (dev_t)arg;
638 		inst = getminor(dev);
639 		if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
640 			return (DDI_FAILURE);
641 		}
642 		*result = (void *) ssc->ses_devp->sd_dev;
643 		error = DDI_SUCCESS;
644 		break;
645 	case DDI_INFO_DEVT2INSTANCE:
646 		dev = (dev_t)arg;
647 		inst = getminor(dev);
648 		*result = (void *)(uintptr_t)inst;
649 		error = DDI_SUCCESS;
650 		break;
651 	default:
652 		error = DDI_FAILURE;
653 	}
654 	return (error);
655 }
656 
657 
658 /*
659  * Unix Entry Points
660  */
661 
662 /* ARGSUSED */
663 static int
664 ses_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
665 {
666 	ses_softc_t *ssc;
667 
668 	if ((ssc = ddi_get_soft_state(estate, getminor(*dev_p))) == NULL) {
669 		return (ENXIO);
670 	}
671 
672 	/*
673 	 * If the device is powered down, request it's activation.
674 	 * If it can't be activated, fail open.
675 	 */
676 	if (ssc->ses_suspended &&
677 	    ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
678 		return (EIO);
679 	}
680 
681 	mutex_enter(SES_MUTEX);
682 	if (otyp == OTYP_LYR)
683 		ssc->ses_lyropen++;
684 	else
685 		ssc->ses_oflag = 1;
686 
687 	ssc->ses_present = (ssc->ses_present)? ssc->ses_present: SES_OPENING;
688 	mutex_exit(SES_MUTEX);
689 	return (EOK);
690 }
691 
692 /*ARGSUSED*/
693 static int
694 ses_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
695 {
696 	ses_softc_t *ssc;
697 	if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL) {
698 		return (ENXIO);
699 	}
700 
701 	if (ssc->ses_suspended) {
702 		(void) ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1);
703 	}
704 
705 	mutex_enter(SES_MUTEX);
706 	if (otyp == OTYP_LYR)
707 		ssc->ses_lyropen -= (ssc->ses_lyropen)? 1: 0;
708 	else
709 		ssc->ses_oflag = 0;
710 	mutex_exit(SES_MUTEX);
711 	return (0);
712 }
713 
714 
715 /*ARGSUSED3*/
716 static int
717 ses_ioctl(dev_t dev, int cmd, intptr_t arg, int flg, cred_t *cred_p, int *rvalp)
718 {
719 	ses_softc_t *ssc;
720 	ses_object k, *up;
721 	ses_objarg x;
722 	uchar_t t;
723 	uchar_t i;
724 	int rv = 0;
725 
726 	if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL ||
727 	    ssc->ses_present == SES_CLOSED) {
728 		return (ENXIO);
729 	}
730 
731 
732 	switch (cmd) {
733 	case SESIOC_GETNOBJ:
734 		if (ddi_copyout(&ssc->ses_nobjects, (void *)arg,
735 		    sizeof (int), flg)) {
736 			rv = EFAULT;
737 			break;
738 		}
739 		break;
740 
741 	case SESIOC_GETOBJMAP:
742 		up = (ses_object *) arg;
743 		mutex_enter(SES_MUTEX);
744 		for (i = 0; i != ssc->ses_nobjects; i++) {
745 			k.obj_id = i;
746 			k.subencid = ssc->ses_objmap[i].subenclosure;
747 			k.elem_type = ssc->ses_objmap[i].enctype;
748 			if (ddi_copyout(&k, up, sizeof (k), flg)) {
749 				rv = EFAULT;
750 				break;
751 			}
752 			up++;
753 		}
754 		mutex_exit(SES_MUTEX);
755 		break;
756 
757 	case SESIOC_INIT:
758 		if (drv_priv(cred_p) != 0) {
759 			rv = EPERM;
760 			break;
761 		}
762 		rv = (*ssc->ses_vec.init_enc)(ssc);
763 		break;
764 
765 	case SESIOC_GETENCSTAT:
766 		if ((ssc->ses_encstat & ENCI_SVALID) == 0) {
767 			rv = (*ssc->ses_vec.get_encstat)(ssc, KM_SLEEP);
768 			if (rv) {
769 				break;
770 			}
771 		}
772 		t = ssc->ses_encstat & 0xf;
773 		if (ddi_copyout(&t, (void *)arg, sizeof (t), flg))
774 			rv = EFAULT;
775 		/*
776 		 * And always invalidate enclosure status on the way out.
777 		 */
778 		mutex_enter(SES_MUTEX);
779 		ssc->ses_encstat &= ~ENCI_SVALID;
780 		mutex_exit(SES_MUTEX);
781 		break;
782 
783 	case SESIOC_SETENCSTAT:
784 		if (drv_priv(cred_p) != 0) {
785 			rv = EPERM;
786 			break;
787 		}
788 		if (ddi_copyin((void *)arg, &t, sizeof (t), flg))
789 			rv = EFAULT;
790 		else
791 			rv = (*ssc->ses_vec.set_encstat)(ssc, t, KM_SLEEP);
792 		mutex_enter(SES_MUTEX);
793 		ssc->ses_encstat &= ~ENCI_SVALID;
794 		mutex_exit(SES_MUTEX);
795 		break;
796 
797 	case SESIOC_GETOBJSTAT:
798 		if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
799 			rv = EFAULT;
800 			break;
801 		}
802 		if (x.obj_id >= ssc->ses_nobjects) {
803 			rv = EINVAL;
804 			break;
805 		}
806 		if ((rv = (*ssc->ses_vec.get_objstat)(ssc, &x, KM_SLEEP)) != 0)
807 			break;
808 		if (ddi_copyout(&x, (void *)arg, sizeof (x), flg))
809 			rv = EFAULT;
810 		else {
811 			/*
812 			 * Now that we no longer poll, svalid never stays true.
813 			 */
814 			mutex_enter(SES_MUTEX);
815 			ssc->ses_objmap[x.obj_id].svalid = 0;
816 			mutex_exit(SES_MUTEX);
817 		}
818 		break;
819 
820 	case SESIOC_SETOBJSTAT:
821 		if (drv_priv(cred_p) != 0) {
822 			rv = EPERM;
823 			break;
824 		}
825 		if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
826 			rv = EFAULT;
827 			break;
828 		}
829 		if (x.obj_id >= ssc->ses_nobjects) {
830 			rv = EINVAL;
831 			break;
832 		}
833 		rv = (*ssc->ses_vec.set_objstat)(ssc, &x, KM_SLEEP);
834 		if (rv == 0) {
835 			mutex_enter(SES_MUTEX);
836 			ssc->ses_objmap[x.obj_id].svalid = 0;
837 			mutex_exit(SES_MUTEX);
838 		}
839 		break;
840 
841 	case USCSICMD:
842 		if (drv_priv(cred_p) != 0) {
843 			rv = EPERM;
844 			break;
845 		}
846 		rv = ses_uscsi_cmd(ssc, (Uscmd *)arg, flg);
847 		break;
848 
849 	default:
850 		rv = ENOTTY;
851 		break;
852 	}
853 	return (rv);
854 }
855 
856 
857 /*
858  * Loop on running a kernel based command
859  *
860  * FIXME:  This routine is not really needed.
861  */
862 int
863 ses_runcmd(ses_softc_t *ssc, Uscmd *lp)
864 {
865 	int e;
866 
867 	lp->uscsi_status = 0;
868 	e = ses_uscsi_cmd(ssc, lp, FKIOCTL);
869 
870 #ifdef	not
871 	/*
872 	 * Debug:  Nice cross-check code for verifying consistent status.
873 	 */
874 	if (lp->uscsi_status) {
875 		if (lp->uscsi_status == STATUS_CHECK) {
876 			SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
877 			    "0x%x->%s ASC/ASCQ=0x%x/0x%x>",
878 			    lp->uscsi_cdb[0],
879 			    scsi_sname(lp->uscsi_rqbuf[2] & 0xf),
880 			    lp->uscsi_rqbuf[12] & 0xff,
881 			    lp->uscsi_rqbuf[13] & 0xff);
882 		} else {
883 			SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
884 			    "0x%x -> Status 0x%x", lp->uscsi_cdb[0],
885 			    lp->uscsi_status);
886 		}
887 	}
888 #endif	/* not */
889 	return (e);
890 }
891 
892 
893 /*
894  * Run a scsi command.
895  */
896 int
897 ses_uscsi_cmd(ses_softc_t *ssc, Uscmd *Uc, int Uf)
898 {
899 	Uscmd	*uscmd;
900 	struct buf	*bp;
901 	enum uio_seg	uioseg;
902 	int	err;
903 
904 	/*
905 	 * Grab local 'special' buffer
906 	 */
907 	mutex_enter(SES_MUTEX);
908 	while (ssc->ses_sbufbsy) {
909 		cv_wait(&ssc->ses_sbufcv, &ssc->ses_devp->sd_mutex);
910 	}
911 	ssc->ses_sbufbsy = 1;
912 	mutex_exit(SES_MUTEX);
913 
914 	/*
915 	 * If the device is powered down, request it's activation.
916 	 * This check must be done after setting ses_sbufbsy!
917 	 */
918 	if (ssc->ses_suspended &&
919 	    ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
920 		mutex_enter(SES_MUTEX);
921 		ssc->ses_sbufbsy = 0;
922 		mutex_exit(SES_MUTEX);
923 		return (EIO);
924 	}
925 
926 	err = scsi_uscsi_alloc_and_copyin((intptr_t)Uc, Uf,
927 	    SES_ROUTE(ssc), &uscmd);
928 	if (err != 0) {
929 		SES_LOG(ssc, SES_CE_DEBUG1, "ses_uscsi_cmd: "
930 		    "scsi_uscsi_alloc_and_copyin failed\n");
931 		mutex_enter(SES_MUTEX);
932 		ssc->ses_sbufbsy = 0;
933 		cv_signal(&ssc->ses_sbufcv);
934 		mutex_exit(SES_MUTEX);
935 		SES_LOG(ssc, SES_CE_DEBUG2, efl, __LINE__);
936 		return (err);
937 	}
938 
939 	/*
940 	 * Copy the uscsi command related infos to ssc for use in ses_start()
941 	 * and ses_callback().
942 	 */
943 	bcopy(uscmd, &ssc->ses_uscsicmd, sizeof (Uscmd));
944 	if (uscmd->uscsi_cdb != NULL) {
945 		bcopy(uscmd->uscsi_cdb, &ssc->ses_srqcdb,
946 		    (size_t)(uscmd->uscsi_cdblen));
947 	}
948 	ssc->ses_uscsicmd.uscsi_status = 0;
949 
950 	bp = ssc->ses_sbufp;
951 	bp->av_back = (struct buf *)NULL;
952 	bp->av_forw = (struct buf *)NULL;
953 	bp->b_back = (struct buf *)ssc;
954 	bp->b_edev = NODEV;
955 
956 	if (uscmd->uscsi_cdb != NULL) {
957 		if (uscmd->uscsi_cdblen == CDB_GROUP0) {
958 			SES_LOG(ssc, SES_CE_DEBUG7,
959 			    "scsi_cmd: %x %x %x %x %x %x",
960 			    ((char *)uscmd->uscsi_cdb)[0],
961 			    ((char *)uscmd->uscsi_cdb)[1],
962 			    ((char *)uscmd->uscsi_cdb)[2],
963 			    ((char *)uscmd->uscsi_cdb)[3],
964 			    ((char *)uscmd->uscsi_cdb)[4],
965 			    ((char *)uscmd->uscsi_cdb)[5]);
966 		} else {
967 			SES_LOG(ssc, SES_CE_DEBUG7,
968 			    "scsi cmd: %x %x %x %x %x %x %x %x %x %x",
969 			    ((char *)uscmd->uscsi_cdb)[0],
970 			    ((char *)uscmd->uscsi_cdb)[1],
971 			    ((char *)uscmd->uscsi_cdb)[2],
972 			    ((char *)uscmd->uscsi_cdb)[3],
973 			    ((char *)uscmd->uscsi_cdb)[4],
974 			    ((char *)uscmd->uscsi_cdb)[5],
975 			    ((char *)uscmd->uscsi_cdb)[6],
976 			    ((char *)uscmd->uscsi_cdb)[7],
977 			    ((char *)uscmd->uscsi_cdb)[8],
978 			    ((char *)uscmd->uscsi_cdb)[9]);
979 		}
980 	}
981 
982 	uioseg = (Uf & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
983 	err = scsi_uscsi_handle_cmd(NODEV, uioseg, uscmd,
984 	    ses_start, bp, NULL);
985 
986 	/*
987 	 * ses_callback() may set values for ssc->ses_uscsicmd or
988 	 * ssc->ses_srqsbuf, so copy them back to uscmd.
989 	 */
990 	if (uscmd->uscsi_rqbuf != NULL) {
991 		bcopy(&ssc->ses_srqsbuf, uscmd->uscsi_rqbuf,
992 		    (size_t)(uscmd->uscsi_rqlen));
993 		uscmd->uscsi_rqresid = ssc->ses_uscsicmd.uscsi_rqresid;
994 	}
995 	uscmd->uscsi_status = ssc->ses_uscsicmd.uscsi_status;
996 
997 	(void) scsi_uscsi_copyout_and_free((intptr_t)Uc, uscmd);
998 	mutex_enter(SES_MUTEX);
999 	ssc->ses_sbufbsy = 0;
1000 	cv_signal(&ssc->ses_sbufcv);
1001 	mutex_exit(SES_MUTEX);
1002 
1003 	return (err);
1004 }
1005 
1006 
1007 
1008 /*
1009  * Command start and done functions.
1010  */
1011 static int
1012 ses_start(struct buf *bp)
1013 {
1014 	ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
1015 
1016 	SES_LOG(ssc, SES_CE_DEBUG9, "ses_start");
1017 	if (!BP_PKT(bp)) {
1018 		/*
1019 		 * Allocate a packet.
1020 		 */
1021 		ses_get_pkt(bp, SLEEP_FUNC);
1022 		if (!BP_PKT(bp)) {
1023 			int err;
1024 			bp->b_resid = bp->b_bcount;
1025 			if (geterror(bp) == 0)
1026 				SET_BP_ERROR(bp, EIO);
1027 			err = geterror(bp);
1028 			biodone(bp);
1029 			return (err);
1030 		}
1031 	}
1032 
1033 	/*
1034 	 * Initialize the transfer residue, error code, and retry count.
1035 	 */
1036 	bp->b_resid = 0;
1037 	SET_BP_ERROR(bp, 0);
1038 
1039 #if	!defined(lint)
1040 	_NOTE(NO_COMPETING_THREADS_NOW);
1041 #endif	/* !defined(lint) */
1042 	ssc->ses_retries = ses_retry_count;
1043 
1044 #if	!defined(lint)
1045 	/* LINTED */
1046 	_NOTE(COMPETING_THREADS_NOW);
1047 #endif	/* !defined(lint) */
1048 
1049 	SES_LOG(ssc, SES_CE_DEBUG9, "ses_start -> scsi_transport");
1050 	switch (scsi_transport(BP_PKT(bp))) {
1051 	case TRAN_ACCEPT:
1052 		return (0);
1053 		/* break; */
1054 
1055 	case TRAN_BUSY:
1056 		SES_LOG(ssc, SES_CE_DEBUG2,
1057 		    "ses_start: TRANSPORT BUSY");
1058 		SES_ENABLE_RESTART(SES_RESTART_TIME, BP_PKT(bp));
1059 		return (0);
1060 		/* break; */
1061 
1062 	default:
1063 		SES_LOG(ssc, SES_CE_DEBUG2, "TRANSPORT ERROR\n");
1064 		SET_BP_ERROR(bp, EIO);
1065 		scsi_destroy_pkt(BP_PKT(bp));
1066 		SET_BP_PKT(bp, NULL);
1067 		biodone(bp);
1068 		return (EIO);
1069 		/* break; */
1070 	}
1071 }
1072 
1073 
1074 static void
1075 ses_get_pkt(struct buf *bp, int (*func)())
1076 {
1077 	ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
1078 	Uscmd *scmd = &ssc->ses_uscsicmd;
1079 	struct scsi_pkt *pkt;
1080 	int stat_size = 1;
1081 	int flags = 0;
1082 
1083 	if ((scmd->uscsi_flags & USCSI_RQENABLE) && ssc->ses_arq) {
1084 		if (scmd->uscsi_rqlen > SENSE_LENGTH) {
1085 			stat_size = (int)(scmd->uscsi_rqlen) +
1086 			    sizeof (struct scsi_arq_status) -
1087 			    sizeof (struct scsi_extended_sense);
1088 			flags = PKT_XARQ;
1089 		} else {
1090 			stat_size = sizeof (struct scsi_arq_status);
1091 		}
1092 	}
1093 
1094 	if (bp->b_bcount) {
1095 		pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, bp,
1096 		    scmd->uscsi_cdblen, stat_size, 0, flags,
1097 		    func, (caddr_t)ssc);
1098 	} else {
1099 		pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, NULL,
1100 		    scmd->uscsi_cdblen, stat_size, 0, flags,
1101 		    func, (caddr_t)ssc);
1102 	}
1103 	SET_BP_PKT(bp, pkt);
1104 	if (pkt == (struct scsi_pkt *)NULL)
1105 		return;
1106 	bcopy(scmd->uscsi_cdb, pkt->pkt_cdbp, (size_t)scmd->uscsi_cdblen);
1107 
1108 	/* Set an upper bound timeout of ses_io_time if zero is passed in */
1109 	pkt->pkt_time = (scmd->uscsi_timeout == 0) ?
1110 	    ses_io_time : scmd->uscsi_timeout;
1111 
1112 	pkt->pkt_comp = ses_callback;
1113 	pkt->pkt_private = (opaque_t)ssc;
1114 }
1115 
1116 
1117 /*
1118  * Restart ses command.
1119  */
1120 static void
1121 ses_restart(void *arg)
1122 {
1123 	struct scsi_pkt *pkt = (struct scsi_pkt *)arg;
1124 	ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1125 	struct buf *bp = ssc->ses_sbufp;
1126 	SES_LOG(ssc, SES_CE_DEBUG9, "ses_restart");
1127 
1128 	ssc->ses_restart_id = NULL;
1129 
1130 	switch (scsi_transport(pkt)) {
1131 	case TRAN_ACCEPT:
1132 		SES_LOG(ssc, SES_CE_DEBUG9,
1133 		    "RESTART %d ok", ssc->ses_retries);
1134 		return;
1135 		/* break; */
1136 	case TRAN_BUSY:
1137 		SES_LOG(ssc, SES_CE_DEBUG1,
1138 		    "RESTART %d TRANSPORT BUSY\n", ssc->ses_retries);
1139 		if (ssc->ses_retries > SES_NO_RETRY) {
1140 			ssc->ses_retries -= SES_BUSY_RETRY;
1141 			SES_ENABLE_RESTART(SES_RESTART_TIME, pkt);
1142 			return;
1143 		}
1144 		SET_BP_ERROR(bp, EBUSY);
1145 		break;
1146 	default:
1147 		SET_BP_ERROR(bp, EIO);
1148 		break;
1149 	}
1150 	SES_LOG(ssc, SES_CE_DEBUG1,
1151 	    "RESTART %d TRANSPORT FAILED\n", ssc->ses_retries);
1152 
1153 	pkt = (struct scsi_pkt *)bp->av_back;
1154 	scsi_destroy_pkt(pkt);
1155 	bp->b_resid = bp->b_bcount;
1156 	SET_BP_PKT(bp, NULL);
1157 	biodone(bp);
1158 }
1159 
1160 
1161 /*
1162  * Command completion processing
1163  */
1164 #define	HBA_RESET	(STAT_BUS_RESET|STAT_DEV_RESET|STAT_ABORTED)
1165 static void
1166 ses_callback(struct scsi_pkt *pkt)
1167 {
1168 	ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1169 	struct buf *bp;
1170 	Uscmd *scmd;
1171 	int err;
1172 	char action;
1173 
1174 	bp = ssc->ses_sbufp;
1175 	scmd = &ssc->ses_uscsicmd;
1176 	/* SES_LOG(ssc, SES_CE_DEBUG9, "ses_callback"); */
1177 
1178 	/*
1179 	 * Optimization: Normal completion.
1180 	 */
1181 	if (pkt->pkt_reason == CMD_CMPLT &&
1182 	    !SCBP_C(pkt) &&
1183 	    !(pkt->pkt_flags & FLAG_SENSING) &&
1184 	    !pkt->pkt_resid) {
1185 		scsi_destroy_pkt(pkt);
1186 		SET_BP_PKT(bp, NULL);
1187 		biodone(bp);
1188 		return;
1189 	}
1190 
1191 
1192 	/*
1193 	 * Abnormal completion.
1194 	 *
1195 	 * Assume most common error initially.
1196 	 */
1197 	err = EIO;
1198 	action = COMMAND_DONE;
1199 	if (scmd->uscsi_flags & USCSI_DIAGNOSE) {
1200 		ssc->ses_retries = SES_NO_RETRY;
1201 	}
1202 
1203 CHECK_PKT:
1204 	if (pkt->pkt_reason != CMD_CMPLT) {
1205 		/* Process transport errors. */
1206 		switch (pkt->pkt_reason) {
1207 		case CMD_TIMEOUT:
1208 			/*
1209 			 * If the transport layer didn't clear the problem,
1210 			 * reset the target.
1211 			 */
1212 			if (! (pkt->pkt_statistics & HBA_RESET)) {
1213 				(void) scsi_reset(&pkt->pkt_address,
1214 				    RESET_TARGET);
1215 			}
1216 			err = ETIMEDOUT;
1217 			break;
1218 
1219 		case CMD_INCOMPLETE:
1220 		case CMD_UNX_BUS_FREE:
1221 			/*
1222 			 * No response?  If probing, give up.
1223 			 * Otherwise, keep trying until retries exhausted.
1224 			 * Then lockdown the driver as the device is
1225 			 * unplugged.
1226 			 */
1227 			if (ssc->ses_retries <= SES_NO_RETRY &&
1228 			    !(scmd->uscsi_flags & USCSI_DIAGNOSE)) {
1229 				ssc->ses_present = SES_CLOSED;
1230 			}
1231 			/* Inhibit retries to speed probe/attach. */
1232 			if (ssc->ses_present < SES_OPEN) {
1233 				ssc->ses_retries = SES_NO_RETRY;
1234 			}
1235 			/* SES_CMD_RETRY4(ssc->ses_retries); */
1236 			err = ENXIO;
1237 			break;
1238 
1239 		case CMD_DATA_OVR:
1240 			/*
1241 			 * XXX:	Some HBA's (e.g. Adaptec 1740 and
1242 			 *	earlier ISP revs) report a DATA OVERRUN
1243 			 *	error instead of a transfer residue.  So,
1244 			 *	we convert the error and restart.
1245 			 */
1246 			if ((bp->b_bcount - pkt->pkt_resid) > 0) {
1247 				SES_LOG(ssc, SES_CE_DEBUG6,
1248 				    "ignoring overrun");
1249 				pkt->pkt_reason = CMD_CMPLT;
1250 				err = EOK;
1251 				goto CHECK_PKT;
1252 			}
1253 			ssc->ses_retries = SES_NO_RETRY;
1254 			/* err = EIO; */
1255 			break;
1256 
1257 		case CMD_DMA_DERR:
1258 			ssc->ses_retries = SES_NO_RETRY;
1259 			err = EFAULT;
1260 			break;
1261 
1262 		default:
1263 			/* err = EIO; */
1264 			break;
1265 		}
1266 		if (pkt == ssc->ses_rqpkt) {
1267 			SES_LOG(ssc, CE_WARN, fail_msg,
1268 			    "Request Sense ",
1269 			    scsi_rname(pkt->pkt_reason),
1270 			    (ssc->ses_retries > 0)?
1271 			    "retrying": "giving up");
1272 			pkt = (struct scsi_pkt *)bp->av_back;
1273 			action = QUE_SENSE;
1274 		} else {
1275 			SES_LOG(ssc, CE_WARN, fail_msg,
1276 			    "", scsi_rname(pkt->pkt_reason),
1277 			    (ssc->ses_retries > 0)?
1278 			    "retrying": "giving up");
1279 			action = QUE_COMMAND;
1280 		}
1281 		/* Device exists, allow full error recovery. */
1282 		if (ssc->ses_retries > SES_NO_RETRY) {
1283 			ssc->ses_present = SES_OPEN;
1284 		}
1285 
1286 
1287 	/*
1288 	 * Process status and sense data errors.
1289 	 */
1290 	} else {
1291 		ssc->ses_present = SES_OPEN;
1292 		action = ses_decode_sense(pkt, &err);
1293 	}
1294 
1295 
1296 	/*
1297 	 * Initiate error recovery action, as needed.
1298 	 */
1299 	switch (action) {
1300 	case QUE_COMMAND_NOW:
1301 		/* SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd now"); */
1302 		if (ssc->ses_retries > SES_NO_RETRY) {
1303 			ssc->ses_retries -= SES_CMD_RETRY;
1304 			scmd->uscsi_status = 0;
1305 			if (ssc->ses_arq)
1306 				bzero(pkt->pkt_scbp,
1307 				    sizeof (struct scsi_arq_status));
1308 
1309 			if (scsi_transport((struct scsi_pkt *)bp->av_back)
1310 			    != TRAN_ACCEPT) {
1311 				SES_ENABLE_RESTART(SES_RESTART_TIME,
1312 				    (struct scsi_pkt *)bp->av_back);
1313 			}
1314 			return;
1315 		}
1316 		break;
1317 
1318 	case QUE_COMMAND:
1319 		SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd");
1320 		if (ssc->ses_retries > SES_NO_RETRY) {
1321 			clock_t ms_time;
1322 
1323 			ms_time =
1324 			    (err == EBUSY)? SES_BUSY_TIME : SES_RESTART_TIME;
1325 			ssc->ses_retries -=
1326 			    (err == EBUSY)? SES_BUSY_RETRY: SES_CMD_RETRY;
1327 			scmd->uscsi_status = 0;
1328 			if (ssc->ses_arq)
1329 				bzero(pkt->pkt_scbp,
1330 				    sizeof (struct scsi_arq_status));
1331 
1332 			SES_ENABLE_RESTART(ms_time,
1333 			    (struct scsi_pkt *)bp->av_back);
1334 			return;
1335 		}
1336 		break;
1337 
1338 	case QUE_SENSE:
1339 		SES_LOG(ssc, SES_CE_DEBUG1, "retrying sense");
1340 		if (ssc->ses_retries > SES_NO_RETRY) {
1341 			ssc->ses_retries -= SES_SENSE_RETRY;
1342 			scmd->uscsi_status = 0;
1343 			bzero(&ssc->ses_srqsbuf, MAX_SENSE_LENGTH);
1344 
1345 			if (scsi_transport(ssc->ses_rqpkt) != TRAN_ACCEPT) {
1346 				SES_ENABLE_RESTART(SES_RESTART_TIME,
1347 				    ssc->ses_rqpkt);
1348 			}
1349 			return;
1350 		}
1351 		break;
1352 
1353 	case COMMAND_DONE:
1354 		SES_LOG(ssc, SES_CE_DEBUG4, "cmd done");
1355 		pkt = (struct scsi_pkt *)bp->av_back;
1356 		bp->b_resid = pkt->pkt_resid;
1357 		if (bp->b_resid) {
1358 			SES_LOG(ssc, SES_CE_DEBUG6,
1359 			    "transfer residue %ld(%ld)",
1360 			    bp->b_bcount - bp->b_resid, bp->b_bcount);
1361 		}
1362 		break;
1363 	}
1364 	pkt = (struct scsi_pkt *)bp->av_back;
1365 	if (err) {
1366 		SES_LOG(ssc, SES_CE_DEBUG1, "SES: ERROR %d\n", err);
1367 		SET_BP_ERROR(bp, err);
1368 		bp->b_resid = bp->b_bcount;
1369 	}
1370 	scsi_destroy_pkt(pkt);
1371 	SET_BP_PKT(bp, NULL);
1372 	biodone(bp);
1373 }
1374 
1375 
1376 /*
1377  * Check status and sense data and determine recovery.
1378  */
1379 static int
1380 ses_decode_sense(struct scsi_pkt *pkt, int *err)
1381 {
1382 	ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1383 	struct	scsi_extended_sense *sense =
1384 	    (struct scsi_extended_sense *)&ssc->ses_srqsbuf;
1385 	Uscmd *scmd = &ssc->ses_uscsicmd;
1386 	char sense_flag = 0;
1387 	uchar_t status = SCBP_C(pkt) & STATUS_MASK;
1388 	char *err_action;
1389 	char action;
1390 	uchar_t rqlen;
1391 	int amt;
1392 
1393 	/*
1394 	 * Process manual request sense.
1395 	 * Copy manual request sense to sense buffer.
1396 	 *
1397 	 * This is done if auto request sense is not enabled.
1398 	 * Or the auto request sense failed and the request
1399 	 * sense needs to be retried.
1400 	 */
1401 	if (pkt->pkt_flags & FLAG_SENSING) {
1402 		struct buf *sbp = ssc->ses_rqbp;
1403 		amt = min(MAX_SENSE_LENGTH,
1404 		    sbp->b_bcount - sbp->b_resid);
1405 		rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
1406 		bcopy(sbp->b_un.b_addr, sense, rqlen);
1407 		scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
1408 		sense_flag = 1;
1409 	/*
1410 	 * Process auto request sense.
1411 	 * Copy auto request sense to sense buffer.
1412 	 *
1413 	 * If auto request sense failed due to transport error,
1414 	 * retry the command.  Otherwise process the status and
1415 	 * sense data.
1416 	 */
1417 	} else if (ssc->ses_arq && pkt->pkt_state & STATE_ARQ_DONE) {
1418 		struct scsi_arq_status *arq =
1419 		    (struct scsi_arq_status *)(pkt->pkt_scbp);
1420 		uchar_t *arq_status = (uchar_t *)&arq->sts_rqpkt_status;
1421 		if (pkt->pkt_state & STATE_XARQ_DONE) {
1422 			amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
1423 		} else {
1424 			if (arq->sts_rqpkt_resid > SENSE_LENGTH) {
1425 				amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
1426 			} else {
1427 				amt = SENSE_LENGTH - arq->sts_rqpkt_resid;
1428 			}
1429 		}
1430 
1431 		if (arq->sts_rqpkt_reason != CMD_CMPLT) {
1432 			return (QUE_COMMAND);
1433 		}
1434 
1435 		rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
1436 		bcopy(&arq->sts_sensedata, sense, rqlen);
1437 		scmd->uscsi_status = status;
1438 		scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
1439 		status = *arq_status & STATUS_MASK;
1440 		pkt->pkt_state &= ~STATE_ARQ_DONE;
1441 		sense_flag = 1;
1442 	}
1443 
1444 
1445 	/*
1446 	 * Check status of REQUEST SENSE or command.
1447 	 *
1448 	 * If it's not successful, try retrying the original command
1449 	 * and hope that it goes away.  If not, we'll eventually run
1450 	 * out of retries and die.
1451 	 */
1452 	switch (status) {
1453 	case STATUS_GOOD:
1454 	case STATUS_INTERMEDIATE:
1455 	case STATUS_MET:
1456 		/*
1457 		 * If the command status is ok, we're done.
1458 		 * Otherwise, examine the request sense data.
1459 		 */
1460 		if (! sense_flag) {
1461 			*err = EOK;
1462 			return (COMMAND_DONE);
1463 		}
1464 		break;
1465 
1466 	case STATUS_CHECK:
1467 		SES_LOG(ssc, SES_CE_DEBUG3, "status decode: check");
1468 		*err = EIO;
1469 		return (QUE_SENSE);
1470 		/* break; */
1471 
1472 	case STATUS_BUSY:
1473 		SES_LOG(ssc, SES_CE_DEBUG1, "status decode: busy");
1474 		/* SES_CMD_RETRY2(ssc->ses_retries); */
1475 		*err = EBUSY;
1476 		return (QUE_COMMAND);
1477 		/* break; */
1478 
1479 	case STATUS_RESERVATION_CONFLICT:
1480 		SES_LOG(ssc, SES_CE_DEBUG1, "status decode: reserved");
1481 		*err = EACCES;
1482 		return (COMMAND_DONE_ERROR);
1483 		/* break; */
1484 
1485 	case STATUS_TERMINATED:
1486 		SES_LOG(ssc, SES_CE_DEBUG1, "status decode: terminated");
1487 		*err = ECANCELED;
1488 		return (COMMAND_DONE_ERROR);
1489 		/* break; */
1490 
1491 	default:
1492 		SES_LOG(ssc, SES_CE_DEBUG1, "status 0x%x", status);
1493 		*err = EIO;
1494 		return (QUE_COMMAND);
1495 		/* break; */
1496 	}
1497 
1498 
1499 	/*
1500 	 * Check REQUEST SENSE error code.
1501 	 *
1502 	 * Either there's no error, a retryable error,
1503 	 * or it's dead.  SES devices aren't very complex.
1504 	 */
1505 	err_action = "retrying";
1506 	switch (sense->es_key) {
1507 	case KEY_RECOVERABLE_ERROR:
1508 		*err = EOK;
1509 		err_action = "recovered";
1510 		action = COMMAND_DONE;
1511 		break;
1512 
1513 	case KEY_UNIT_ATTENTION:
1514 		/*
1515 		 * This is common for RAID!
1516 		 */
1517 		/* *err = EIO; */
1518 		SES_CMD_RETRY1(ssc->ses_retries);
1519 		action = QUE_COMMAND_NOW;
1520 		break;
1521 
1522 	case KEY_NOT_READY:
1523 	case KEY_NO_SENSE:
1524 		/* *err = EIO; */
1525 		action = QUE_COMMAND;
1526 		break;
1527 
1528 	default:
1529 		/* *err = EIO; */
1530 		err_action = "fatal";
1531 		action = COMMAND_DONE_ERROR;
1532 		break;
1533 	}
1534 	SES_LOG(ssc, SES_CE_DEBUG1,
1535 	    "cdb[0]= 0x%x %s,  key=0x%x, ASC/ASCQ=0x%x/0x%x",
1536 	    scmd->uscsi_cdb[0], err_action,
1537 	    sense->es_key, sense->es_add_code, sense->es_qual_code);
1538 
1539 #ifdef	not
1540 	/*
1541 	 * Dump cdb and sense data stat's for manufacturing.
1542 	 */
1543 	if (DEBUGGING_ERR || sd_error_level == SDERR_ALL) {
1544 		auto buf[128];
1545 
1546 		p = pkt->pkt_cdbp;
1547 		if ((j = scsi_cdb_size[CDB_GROUPID(*p)]) == 0)
1548 			j = CDB_SIZE;
1549 
1550 		/* Print cdb */
1551 		(void) sprintf(buf, "cmd:");
1552 		for (i = 0; i < j; i++) {
1553 			(void) sprintf(&buf[strlen(buf)],
1554 			    hex, (uchar_t)*p++);
1555 		}
1556 		SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
1557 
1558 		/* Suppress trailing zero's in sense data */
1559 		if (amt > 3) {
1560 			p = (char *)devp->sd_sense + amt;
1561 			for (j = amt; j > 3; j--) {
1562 				if (*(--p))  break;
1563 			}
1564 		} else {
1565 			j = amt;
1566 		}
1567 
1568 		/* Print sense data. */
1569 		(void) sprintf(buf, "sense:");
1570 		p = (char *)devp->sd_sense;
1571 		for (i = 0; i < j; i++) {
1572 			(void) sprintf(&buf[strlen(buf)],
1573 			    hex, (uchar_t)*p++);
1574 		}
1575 		SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
1576 	}
1577 #endif	/* not */
1578 	return (action);
1579 }
1580 
1581 
1582 /*PRINTFLIKE3*/
1583 void
1584 ses_log(ses_softc_t *ssc, int level, const char *fmt, ...)
1585 {
1586 	va_list	ap;
1587 	char buf[256];
1588 
1589 	va_start(ap, fmt);
1590 	(void) vsprintf(buf, fmt, ap);
1591 	va_end(ap);
1592 
1593 	if (ssc == (ses_softc_t *)NULL) {
1594 		switch (level) {
1595 		case SES_CE_DEBUG1:
1596 			if (ses_debug > 1)
1597 				cmn_err(CE_NOTE, "%s", buf);
1598 			break;
1599 		case SES_CE_DEBUG2:
1600 			if (ses_debug > 2)
1601 				cmn_err(CE_NOTE, "%s", buf);
1602 			break;
1603 		case SES_CE_DEBUG3:
1604 			if (ses_debug > 3)
1605 				cmn_err(CE_NOTE, "%s", buf);
1606 			break;
1607 		case SES_CE_DEBUG4:
1608 			if (ses_debug > 4)
1609 				cmn_err(CE_NOTE, "%s", buf);
1610 			break;
1611 		case SES_CE_DEBUG5:
1612 			if (ses_debug > 5)
1613 				cmn_err(CE_NOTE, "%s", buf);
1614 			break;
1615 		case SES_CE_DEBUG6:
1616 			if (ses_debug > 6)
1617 				cmn_err(CE_NOTE, "%s", buf);
1618 			break;
1619 		case SES_CE_DEBUG7:
1620 			if (ses_debug > 7)
1621 				cmn_err(CE_NOTE, "%s", buf);
1622 			break;
1623 		case SES_CE_DEBUG8:
1624 			if (ses_debug > 8)
1625 				cmn_err(CE_NOTE, "%s", buf);
1626 			break;
1627 		case SES_CE_DEBUG9:
1628 			if (ses_debug > 9)
1629 				cmn_err(CE_NOTE, "%s", buf);
1630 			break;
1631 		case CE_NOTE:
1632 		case CE_WARN:
1633 		case CE_PANIC:
1634 			cmn_err(level, "%s", buf);
1635 			break;
1636 		case SES_CE_DEBUG:
1637 		default:
1638 			cmn_err(CE_NOTE, "%s", buf);
1639 		break;
1640 		}
1641 		return;
1642 	}
1643 
1644 	switch (level) {
1645 	case CE_CONT:
1646 	case CE_NOTE:
1647 	case CE_WARN:
1648 	case CE_PANIC:
1649 		scsi_log(SES_DEVINFO(ssc), (char *)Snm, level, Str, buf);
1650 		break;
1651 	case SES_CE_DEBUG1:
1652 		if (ses_debug > 1)
1653 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1654 			    Str, buf);
1655 		break;
1656 	case SES_CE_DEBUG2:
1657 		if (ses_debug > 2)
1658 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1659 			    Str, buf);
1660 		break;
1661 	case SES_CE_DEBUG3:
1662 		if (ses_debug > 3)
1663 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1664 			    Str, buf);
1665 		break;
1666 	case SES_CE_DEBUG4:
1667 		if (ses_debug > 4)
1668 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1669 			    Str, buf);
1670 		break;
1671 	case SES_CE_DEBUG5:
1672 		if (ses_debug > 5)
1673 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1674 			    Str, buf);
1675 		break;
1676 	case SES_CE_DEBUG6:
1677 		if (ses_debug > 6)
1678 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1679 			    Str, buf);
1680 		break;
1681 	case SES_CE_DEBUG7:
1682 		if (ses_debug > 7)
1683 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1684 			    Str, buf);
1685 		break;
1686 	case SES_CE_DEBUG8:
1687 		if (ses_debug > 8)
1688 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1689 			    Str, buf);
1690 		break;
1691 	case SES_CE_DEBUG9:
1692 		if (ses_debug > 9)
1693 			scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1694 			    Str, buf);
1695 		break;
1696 	case SES_CE_DEBUG:
1697 	default:
1698 		scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG, Str, buf);
1699 		break;
1700 	}
1701 }
1702 /*
1703  * mode: c
1704  * Local variables:
1705  * c-indent-level: 8
1706  * c-brace-imaginary-offset: 0
1707  * c-brace-offset: -8
1708  * c-argdecl-indent: 8
1709  * c-label-offset: -8
1710  * c-continued-statement-offset: 8
1711  * c-continued-brace-offset: 0
1712  * End:
1713  */
1714