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