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