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