17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
56567eb0aSlh195018 * Common Development and Distribution License (the "License").
66567eb0aSlh195018 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate * Enclosure Services Device target driver
237c478bd9Sstevel@tonic-gate *
244c06356bSdh142964 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate * Use is subject to license terms.
2689b43686SBayard Bell * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
27*ffc5bd0fSKevin Crowe * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
287c478bd9Sstevel@tonic-gate */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
317c478bd9Sstevel@tonic-gate #include <sys/file.h>
327c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
337c478bd9Sstevel@tonic-gate #include <sys/scsi/generic/status.h>
347c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/sesio.h>
357c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/ses.h>
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * Power management defines (should be in a common include file?)
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate #define PM_HARDWARE_STATE_PROP "pm-hardware-state"
437c478bd9Sstevel@tonic-gate #define PM_NEEDS_SUSPEND_RESUME "needs-suspend-resume"
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate * Global Driver Data
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate int ses_io_time = SES_IO_TIME;
507c478bd9Sstevel@tonic-gate
517c478bd9Sstevel@tonic-gate static int ses_retry_count = SES_RETRY_COUNT * SES_RETRY_MULTIPLIER;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #ifdef DEBUG
547c478bd9Sstevel@tonic-gate int ses_debug = 0;
557c478bd9Sstevel@tonic-gate #else /* DEBUG */
567c478bd9Sstevel@tonic-gate #define ses_debug 0
577c478bd9Sstevel@tonic-gate #endif /* DEBUG */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * External Enclosure Functions
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate extern int ses_softc_init(ses_softc_t *, int);
647c478bd9Sstevel@tonic-gate extern int ses_init_enc(ses_softc_t *);
657c478bd9Sstevel@tonic-gate extern int ses_get_encstat(ses_softc_t *, int);
667c478bd9Sstevel@tonic-gate extern int ses_set_encstat(ses_softc_t *, uchar_t, int);
677c478bd9Sstevel@tonic-gate extern int ses_get_objstat(ses_softc_t *, ses_objarg *, int);
687c478bd9Sstevel@tonic-gate extern int ses_set_objstat(ses_softc_t *, ses_objarg *, int);
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate extern int safte_softc_init(ses_softc_t *, int);
717c478bd9Sstevel@tonic-gate extern int safte_init_enc(ses_softc_t *);
727c478bd9Sstevel@tonic-gate extern int safte_get_encstat(ses_softc_t *, int);
737c478bd9Sstevel@tonic-gate extern int safte_set_encstat(ses_softc_t *, uchar_t, int);
747c478bd9Sstevel@tonic-gate extern int safte_get_objstat(ses_softc_t *, ses_objarg *, int);
757c478bd9Sstevel@tonic-gate extern int safte_set_objstat(ses_softc_t *, ses_objarg *, int);
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate extern int sen_softc_init(ses_softc_t *, int);
787c478bd9Sstevel@tonic-gate extern int sen_init_enc(ses_softc_t *);
797c478bd9Sstevel@tonic-gate extern int sen_get_encstat(ses_softc_t *, int);
807c478bd9Sstevel@tonic-gate extern int sen_set_encstat(ses_softc_t *, uchar_t, int);
817c478bd9Sstevel@tonic-gate extern int sen_get_objstat(ses_softc_t *, ses_objarg *, int);
827c478bd9Sstevel@tonic-gate extern int sen_set_objstat(ses_softc_t *, ses_objarg *, int);
837c478bd9Sstevel@tonic-gate
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate * Local Function prototypes
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate static int ses_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
887c478bd9Sstevel@tonic-gate static int ses_probe(dev_info_t *);
897c478bd9Sstevel@tonic-gate static int ses_attach(dev_info_t *, ddi_attach_cmd_t);
907c478bd9Sstevel@tonic-gate static int ses_detach(dev_info_t *, ddi_detach_cmd_t);
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate static int is_enc_dev(ses_softc_t *, struct scsi_inquiry *, int, enctyp *);
937c478bd9Sstevel@tonic-gate static int ses_doattach(dev_info_t *dip);
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate static int ses_open(dev_t *, int, int, cred_t *);
967c478bd9Sstevel@tonic-gate static int ses_close(dev_t, int, int, cred_t *);
977c478bd9Sstevel@tonic-gate static int ses_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate static encvec vecs[3] = {
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate ses_softc_init, ses_init_enc, ses_get_encstat,
1027c478bd9Sstevel@tonic-gate ses_set_encstat, ses_get_objstat, ses_set_objstat
1037c478bd9Sstevel@tonic-gate },
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate safte_softc_init, safte_init_enc, safte_get_encstat,
1067c478bd9Sstevel@tonic-gate safte_set_encstat, safte_get_objstat, safte_set_objstat,
1077c478bd9Sstevel@tonic-gate },
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate sen_softc_init, sen_init_enc, sen_get_encstat,
1107c478bd9Sstevel@tonic-gate sen_set_encstat, sen_get_objstat, sen_set_objstat
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate };
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate * Local Functions
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate static int ses_start(struct buf *bp);
1197c478bd9Sstevel@tonic-gate static int ses_decode_sense(struct scsi_pkt *pkt, int *err);
1207c478bd9Sstevel@tonic-gate
1217c478bd9Sstevel@tonic-gate static void ses_get_pkt(struct buf *bp, int (*func)(opaque_t));
1227c478bd9Sstevel@tonic-gate static void ses_callback(struct scsi_pkt *pkt);
1237c478bd9Sstevel@tonic-gate static void ses_restart(void *arg);
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * Local Static Data
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate #ifndef D_HOTPLUG
1307c478bd9Sstevel@tonic-gate #define D_HOTPLUG 0
1317c478bd9Sstevel@tonic-gate #endif /* D_HOTPLUG */
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate static struct cb_ops ses_cb_ops = {
1347c478bd9Sstevel@tonic-gate ses_open, /* open */
1357c478bd9Sstevel@tonic-gate ses_close, /* close */
1367c478bd9Sstevel@tonic-gate nodev, /* strategy */
1377c478bd9Sstevel@tonic-gate nodev, /* print */
1387c478bd9Sstevel@tonic-gate nodev, /* dump */
1397c478bd9Sstevel@tonic-gate nodev, /* read */
1407c478bd9Sstevel@tonic-gate nodev, /* write */
1417c478bd9Sstevel@tonic-gate ses_ioctl, /* ioctl */
1427c478bd9Sstevel@tonic-gate nodev, /* devmap */
1437c478bd9Sstevel@tonic-gate nodev, /* mmap */
1447c478bd9Sstevel@tonic-gate nodev, /* segmap */
1457c478bd9Sstevel@tonic-gate nochpoll, /* poll */
1467c478bd9Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */
1477c478bd9Sstevel@tonic-gate 0, /* streamtab */
1487c478bd9Sstevel@tonic-gate #if !defined(CB_REV)
1497c478bd9Sstevel@tonic-gate D_MP | D_NEW | D_HOTPLUG /* Driver compatibility flag */
1507c478bd9Sstevel@tonic-gate #else /* !defined(CB_REV) */
1517c478bd9Sstevel@tonic-gate D_MP | D_NEW | D_HOTPLUG, /* Driver compatibility flag */
1527c478bd9Sstevel@tonic-gate CB_REV, /* cb_ops version number */
1537c478bd9Sstevel@tonic-gate nodev, /* aread */
1547c478bd9Sstevel@tonic-gate nodev /* awrite */
1557c478bd9Sstevel@tonic-gate #endif /* !defined(CB_REV) */
1567c478bd9Sstevel@tonic-gate };
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate static struct dev_ops ses_dev_ops = {
1597c478bd9Sstevel@tonic-gate DEVO_REV, /* devo_rev, */
1607c478bd9Sstevel@tonic-gate 0, /* refcnt */
1617c478bd9Sstevel@tonic-gate ses_info, /* info */
1627c478bd9Sstevel@tonic-gate nulldev, /* identify */
1637c478bd9Sstevel@tonic-gate ses_probe, /* probe */
1647c478bd9Sstevel@tonic-gate ses_attach, /* attach */
1657c478bd9Sstevel@tonic-gate ses_detach, /* detach */
1667c478bd9Sstevel@tonic-gate nodev, /* reset */
1677c478bd9Sstevel@tonic-gate &ses_cb_ops, /* driver operations */
1687c478bd9Sstevel@tonic-gate (struct bus_ops *)NULL, /* bus operations */
16919397407SSherry Moore NULL, /* power */
17019397407SSherry Moore ddi_quiesce_not_needed, /* quiesce */
1717c478bd9Sstevel@tonic-gate };
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate static void *estate = NULL;
1747c478bd9Sstevel@tonic-gate static const char *Snm = "ses";
1757c478bd9Sstevel@tonic-gate static const char *Str = "%s\n";
1767c478bd9Sstevel@tonic-gate static const char *efl = "copyin/copyout EFAULT @ line %d";
1777c478bd9Sstevel@tonic-gate static const char *fail_msg = "%stransport failed: reason '%s': %s";
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * autoconfiguration routines.
1837c478bd9Sstevel@tonic-gate */
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
18619397407SSherry Moore &mod_driverops,
18719397407SSherry Moore "SCSI Enclosure Services",
18819397407SSherry Moore &ses_dev_ops
1897c478bd9Sstevel@tonic-gate };
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1927c478bd9Sstevel@tonic-gate MODREV_1, &modldrv, NULL
1937c478bd9Sstevel@tonic-gate };
1947c478bd9Sstevel@tonic-gate
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate int
_init(void)1977c478bd9Sstevel@tonic-gate _init(void)
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate int status;
2007c478bd9Sstevel@tonic-gate status = ddi_soft_state_init(&estate, sizeof (ses_softc_t), 0);
2017c478bd9Sstevel@tonic-gate if (status == 0) {
2027c478bd9Sstevel@tonic-gate if ((status = mod_install(&modlinkage)) != 0) {
2037c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&estate);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate return (status);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate int
_fini(void)2107c478bd9Sstevel@tonic-gate _fini(void)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate int status;
2137c478bd9Sstevel@tonic-gate if ((status = mod_remove(&modlinkage)) != 0) {
2147c478bd9Sstevel@tonic-gate return (status);
2157c478bd9Sstevel@tonic-gate }
2167c478bd9Sstevel@tonic-gate ddi_soft_state_fini(&estate);
2177c478bd9Sstevel@tonic-gate return (status);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate
2207c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2217c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate static int
ses_probe(dev_info_t * dip)2277c478bd9Sstevel@tonic-gate ses_probe(dev_info_t *dip)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate int err;
2307c478bd9Sstevel@tonic-gate struct scsi_device *devp;
2317c478bd9Sstevel@tonic-gate enctyp ep;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate * I finally figured out why we return success
2357c478bd9Sstevel@tonic-gate * on every probe. The devices that we attach to
2367c478bd9Sstevel@tonic-gate * don't all report as being the same "device type"
2377c478bd9Sstevel@tonic-gate *
2387c478bd9Sstevel@tonic-gate * 1) A5x00 -- report as Enclosure Services (0xD) SES
2397c478bd9Sstevel@tonic-gate * 2) A1000 -- report as Direct Access (0x0) SES
2407c478bd9Sstevel@tonic-gate * uses the same target as raid controler.
2417c478bd9Sstevel@tonic-gate * 3) D1000 -- report as processor (0x3) SAFTE
2427c478bd9Sstevel@tonic-gate * 3) D240 -- report as processor (0x3) SAFTE
2437c478bd9Sstevel@tonic-gate *
2447c478bd9Sstevel@tonic-gate * We also reportedly attach to SEN devices which I
2457c478bd9Sstevel@tonic-gate * believe reside in a Tobasco tray. I have never
2467c478bd9Sstevel@tonic-gate * been able to get one to attach.
2477c478bd9Sstevel@tonic-gate *
2487c478bd9Sstevel@tonic-gate */
2497c478bd9Sstevel@tonic-gate if (dip == NULL)
2507c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE);
2514c06356bSdh142964 /* SES_LOG(NULL, SES_CE_DEBUG1, "ses_probe: OK"); */
2524c06356bSdh142964 if (ddi_dev_is_sid(dip) == DDI_SUCCESS) {
2534c06356bSdh142964 return (DDI_PROBE_DONTCARE);
2544c06356bSdh142964 }
2554c06356bSdh142964
2564c06356bSdh142964 devp = ddi_get_driver_private(dip);
2574c06356bSdh142964
2584c06356bSdh142964 /* Legacy: prevent driver.conf specified ses nodes on atapi. */
2594c06356bSdh142964 if (scsi_ifgetcap(&devp->sd_address, "interconnect-type", -1) ==
2604c06356bSdh142964 INTERCONNECT_ATAPI)
2614c06356bSdh142964 return (DDI_PROBE_FAILURE);
2624c06356bSdh142964
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate * XXX: Breakage from the x86 folks.
2657c478bd9Sstevel@tonic-gate */
2667c478bd9Sstevel@tonic-gate if (strcmp(ddi_get_name(ddi_get_parent(dip)), "ata") == 0) {
2677c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE);
2687c478bd9Sstevel@tonic-gate }
2694c06356bSdh142964
2707c478bd9Sstevel@tonic-gate switch (err = scsi_probe(devp, SLEEP_FUNC)) {
2717c478bd9Sstevel@tonic-gate case SCSIPROBE_EXISTS:
2727c478bd9Sstevel@tonic-gate if (is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &ep)) {
2737c478bd9Sstevel@tonic-gate break;
2747c478bd9Sstevel@tonic-gate }
2757c478bd9Sstevel@tonic-gate /* FALLTHROUGH */
2767c478bd9Sstevel@tonic-gate case SCSIPROBE_NORESP:
2777c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
2787c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE);
2797c478bd9Sstevel@tonic-gate default:
2807c478bd9Sstevel@tonic-gate SES_LOG(NULL, SES_CE_DEBUG9,
2817c478bd9Sstevel@tonic-gate "ses_probe: probe error %d", err);
2827c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
2837c478bd9Sstevel@tonic-gate return (DDI_PROBE_FAILURE);
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
2867c478bd9Sstevel@tonic-gate return (DDI_PROBE_SUCCESS);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate static int
ses_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2907c478bd9Sstevel@tonic-gate ses_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate int inst, err;
2937c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip);
2967c478bd9Sstevel@tonic-gate switch (cmd) {
2977c478bd9Sstevel@tonic-gate case DDI_ATTACH:
2987c478bd9Sstevel@tonic-gate SES_LOG(NULL, SES_CE_DEBUG9, "ses_attach: DDI_ATTACH ses%d",
2997c478bd9Sstevel@tonic-gate inst);
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate err = ses_doattach(dip);
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate if (err == DDI_FAILURE) {
3047c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate SES_LOG(NULL, SES_CE_DEBUG4,
3077c478bd9Sstevel@tonic-gate "ses_attach: DDI_ATTACH OK ses%d", inst);
3087c478bd9Sstevel@tonic-gate break;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate case DDI_RESUME:
3117c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
3127c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "ses_attach: DDI_ATTACH ses%d",
3157c478bd9Sstevel@tonic-gate inst);
3167c478bd9Sstevel@tonic-gate ssc->ses_suspended = 0;
3177c478bd9Sstevel@tonic-gate break;
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate default:
3207c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate static int
is_enc_dev(ses_softc_t * ssc,struct scsi_inquiry * inqp,int iqlen,enctyp * ep)3267c478bd9Sstevel@tonic-gate is_enc_dev(ses_softc_t *ssc, struct scsi_inquiry *inqp, int iqlen, enctyp *ep)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate uchar_t dt = (inqp->inq_dtype & DTYPE_MASK);
3297c478bd9Sstevel@tonic-gate uchar_t *iqd = (uchar_t *)inqp;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate if (dt == DTYPE_ESI) {
3327c478bd9Sstevel@tonic-gate if (strncmp(inqp->inq_vid, SEN_ID, SEN_ID_LEN) == 0) {
3337c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "SEN device found");
3347c478bd9Sstevel@tonic-gate *ep = SEN_TYPE;
33524f1a99aSjmcp } else if (inqp->inq_rdf == RDF_SCSI2) {
33624f1a99aSjmcp /*
33724f1a99aSjmcp * Per SPC4 #6.4.2 Standard Inquiry Data, response
33824f1a99aSjmcp * data format (RDF) values of 0 and 1 are Obsolete,
33924f1a99aSjmcp * whereas values greater than 2 are Reserved
34024f1a99aSjmcp */
3417c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "SES device found");
3427c478bd9Sstevel@tonic-gate *ep = SES_TYPE;
3437c478bd9Sstevel@tonic-gate } else {
3447c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "Pre-SCSI3 SES device");
3457c478bd9Sstevel@tonic-gate *ep = SES_TYPE;
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate return (1);
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate if ((iqd[6] & 0x40) && inqp->inq_rdf >= RDF_SCSI2) {
3507c478bd9Sstevel@tonic-gate /*
3517c478bd9Sstevel@tonic-gate * PassThrough Device.
3527c478bd9Sstevel@tonic-gate */
3537c478bd9Sstevel@tonic-gate *ep = SES_TYPE;
3547c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "Passthru SES device");
3557c478bd9Sstevel@tonic-gate return (1);
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate if (iqlen < 47) {
3597c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE,
3607c478bd9Sstevel@tonic-gate "INQUIRY data too short to determine SAF-TE");
3617c478bd9Sstevel@tonic-gate return (0);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate if (strncmp((char *)&iqd[44], "SAF-TE", 4) == 0) {
3647c478bd9Sstevel@tonic-gate *ep = SAFT_TYPE;
3657c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "SAF-TE device found");
3667c478bd9Sstevel@tonic-gate return (1);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate return (0);
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate * Attach ses device.
3747c478bd9Sstevel@tonic-gate *
3757c478bd9Sstevel@tonic-gate * XXX: Power management is NOT supported. A token framework
3767c478bd9Sstevel@tonic-gate * is provided that will need to be extended assuming we have
3777c478bd9Sstevel@tonic-gate * ses devices we can power down. Currently, we don't have any.
3787c478bd9Sstevel@tonic-gate */
3797c478bd9Sstevel@tonic-gate static int
ses_doattach(dev_info_t * dip)3807c478bd9Sstevel@tonic-gate ses_doattach(dev_info_t *dip)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate int inst, err;
3837c478bd9Sstevel@tonic-gate Scsidevp devp;
3847c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
3857c478bd9Sstevel@tonic-gate enctyp etyp;
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip);
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate * Workaround for bug #4154979- for some reason we can
3907c478bd9Sstevel@tonic-gate * be called with identical instance numbers but for
3917c478bd9Sstevel@tonic-gate * different dev_info_t-s- all but one are bogus.
3927c478bd9Sstevel@tonic-gate *
3937c478bd9Sstevel@tonic-gate * Bad Dog! No Biscuit!
3947c478bd9Sstevel@tonic-gate *
3957c478bd9Sstevel@tonic-gate * A quick workaround might be to call ddi_soft_state_zalloc
3967c478bd9Sstevel@tonic-gate * unconditionally, as the implementation fails these calls
3977c478bd9Sstevel@tonic-gate * if there's an item already allocated. A more reasonable
3987c478bd9Sstevel@tonic-gate * and longer term change is to move the allocation past
3997c478bd9Sstevel@tonic-gate * the probe for the device's existence as most of these
4007c478bd9Sstevel@tonic-gate * 'bogus' calls are for nonexistent devices.
4017c478bd9Sstevel@tonic-gate */
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate devp = ddi_get_driver_private(dip);
4047c478bd9Sstevel@tonic-gate devp->sd_dev = dip;
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate /*
4077c478bd9Sstevel@tonic-gate * Determine whether the { i, t, l } we're called
4087c478bd9Sstevel@tonic-gate * to start is an enclosure services device.
4097c478bd9Sstevel@tonic-gate */
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate * Call the scsi_probe routine to see whether
4137c478bd9Sstevel@tonic-gate * we actually have an Enclosure Services device at
4147c478bd9Sstevel@tonic-gate * this address.
4157c478bd9Sstevel@tonic-gate */
4167c478bd9Sstevel@tonic-gate err = scsi_probe(devp, SLEEP_FUNC);
4177c478bd9Sstevel@tonic-gate if (err != SCSIPROBE_EXISTS) {
4187c478bd9Sstevel@tonic-gate SES_LOG(NULL, SES_CE_DEBUG9,
4197c478bd9Sstevel@tonic-gate "ses_doattach: probe error %d", err);
4207c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4217c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4227c478bd9Sstevel@tonic-gate }
4237c478bd9Sstevel@tonic-gate /* Call is_enc_dev() to get the etyp */
4247c478bd9Sstevel@tonic-gate if (!(is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &etyp))) {
4257c478bd9Sstevel@tonic-gate SES_LOG(NULL, CE_WARN,
4267c478bd9Sstevel@tonic-gate "ses_doattach: ses%d: is_enc_dev failure", inst);
4277c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4287c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate if (ddi_soft_state_zalloc(estate, inst) != DDI_SUCCESS) {
4327c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4337c478bd9Sstevel@tonic-gate SES_LOG(NULL, CE_NOTE, "ses%d: softalloc fails", inst);
4347c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate ssc = ddi_get_soft_state(estate, inst);
4377c478bd9Sstevel@tonic-gate if (ssc == NULL) {
4387c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4397c478bd9Sstevel@tonic-gate SES_LOG(NULL, CE_NOTE, "ses%d: get_soft_state fails", inst);
4407c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate devp->sd_private = (opaque_t)ssc;
4437c478bd9Sstevel@tonic-gate ssc->ses_devp = devp;
4447c478bd9Sstevel@tonic-gate err = ddi_create_minor_node(dip, "0", S_IFCHR, inst,
4457c478bd9Sstevel@tonic-gate DDI_NT_SCSI_ENCLOSURE, NULL);
4467c478bd9Sstevel@tonic-gate if (err == DDI_FAILURE) {
4477c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
4487c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "minor node creation failed");
4497c478bd9Sstevel@tonic-gate ddi_soft_state_free(estate, inst);
4507c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4517c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate ssc->ses_type = etyp;
4557c478bd9Sstevel@tonic-gate ssc->ses_vec = vecs[etyp];
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate /* Call SoftC Init Routine A bit later... */
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate ssc->ses_rqbp = scsi_alloc_consistent_buf(SES_ROUTE(ssc),
4600a2f1c3aSNikko He NULL, MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL);
4617c478bd9Sstevel@tonic-gate if (ssc->ses_rqbp != NULL) {
4627c478bd9Sstevel@tonic-gate ssc->ses_rqpkt = scsi_init_pkt(SES_ROUTE(ssc), NULL,
4637c478bd9Sstevel@tonic-gate ssc->ses_rqbp, CDB_GROUP0, 1, 0, PKT_CONSISTENT,
4647c478bd9Sstevel@tonic-gate SLEEP_FUNC, NULL);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate if (ssc->ses_rqbp == NULL || ssc->ses_rqpkt == NULL) {
4677c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
4687c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "scsi_init_pkt of rqbuf failed");
4697c478bd9Sstevel@tonic-gate if (ssc->ses_rqbp != NULL) {
4707c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(ssc->ses_rqbp);
4717c478bd9Sstevel@tonic-gate ssc->ses_rqbp = NULL;
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate ddi_soft_state_free(estate, inst);
4747c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
4757c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_private = (opaque_t)ssc;
4787c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_address = *(SES_ROUTE(ssc));
4797c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_comp = ses_callback;
4807c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_time = ses_io_time;
4817c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_flags = FLAG_NOPARITY|FLAG_NODISCON|FLAG_SENSING;
4827c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_cdbp[0] = SCMD_REQUEST_SENSE;
4837c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_cdbp[1] = 0;
4847c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_cdbp[2] = 0;
4857c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_cdbp[3] = 0;
4860a2f1c3aSNikko He ssc->ses_rqpkt->pkt_cdbp[4] = MAX_SENSE_LENGTH;
4877c478bd9Sstevel@tonic-gate ssc->ses_rqpkt->pkt_cdbp[5] = 0;
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate switch (scsi_ifgetcap(SES_ROUTE(ssc), "auto-rqsense", 1)) {
4907c478bd9Sstevel@tonic-gate case 1:
4917c478bd9Sstevel@tonic-gate /* if already set, don't reset it */
4927c478bd9Sstevel@tonic-gate ssc->ses_arq = 1;
4937c478bd9Sstevel@tonic-gate break;
4947c478bd9Sstevel@tonic-gate case 0:
4957c478bd9Sstevel@tonic-gate /* try and set it */
4967c478bd9Sstevel@tonic-gate ssc->ses_arq = ((scsi_ifsetcap(SES_ROUTE(ssc),
4977c478bd9Sstevel@tonic-gate "auto-rqsense", 1, 1) == 1) ? 1 : 0);
4987c478bd9Sstevel@tonic-gate break;
4997c478bd9Sstevel@tonic-gate default:
5007c478bd9Sstevel@tonic-gate /* probably undefined, so zero it out */
5017c478bd9Sstevel@tonic-gate ssc->ses_arq = 0;
5027c478bd9Sstevel@tonic-gate break;
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate ssc->ses_sbufp = getrbuf(KM_SLEEP);
5067c478bd9Sstevel@tonic-gate cv_init(&ssc->ses_sbufcv, NULL, CV_DRIVER, NULL);
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate * If the HBA supports wide, tell it to use wide.
5107c478bd9Sstevel@tonic-gate */
5117c478bd9Sstevel@tonic-gate if (scsi_ifgetcap(SES_ROUTE(ssc), "wide-xfer", 1) != -1) {
5127c478bd9Sstevel@tonic-gate int wd = ((devp->sd_inq->inq_rdf == RDF_SCSI2) &&
5137c478bd9Sstevel@tonic-gate (devp->sd_inq->inq_wbus16 || devp->sd_inq->inq_wbus32))
5147c478bd9Sstevel@tonic-gate ? 1 : 0;
5157c478bd9Sstevel@tonic-gate (void) scsi_ifsetcap(SES_ROUTE(ssc), "wide-xfer", wd, 1);
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Now do ssc init of enclosure specifics.
5207c478bd9Sstevel@tonic-gate * At the same time, check to make sure getrbuf
5217c478bd9Sstevel@tonic-gate * actually succeeded.
5227c478bd9Sstevel@tonic-gate */
52315e38525Srralphs if ((*ssc->ses_vec.softc_init)(ssc, 1)) {
52415e38525Srralphs SES_LOG(ssc, SES_CE_DEBUG3, "failed softc init");
52515e38525Srralphs (void) (*ssc->ses_vec.softc_init)(ssc, 0);
5267c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
5277c478bd9Sstevel@tonic-gate scsi_destroy_pkt(ssc->ses_rqpkt);
5287c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(ssc->ses_rqbp);
5297c478bd9Sstevel@tonic-gate if (ssc->ses_sbufp) {
5307c478bd9Sstevel@tonic-gate freerbuf(ssc->ses_sbufp);
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate cv_destroy(&ssc->ses_sbufcv);
5337c478bd9Sstevel@tonic-gate ddi_soft_state_free(estate, inst);
5347c478bd9Sstevel@tonic-gate scsi_unprobe(devp);
5357c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5367c478bd9Sstevel@tonic-gate }
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate /*
5397c478bd9Sstevel@tonic-gate * create this property so that PM code knows we want
5407c478bd9Sstevel@tonic-gate * to be suspended at PM time
5417c478bd9Sstevel@tonic-gate */
5427c478bd9Sstevel@tonic-gate (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
5437c478bd9Sstevel@tonic-gate PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate /* announce the existence of this device */
5467c478bd9Sstevel@tonic-gate ddi_report_dev(dip);
5477c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate /*
5527c478bd9Sstevel@tonic-gate * Detach ses device.
5537c478bd9Sstevel@tonic-gate *
5547c478bd9Sstevel@tonic-gate * XXX: Power management is NOT supported. A token framework
5557c478bd9Sstevel@tonic-gate * is provided that will need to be extended assuming we have
5567c478bd9Sstevel@tonic-gate * ses devices we can power down. Currently, we don't have any.
5577c478bd9Sstevel@tonic-gate */
5587c478bd9Sstevel@tonic-gate static int
ses_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)5597c478bd9Sstevel@tonic-gate ses_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
5627c478bd9Sstevel@tonic-gate int inst;
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate switch (cmd) {
5657c478bd9Sstevel@tonic-gate case DDI_DETACH:
5667c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip);
5677c478bd9Sstevel@tonic-gate ssc = ddi_get_soft_state(estate, inst);
5687c478bd9Sstevel@tonic-gate if (ssc == NULL) {
5697c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
5707c478bd9Sstevel@tonic-gate "ses%d: DDI_DETACH, no softstate found", inst);
5717c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate if (ISOPEN(ssc)) {
5747c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate #if !defined(lint)
5787c478bd9Sstevel@tonic-gate /* LINTED */
5797c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW);
5807c478bd9Sstevel@tonic-gate #endif /* !defined(lint) */
5817c478bd9Sstevel@tonic-gate
5827c478bd9Sstevel@tonic-gate if (ssc->ses_vec.softc_init)
5837c478bd9Sstevel@tonic-gate (void) (*ssc->ses_vec.softc_init)(ssc, 0);
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate #if !defined(lint)
5867c478bd9Sstevel@tonic-gate _NOTE(NO_COMPETING_THREADS_NOW);
5877c478bd9Sstevel@tonic-gate #endif /* !defined(lint) */
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate (void) scsi_ifsetcap(SES_ROUTE(ssc), "auto-rqsense", 1, 0);
5907c478bd9Sstevel@tonic-gate scsi_destroy_pkt(ssc->ses_rqpkt);
5917c478bd9Sstevel@tonic-gate scsi_free_consistent_buf(ssc->ses_rqbp);
5927c478bd9Sstevel@tonic-gate freerbuf(ssc->ses_sbufp);
5937c478bd9Sstevel@tonic-gate cv_destroy(&ssc->ses_sbufcv);
5947c478bd9Sstevel@tonic-gate ddi_soft_state_free(estate, inst);
5957c478bd9Sstevel@tonic-gate ddi_prop_remove_all(dip);
5967c478bd9Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
5977c478bd9Sstevel@tonic-gate scsi_unprobe(ddi_get_driver_private(dip));
5987c478bd9Sstevel@tonic-gate break;
5997c478bd9Sstevel@tonic-gate
6007c478bd9Sstevel@tonic-gate case DDI_SUSPEND:
6017c478bd9Sstevel@tonic-gate inst = ddi_get_instance(dip);
6027c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
6037c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE,
6047c478bd9Sstevel@tonic-gate "ses%d: DDI_SUSPEND, no softstate found", inst);
6057c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate /*
6097c478bd9Sstevel@tonic-gate * If driver idle, accept suspend request.
6107c478bd9Sstevel@tonic-gate * If it's busy, reject it. This keeps things simple!
6117c478bd9Sstevel@tonic-gate */
6127c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
6137c478bd9Sstevel@tonic-gate if (ssc->ses_sbufbsy) {
6147c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
6157c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate ssc->ses_suspended = 1;
6187c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
6197c478bd9Sstevel@tonic-gate break;
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate default:
6227c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6237c478bd9Sstevel@tonic-gate }
6247c478bd9Sstevel@tonic-gate return (DDI_SUCCESS);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate /* ARGSUSED */
6287c478bd9Sstevel@tonic-gate static int
ses_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)6297c478bd9Sstevel@tonic-gate ses_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate dev_t dev;
6327c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
6337c478bd9Sstevel@tonic-gate int inst, error;
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate switch (infocmd) {
6367c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO:
6377c478bd9Sstevel@tonic-gate dev = (dev_t)arg;
6387c478bd9Sstevel@tonic-gate inst = getminor(dev);
6397c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
6407c478bd9Sstevel@tonic-gate return (DDI_FAILURE);
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate *result = (void *) ssc->ses_devp->sd_dev;
6437c478bd9Sstevel@tonic-gate error = DDI_SUCCESS;
6447c478bd9Sstevel@tonic-gate break;
6457c478bd9Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE:
6467c478bd9Sstevel@tonic-gate dev = (dev_t)arg;
6477c478bd9Sstevel@tonic-gate inst = getminor(dev);
6487c478bd9Sstevel@tonic-gate *result = (void *)(uintptr_t)inst;
6497c478bd9Sstevel@tonic-gate error = DDI_SUCCESS;
6507c478bd9Sstevel@tonic-gate break;
6517c478bd9Sstevel@tonic-gate default:
6527c478bd9Sstevel@tonic-gate error = DDI_FAILURE;
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate return (error);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate
65719397407SSherry Moore
6587c478bd9Sstevel@tonic-gate /*
6597c478bd9Sstevel@tonic-gate * Unix Entry Points
6607c478bd9Sstevel@tonic-gate */
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate /* ARGSUSED */
6637c478bd9Sstevel@tonic-gate static int
ses_open(dev_t * dev_p,int flag,int otyp,cred_t * cred_p)6647c478bd9Sstevel@tonic-gate ses_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
6677c478bd9Sstevel@tonic-gate
6687c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, getminor(*dev_p))) == NULL) {
6697c478bd9Sstevel@tonic-gate return (ENXIO);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate * If the device is powered down, request it's activation.
6747c478bd9Sstevel@tonic-gate * If it can't be activated, fail open.
6757c478bd9Sstevel@tonic-gate */
6767c478bd9Sstevel@tonic-gate if (ssc->ses_suspended &&
6777c478bd9Sstevel@tonic-gate ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
6787c478bd9Sstevel@tonic-gate return (EIO);
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
6827c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR)
6837c478bd9Sstevel@tonic-gate ssc->ses_lyropen++;
6847c478bd9Sstevel@tonic-gate else
6857c478bd9Sstevel@tonic-gate ssc->ses_oflag = 1;
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate ssc->ses_present = (ssc->ses_present)? ssc->ses_present: SES_OPENING;
6887c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
6897c478bd9Sstevel@tonic-gate return (EOK);
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6937c478bd9Sstevel@tonic-gate static int
ses_close(dev_t dev,int flag,int otyp,cred_t * cred_p)6947c478bd9Sstevel@tonic-gate ses_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
6957c478bd9Sstevel@tonic-gate {
6967c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
6977c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL) {
6987c478bd9Sstevel@tonic-gate return (ENXIO);
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (ssc->ses_suspended) {
7027c478bd9Sstevel@tonic-gate (void) ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
7067c478bd9Sstevel@tonic-gate if (otyp == OTYP_LYR)
7077c478bd9Sstevel@tonic-gate ssc->ses_lyropen -= (ssc->ses_lyropen)? 1: 0;
7087c478bd9Sstevel@tonic-gate else
7097c478bd9Sstevel@tonic-gate ssc->ses_oflag = 0;
7107c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
7117c478bd9Sstevel@tonic-gate return (0);
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate /*ARGSUSED3*/
7167c478bd9Sstevel@tonic-gate static int
ses_ioctl(dev_t dev,int cmd,intptr_t arg,int flg,cred_t * cred_p,int * rvalp)7177c478bd9Sstevel@tonic-gate ses_ioctl(dev_t dev, int cmd, intptr_t arg, int flg, cred_t *cred_p, int *rvalp)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate ses_softc_t *ssc;
7207c478bd9Sstevel@tonic-gate ses_object k, *up;
7217c478bd9Sstevel@tonic-gate ses_objarg x;
7227c478bd9Sstevel@tonic-gate uchar_t t;
7237c478bd9Sstevel@tonic-gate uchar_t i;
7247c478bd9Sstevel@tonic-gate int rv = 0;
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL ||
7277c478bd9Sstevel@tonic-gate ssc->ses_present == SES_CLOSED) {
7287c478bd9Sstevel@tonic-gate return (ENXIO);
7297c478bd9Sstevel@tonic-gate }
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate
7327c478bd9Sstevel@tonic-gate switch (cmd) {
7337c478bd9Sstevel@tonic-gate case SESIOC_GETNOBJ:
7347c478bd9Sstevel@tonic-gate if (ddi_copyout(&ssc->ses_nobjects, (void *)arg,
7357c478bd9Sstevel@tonic-gate sizeof (int), flg)) {
7367c478bd9Sstevel@tonic-gate rv = EFAULT;
7377c478bd9Sstevel@tonic-gate break;
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate break;
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate case SESIOC_GETOBJMAP:
7427c478bd9Sstevel@tonic-gate up = (ses_object *) arg;
7437c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
7447c478bd9Sstevel@tonic-gate for (i = 0; i != ssc->ses_nobjects; i++) {
7457c478bd9Sstevel@tonic-gate k.obj_id = i;
7467c478bd9Sstevel@tonic-gate k.subencid = ssc->ses_objmap[i].subenclosure;
7477c478bd9Sstevel@tonic-gate k.elem_type = ssc->ses_objmap[i].enctype;
7487c478bd9Sstevel@tonic-gate if (ddi_copyout(&k, up, sizeof (k), flg)) {
7497c478bd9Sstevel@tonic-gate rv = EFAULT;
7507c478bd9Sstevel@tonic-gate break;
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate up++;
7537c478bd9Sstevel@tonic-gate }
7547c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
7557c478bd9Sstevel@tonic-gate break;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate case SESIOC_INIT:
7581cba8b6cSRandall Ralphs if (drv_priv(cred_p) != 0) {
7591cba8b6cSRandall Ralphs rv = EPERM;
7601cba8b6cSRandall Ralphs break;
7611cba8b6cSRandall Ralphs }
7627c478bd9Sstevel@tonic-gate rv = (*ssc->ses_vec.init_enc)(ssc);
7637c478bd9Sstevel@tonic-gate break;
7647c478bd9Sstevel@tonic-gate
7657c478bd9Sstevel@tonic-gate case SESIOC_GETENCSTAT:
7667c478bd9Sstevel@tonic-gate if ((ssc->ses_encstat & ENCI_SVALID) == 0) {
7677c478bd9Sstevel@tonic-gate rv = (*ssc->ses_vec.get_encstat)(ssc, KM_SLEEP);
7687c478bd9Sstevel@tonic-gate if (rv) {
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate t = ssc->ses_encstat & 0xf;
7737c478bd9Sstevel@tonic-gate if (ddi_copyout(&t, (void *)arg, sizeof (t), flg))
7747c478bd9Sstevel@tonic-gate rv = EFAULT;
7757c478bd9Sstevel@tonic-gate /*
7767c478bd9Sstevel@tonic-gate * And always invalidate enclosure status on the way out.
7777c478bd9Sstevel@tonic-gate */
7787c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
7797c478bd9Sstevel@tonic-gate ssc->ses_encstat &= ~ENCI_SVALID;
7807c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
7817c478bd9Sstevel@tonic-gate break;
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate case SESIOC_SETENCSTAT:
7841cba8b6cSRandall Ralphs if (drv_priv(cred_p) != 0) {
7851cba8b6cSRandall Ralphs rv = EPERM;
7861cba8b6cSRandall Ralphs break;
7871cba8b6cSRandall Ralphs }
7887c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &t, sizeof (t), flg))
7897c478bd9Sstevel@tonic-gate rv = EFAULT;
7907c478bd9Sstevel@tonic-gate else
7917c478bd9Sstevel@tonic-gate rv = (*ssc->ses_vec.set_encstat)(ssc, t, KM_SLEEP);
7927c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
7937c478bd9Sstevel@tonic-gate ssc->ses_encstat &= ~ENCI_SVALID;
7947c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
7957c478bd9Sstevel@tonic-gate break;
7967c478bd9Sstevel@tonic-gate
7977c478bd9Sstevel@tonic-gate case SESIOC_GETOBJSTAT:
7987c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
7997c478bd9Sstevel@tonic-gate rv = EFAULT;
8007c478bd9Sstevel@tonic-gate break;
8017c478bd9Sstevel@tonic-gate }
8027c478bd9Sstevel@tonic-gate if (x.obj_id >= ssc->ses_nobjects) {
8037c478bd9Sstevel@tonic-gate rv = EINVAL;
8047c478bd9Sstevel@tonic-gate break;
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate if ((rv = (*ssc->ses_vec.get_objstat)(ssc, &x, KM_SLEEP)) != 0)
8077c478bd9Sstevel@tonic-gate break;
8087c478bd9Sstevel@tonic-gate if (ddi_copyout(&x, (void *)arg, sizeof (x), flg))
8097c478bd9Sstevel@tonic-gate rv = EFAULT;
8107c478bd9Sstevel@tonic-gate else {
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate * Now that we no longer poll, svalid never stays true.
8137c478bd9Sstevel@tonic-gate */
8147c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
8157c478bd9Sstevel@tonic-gate ssc->ses_objmap[x.obj_id].svalid = 0;
8167c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
8177c478bd9Sstevel@tonic-gate }
8187c478bd9Sstevel@tonic-gate break;
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate case SESIOC_SETOBJSTAT:
8211cba8b6cSRandall Ralphs if (drv_priv(cred_p) != 0) {
8221cba8b6cSRandall Ralphs rv = EPERM;
8231cba8b6cSRandall Ralphs break;
8241cba8b6cSRandall Ralphs }
8257c478bd9Sstevel@tonic-gate if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
8267c478bd9Sstevel@tonic-gate rv = EFAULT;
8277c478bd9Sstevel@tonic-gate break;
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate if (x.obj_id >= ssc->ses_nobjects) {
8307c478bd9Sstevel@tonic-gate rv = EINVAL;
8317c478bd9Sstevel@tonic-gate break;
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate rv = (*ssc->ses_vec.set_objstat)(ssc, &x, KM_SLEEP);
8347c478bd9Sstevel@tonic-gate if (rv == 0) {
8357c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
8367c478bd9Sstevel@tonic-gate ssc->ses_objmap[x.obj_id].svalid = 0;
8377c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate break;
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate case USCSICMD:
8421cba8b6cSRandall Ralphs if (drv_priv(cred_p) != 0) {
8431cba8b6cSRandall Ralphs rv = EPERM;
8441cba8b6cSRandall Ralphs break;
8451cba8b6cSRandall Ralphs }
8466567eb0aSlh195018 rv = ses_uscsi_cmd(ssc, (Uscmd *)arg, flg);
8477c478bd9Sstevel@tonic-gate break;
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate default:
8507c478bd9Sstevel@tonic-gate rv = ENOTTY;
8517c478bd9Sstevel@tonic-gate break;
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate return (rv);
8547c478bd9Sstevel@tonic-gate }
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate /*
8587c478bd9Sstevel@tonic-gate * Loop on running a kernel based command
8597c478bd9Sstevel@tonic-gate *
8607c478bd9Sstevel@tonic-gate * FIXME: This routine is not really needed.
8617c478bd9Sstevel@tonic-gate */
8627c478bd9Sstevel@tonic-gate int
ses_runcmd(ses_softc_t * ssc,Uscmd * lp)8637c478bd9Sstevel@tonic-gate ses_runcmd(ses_softc_t *ssc, Uscmd *lp)
8647c478bd9Sstevel@tonic-gate {
8657c478bd9Sstevel@tonic-gate int e;
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate lp->uscsi_status = 0;
8686567eb0aSlh195018 e = ses_uscsi_cmd(ssc, lp, FKIOCTL);
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate #ifdef not
8717c478bd9Sstevel@tonic-gate /*
8727c478bd9Sstevel@tonic-gate * Debug: Nice cross-check code for verifying consistent status.
8737c478bd9Sstevel@tonic-gate */
8747c478bd9Sstevel@tonic-gate if (lp->uscsi_status) {
8757c478bd9Sstevel@tonic-gate if (lp->uscsi_status == STATUS_CHECK) {
8767c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
8777c478bd9Sstevel@tonic-gate "0x%x->%s ASC/ASCQ=0x%x/0x%x>",
8787c478bd9Sstevel@tonic-gate lp->uscsi_cdb[0],
8797c478bd9Sstevel@tonic-gate scsi_sname(lp->uscsi_rqbuf[2] & 0xf),
8807c478bd9Sstevel@tonic-gate lp->uscsi_rqbuf[12] & 0xff,
8817c478bd9Sstevel@tonic-gate lp->uscsi_rqbuf[13] & 0xff);
8827c478bd9Sstevel@tonic-gate } else {
8837c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
8847c478bd9Sstevel@tonic-gate "0x%x -> Status 0x%x", lp->uscsi_cdb[0],
8857c478bd9Sstevel@tonic-gate lp->uscsi_status);
8867c478bd9Sstevel@tonic-gate }
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate #endif /* not */
8897c478bd9Sstevel@tonic-gate return (e);
8907c478bd9Sstevel@tonic-gate }
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate
8937c478bd9Sstevel@tonic-gate /*
8947c478bd9Sstevel@tonic-gate * Run a scsi command.
8957c478bd9Sstevel@tonic-gate */
8967c478bd9Sstevel@tonic-gate int
ses_uscsi_cmd(ses_softc_t * ssc,Uscmd * Uc,int Uf)8976567eb0aSlh195018 ses_uscsi_cmd(ses_softc_t *ssc, Uscmd *Uc, int Uf)
8987c478bd9Sstevel@tonic-gate {
8996567eb0aSlh195018 Uscmd *uscmd;
9007c478bd9Sstevel@tonic-gate struct buf *bp;
9016567eb0aSlh195018 enum uio_seg uioseg;
9026567eb0aSlh195018 int err;
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate /*
9057c478bd9Sstevel@tonic-gate * Grab local 'special' buffer
9067c478bd9Sstevel@tonic-gate */
9077c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
9087c478bd9Sstevel@tonic-gate while (ssc->ses_sbufbsy) {
9097c478bd9Sstevel@tonic-gate cv_wait(&ssc->ses_sbufcv, &ssc->ses_devp->sd_mutex);
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate ssc->ses_sbufbsy = 1;
9127c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate /*
9157c478bd9Sstevel@tonic-gate * If the device is powered down, request it's activation.
9167c478bd9Sstevel@tonic-gate * This check must be done after setting ses_sbufbsy!
9177c478bd9Sstevel@tonic-gate */
9187c478bd9Sstevel@tonic-gate if (ssc->ses_suspended &&
9197c478bd9Sstevel@tonic-gate ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
9207c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
9217c478bd9Sstevel@tonic-gate ssc->ses_sbufbsy = 0;
9227c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
9237c478bd9Sstevel@tonic-gate return (EIO);
9247c478bd9Sstevel@tonic-gate }
9257c478bd9Sstevel@tonic-gate
9266567eb0aSlh195018 err = scsi_uscsi_alloc_and_copyin((intptr_t)Uc, Uf,
9276567eb0aSlh195018 SES_ROUTE(ssc), &uscmd);
9286567eb0aSlh195018 if (err != 0) {
9296567eb0aSlh195018 SES_LOG(ssc, SES_CE_DEBUG1, "ses_uscsi_cmd: "
9306567eb0aSlh195018 "scsi_uscsi_alloc_and_copyin failed\n");
9317c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
9327c478bd9Sstevel@tonic-gate ssc->ses_sbufbsy = 0;
9337c478bd9Sstevel@tonic-gate cv_signal(&ssc->ses_sbufcv);
9347c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
9357c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, efl, __LINE__);
9366567eb0aSlh195018 return (err);
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate /*
9406567eb0aSlh195018 * Copy the uscsi command related infos to ssc for use in ses_start()
9416567eb0aSlh195018 * and ses_callback().
9427c478bd9Sstevel@tonic-gate */
9436567eb0aSlh195018 bcopy(uscmd, &ssc->ses_uscsicmd, sizeof (Uscmd));
9446567eb0aSlh195018 if (uscmd->uscsi_cdb != NULL) {
9456567eb0aSlh195018 bcopy(uscmd->uscsi_cdb, &ssc->ses_srqcdb,
9466567eb0aSlh195018 (size_t)(uscmd->uscsi_cdblen));
9476567eb0aSlh195018 }
948275c9da8Seschrock ssc->ses_uscsicmd.uscsi_status = 0;
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate bp = ssc->ses_sbufp;
9517c478bd9Sstevel@tonic-gate bp->av_back = (struct buf *)NULL;
9527c478bd9Sstevel@tonic-gate bp->av_forw = (struct buf *)NULL;
9537c478bd9Sstevel@tonic-gate bp->b_back = (struct buf *)ssc;
9547c478bd9Sstevel@tonic-gate bp->b_edev = NODEV;
9557c478bd9Sstevel@tonic-gate
9566567eb0aSlh195018 if (uscmd->uscsi_cdb != NULL) {
9576567eb0aSlh195018 if (uscmd->uscsi_cdblen == CDB_GROUP0) {
9587c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG7,
9597c478bd9Sstevel@tonic-gate "scsi_cmd: %x %x %x %x %x %x",
9606567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[0],
9616567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[1],
9626567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[2],
9636567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[3],
9646567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[4],
9656567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[5]);
9667c478bd9Sstevel@tonic-gate } else {
9677c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG7,
9687c478bd9Sstevel@tonic-gate "scsi cmd: %x %x %x %x %x %x %x %x %x %x",
9696567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[0],
9706567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[1],
9716567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[2],
9726567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[3],
9736567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[4],
9746567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[5],
9756567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[6],
9766567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[7],
9776567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[8],
9786567eb0aSlh195018 ((char *)uscmd->uscsi_cdb)[9]);
9797c478bd9Sstevel@tonic-gate }
9807c478bd9Sstevel@tonic-gate }
9817c478bd9Sstevel@tonic-gate
9826567eb0aSlh195018 uioseg = (Uf & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
9836567eb0aSlh195018 err = scsi_uscsi_handle_cmd(NODEV, uioseg, uscmd,
9846567eb0aSlh195018 ses_start, bp, NULL);
9856567eb0aSlh195018
9867c478bd9Sstevel@tonic-gate /*
9876567eb0aSlh195018 * ses_callback() may set values for ssc->ses_uscsicmd or
9886567eb0aSlh195018 * ssc->ses_srqsbuf, so copy them back to uscmd.
9897c478bd9Sstevel@tonic-gate */
9906567eb0aSlh195018 if (uscmd->uscsi_rqbuf != NULL) {
9916567eb0aSlh195018 bcopy(&ssc->ses_srqsbuf, uscmd->uscsi_rqbuf,
9926567eb0aSlh195018 (size_t)(uscmd->uscsi_rqlen));
9936567eb0aSlh195018 uscmd->uscsi_rqresid = ssc->ses_uscsicmd.uscsi_rqresid;
9946567eb0aSlh195018 }
9956567eb0aSlh195018 uscmd->uscsi_status = ssc->ses_uscsicmd.uscsi_status;
9966567eb0aSlh195018
9976567eb0aSlh195018 (void) scsi_uscsi_copyout_and_free((intptr_t)Uc, uscmd);
9987c478bd9Sstevel@tonic-gate mutex_enter(SES_MUTEX);
9997c478bd9Sstevel@tonic-gate ssc->ses_sbufbsy = 0;
10007c478bd9Sstevel@tonic-gate cv_signal(&ssc->ses_sbufcv);
10017c478bd9Sstevel@tonic-gate mutex_exit(SES_MUTEX);
10027c478bd9Sstevel@tonic-gate
10037c478bd9Sstevel@tonic-gate return (err);
10047c478bd9Sstevel@tonic-gate }
10057c478bd9Sstevel@tonic-gate
10067c478bd9Sstevel@tonic-gate
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate /*
10097c478bd9Sstevel@tonic-gate * Command start and done functions.
10107c478bd9Sstevel@tonic-gate */
10117c478bd9Sstevel@tonic-gate static int
ses_start(struct buf * bp)10127c478bd9Sstevel@tonic-gate ses_start(struct buf *bp)
10137c478bd9Sstevel@tonic-gate {
10147c478bd9Sstevel@tonic-gate ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG9, "ses_start");
10177c478bd9Sstevel@tonic-gate if (!BP_PKT(bp)) {
10187c478bd9Sstevel@tonic-gate /*
10197c478bd9Sstevel@tonic-gate * Allocate a packet.
10207c478bd9Sstevel@tonic-gate */
10217c478bd9Sstevel@tonic-gate ses_get_pkt(bp, SLEEP_FUNC);
10227c478bd9Sstevel@tonic-gate if (!BP_PKT(bp)) {
10237c478bd9Sstevel@tonic-gate int err;
10247c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount;
10257c478bd9Sstevel@tonic-gate if (geterror(bp) == 0)
10267c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, EIO);
10277c478bd9Sstevel@tonic-gate err = geterror(bp);
10287c478bd9Sstevel@tonic-gate biodone(bp);
10297c478bd9Sstevel@tonic-gate return (err);
10307c478bd9Sstevel@tonic-gate }
10317c478bd9Sstevel@tonic-gate }
10327c478bd9Sstevel@tonic-gate
10337c478bd9Sstevel@tonic-gate /*
10347c478bd9Sstevel@tonic-gate * Initialize the transfer residue, error code, and retry count.
10357c478bd9Sstevel@tonic-gate */
10367c478bd9Sstevel@tonic-gate bp->b_resid = 0;
10377c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, 0);
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate #if !defined(lint)
10407c478bd9Sstevel@tonic-gate _NOTE(NO_COMPETING_THREADS_NOW);
10417c478bd9Sstevel@tonic-gate #endif /* !defined(lint) */
10427c478bd9Sstevel@tonic-gate ssc->ses_retries = ses_retry_count;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate #if !defined(lint)
10457c478bd9Sstevel@tonic-gate /* LINTED */
10467c478bd9Sstevel@tonic-gate _NOTE(COMPETING_THREADS_NOW);
10477c478bd9Sstevel@tonic-gate #endif /* !defined(lint) */
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG9, "ses_start -> scsi_transport");
10507c478bd9Sstevel@tonic-gate switch (scsi_transport(BP_PKT(bp))) {
10517c478bd9Sstevel@tonic-gate case TRAN_ACCEPT:
10527c478bd9Sstevel@tonic-gate return (0);
10537c478bd9Sstevel@tonic-gate /* break; */
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate case TRAN_BUSY:
10567c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2,
10577c478bd9Sstevel@tonic-gate "ses_start: TRANSPORT BUSY");
10587c478bd9Sstevel@tonic-gate SES_ENABLE_RESTART(SES_RESTART_TIME, BP_PKT(bp));
10597c478bd9Sstevel@tonic-gate return (0);
10607c478bd9Sstevel@tonic-gate /* break; */
10617c478bd9Sstevel@tonic-gate
10627c478bd9Sstevel@tonic-gate default:
10637c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG2, "TRANSPORT ERROR\n");
10647c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, EIO);
10657c478bd9Sstevel@tonic-gate scsi_destroy_pkt(BP_PKT(bp));
10667c478bd9Sstevel@tonic-gate SET_BP_PKT(bp, NULL);
10677c478bd9Sstevel@tonic-gate biodone(bp);
10687c478bd9Sstevel@tonic-gate return (EIO);
10697c478bd9Sstevel@tonic-gate /* break; */
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate }
10727c478bd9Sstevel@tonic-gate
10737c478bd9Sstevel@tonic-gate
10747c478bd9Sstevel@tonic-gate static void
ses_get_pkt(struct buf * bp,int (* func)())10757c478bd9Sstevel@tonic-gate ses_get_pkt(struct buf *bp, int (*func)())
10767c478bd9Sstevel@tonic-gate {
10777c478bd9Sstevel@tonic-gate ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
10787c478bd9Sstevel@tonic-gate Uscmd *scmd = &ssc->ses_uscsicmd;
10797c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt;
10800a2f1c3aSNikko He int stat_size = 1;
10810a2f1c3aSNikko He int flags = 0;
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate if ((scmd->uscsi_flags & USCSI_RQENABLE) && ssc->ses_arq) {
10840a2f1c3aSNikko He if (scmd->uscsi_rqlen > SENSE_LENGTH) {
10850a2f1c3aSNikko He stat_size = (int)(scmd->uscsi_rqlen) +
10860a2f1c3aSNikko He sizeof (struct scsi_arq_status) -
10870a2f1c3aSNikko He sizeof (struct scsi_extended_sense);
10880a2f1c3aSNikko He flags = PKT_XARQ;
10897c478bd9Sstevel@tonic-gate } else {
10900a2f1c3aSNikko He stat_size = sizeof (struct scsi_arq_status);
10910a2f1c3aSNikko He }
10927c478bd9Sstevel@tonic-gate }
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate if (bp->b_bcount) {
10957c478bd9Sstevel@tonic-gate pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, bp,
10960a2f1c3aSNikko He scmd->uscsi_cdblen, stat_size, 0, flags,
10970a2f1c3aSNikko He func, (caddr_t)ssc);
10987c478bd9Sstevel@tonic-gate } else {
10997c478bd9Sstevel@tonic-gate pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, NULL,
11000a2f1c3aSNikko He scmd->uscsi_cdblen, stat_size, 0, flags,
11010a2f1c3aSNikko He func, (caddr_t)ssc);
11027c478bd9Sstevel@tonic-gate }
11037c478bd9Sstevel@tonic-gate SET_BP_PKT(bp, pkt);
11047c478bd9Sstevel@tonic-gate if (pkt == (struct scsi_pkt *)NULL)
11057c478bd9Sstevel@tonic-gate return;
11067c478bd9Sstevel@tonic-gate bcopy(scmd->uscsi_cdb, pkt->pkt_cdbp, (size_t)scmd->uscsi_cdblen);
1107*ffc5bd0fSKevin Crowe
1108*ffc5bd0fSKevin Crowe /* Set an upper bound timeout of ses_io_time if zero is passed in */
1109*ffc5bd0fSKevin Crowe pkt->pkt_time = (scmd->uscsi_timeout == 0) ?
1110*ffc5bd0fSKevin Crowe ses_io_time : scmd->uscsi_timeout;
11117c478bd9Sstevel@tonic-gate
11127c478bd9Sstevel@tonic-gate pkt->pkt_comp = ses_callback;
11137c478bd9Sstevel@tonic-gate pkt->pkt_private = (opaque_t)ssc;
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /*
11187c478bd9Sstevel@tonic-gate * Restart ses command.
11197c478bd9Sstevel@tonic-gate */
11207c478bd9Sstevel@tonic-gate static void
ses_restart(void * arg)11217c478bd9Sstevel@tonic-gate ses_restart(void *arg)
11227c478bd9Sstevel@tonic-gate {
11237c478bd9Sstevel@tonic-gate struct scsi_pkt *pkt = (struct scsi_pkt *)arg;
11247c478bd9Sstevel@tonic-gate ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
11257c478bd9Sstevel@tonic-gate struct buf *bp = ssc->ses_sbufp;
11267c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG9, "ses_restart");
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate ssc->ses_restart_id = NULL;
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate switch (scsi_transport(pkt)) {
11317c478bd9Sstevel@tonic-gate case TRAN_ACCEPT:
11327c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG9,
11337c478bd9Sstevel@tonic-gate "RESTART %d ok", ssc->ses_retries);
11347c478bd9Sstevel@tonic-gate return;
11357c478bd9Sstevel@tonic-gate /* break; */
11367c478bd9Sstevel@tonic-gate case TRAN_BUSY:
11377c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1,
11387c478bd9Sstevel@tonic-gate "RESTART %d TRANSPORT BUSY\n", ssc->ses_retries);
11397c478bd9Sstevel@tonic-gate if (ssc->ses_retries > SES_NO_RETRY) {
11407c478bd9Sstevel@tonic-gate ssc->ses_retries -= SES_BUSY_RETRY;
11417c478bd9Sstevel@tonic-gate SES_ENABLE_RESTART(SES_RESTART_TIME, pkt);
11427c478bd9Sstevel@tonic-gate return;
11437c478bd9Sstevel@tonic-gate }
11447c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, EBUSY);
11457c478bd9Sstevel@tonic-gate break;
11467c478bd9Sstevel@tonic-gate default:
11477c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, EIO);
11487c478bd9Sstevel@tonic-gate break;
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1,
11517c478bd9Sstevel@tonic-gate "RESTART %d TRANSPORT FAILED\n", ssc->ses_retries);
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate pkt = (struct scsi_pkt *)bp->av_back;
11547c478bd9Sstevel@tonic-gate scsi_destroy_pkt(pkt);
11557c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount;
11567c478bd9Sstevel@tonic-gate SET_BP_PKT(bp, NULL);
11577c478bd9Sstevel@tonic-gate biodone(bp);
11587c478bd9Sstevel@tonic-gate }
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate /*
11627c478bd9Sstevel@tonic-gate * Command completion processing
11637c478bd9Sstevel@tonic-gate */
11647c478bd9Sstevel@tonic-gate #define HBA_RESET (STAT_BUS_RESET|STAT_DEV_RESET|STAT_ABORTED)
11657c478bd9Sstevel@tonic-gate static void
ses_callback(struct scsi_pkt * pkt)11667c478bd9Sstevel@tonic-gate ses_callback(struct scsi_pkt *pkt)
11677c478bd9Sstevel@tonic-gate {
11687c478bd9Sstevel@tonic-gate ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
11697c478bd9Sstevel@tonic-gate struct buf *bp;
11707c478bd9Sstevel@tonic-gate Uscmd *scmd;
11717c478bd9Sstevel@tonic-gate int err;
11727c478bd9Sstevel@tonic-gate char action;
11737c478bd9Sstevel@tonic-gate
11747c478bd9Sstevel@tonic-gate bp = ssc->ses_sbufp;
11757c478bd9Sstevel@tonic-gate scmd = &ssc->ses_uscsicmd;
11767c478bd9Sstevel@tonic-gate /* SES_LOG(ssc, SES_CE_DEBUG9, "ses_callback"); */
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate /*
11797c478bd9Sstevel@tonic-gate * Optimization: Normal completion.
11807c478bd9Sstevel@tonic-gate */
11817c478bd9Sstevel@tonic-gate if (pkt->pkt_reason == CMD_CMPLT &&
11827c478bd9Sstevel@tonic-gate !SCBP_C(pkt) &&
11837c478bd9Sstevel@tonic-gate !(pkt->pkt_flags & FLAG_SENSING) &&
1184bf82a41bSeschrock !pkt->pkt_resid) {
11857c478bd9Sstevel@tonic-gate scsi_destroy_pkt(pkt);
11867c478bd9Sstevel@tonic-gate SET_BP_PKT(bp, NULL);
11877c478bd9Sstevel@tonic-gate biodone(bp);
11887c478bd9Sstevel@tonic-gate return;
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate
11927c478bd9Sstevel@tonic-gate /*
11937c478bd9Sstevel@tonic-gate * Abnormal completion.
11947c478bd9Sstevel@tonic-gate *
11957c478bd9Sstevel@tonic-gate * Assume most common error initially.
11967c478bd9Sstevel@tonic-gate */
11977c478bd9Sstevel@tonic-gate err = EIO;
11987c478bd9Sstevel@tonic-gate action = COMMAND_DONE;
11997c478bd9Sstevel@tonic-gate if (scmd->uscsi_flags & USCSI_DIAGNOSE) {
12007c478bd9Sstevel@tonic-gate ssc->ses_retries = SES_NO_RETRY;
12017c478bd9Sstevel@tonic-gate }
12027c478bd9Sstevel@tonic-gate
12037c478bd9Sstevel@tonic-gate CHECK_PKT:
12047c478bd9Sstevel@tonic-gate if (pkt->pkt_reason != CMD_CMPLT) {
12057c478bd9Sstevel@tonic-gate /* Process transport errors. */
12067c478bd9Sstevel@tonic-gate switch (pkt->pkt_reason) {
12077c478bd9Sstevel@tonic-gate case CMD_TIMEOUT:
12087c478bd9Sstevel@tonic-gate /*
12097c478bd9Sstevel@tonic-gate * If the transport layer didn't clear the problem,
12107c478bd9Sstevel@tonic-gate * reset the target.
12117c478bd9Sstevel@tonic-gate */
12127c478bd9Sstevel@tonic-gate if (! (pkt->pkt_statistics & HBA_RESET)) {
1213275c9da8Seschrock (void) scsi_reset(&pkt->pkt_address,
1214275c9da8Seschrock RESET_TARGET);
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate err = ETIMEDOUT;
12177c478bd9Sstevel@tonic-gate break;
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate case CMD_INCOMPLETE:
12207c478bd9Sstevel@tonic-gate case CMD_UNX_BUS_FREE:
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate * No response? If probing, give up.
12237c478bd9Sstevel@tonic-gate * Otherwise, keep trying until retries exhausted.
12247c478bd9Sstevel@tonic-gate * Then lockdown the driver as the device is
12257c478bd9Sstevel@tonic-gate * unplugged.
12267c478bd9Sstevel@tonic-gate */
12277c478bd9Sstevel@tonic-gate if (ssc->ses_retries <= SES_NO_RETRY &&
12287c478bd9Sstevel@tonic-gate !(scmd->uscsi_flags & USCSI_DIAGNOSE)) {
12297c478bd9Sstevel@tonic-gate ssc->ses_present = SES_CLOSED;
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate /* Inhibit retries to speed probe/attach. */
12327c478bd9Sstevel@tonic-gate if (ssc->ses_present < SES_OPEN) {
12337c478bd9Sstevel@tonic-gate ssc->ses_retries = SES_NO_RETRY;
12347c478bd9Sstevel@tonic-gate }
12357c478bd9Sstevel@tonic-gate /* SES_CMD_RETRY4(ssc->ses_retries); */
12367c478bd9Sstevel@tonic-gate err = ENXIO;
12377c478bd9Sstevel@tonic-gate break;
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate case CMD_DATA_OVR:
12407c478bd9Sstevel@tonic-gate /*
12417c478bd9Sstevel@tonic-gate * XXX: Some HBA's (e.g. Adaptec 1740 and
12427c478bd9Sstevel@tonic-gate * earlier ISP revs) report a DATA OVERRUN
12437c478bd9Sstevel@tonic-gate * error instead of a transfer residue. So,
12447c478bd9Sstevel@tonic-gate * we convert the error and restart.
12457c478bd9Sstevel@tonic-gate */
12467c478bd9Sstevel@tonic-gate if ((bp->b_bcount - pkt->pkt_resid) > 0) {
12477c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG6,
12487c478bd9Sstevel@tonic-gate "ignoring overrun");
12497c478bd9Sstevel@tonic-gate pkt->pkt_reason = CMD_CMPLT;
12507c478bd9Sstevel@tonic-gate err = EOK;
12517c478bd9Sstevel@tonic-gate goto CHECK_PKT;
12527c478bd9Sstevel@tonic-gate }
12537c478bd9Sstevel@tonic-gate ssc->ses_retries = SES_NO_RETRY;
12547c478bd9Sstevel@tonic-gate /* err = EIO; */
12557c478bd9Sstevel@tonic-gate break;
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate case CMD_DMA_DERR:
12587c478bd9Sstevel@tonic-gate ssc->ses_retries = SES_NO_RETRY;
12597c478bd9Sstevel@tonic-gate err = EFAULT;
12607c478bd9Sstevel@tonic-gate break;
12617c478bd9Sstevel@tonic-gate
12627c478bd9Sstevel@tonic-gate default:
12637c478bd9Sstevel@tonic-gate /* err = EIO; */
12647c478bd9Sstevel@tonic-gate break;
12657c478bd9Sstevel@tonic-gate }
12667c478bd9Sstevel@tonic-gate if (pkt == ssc->ses_rqpkt) {
12677c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_WARN, fail_msg,
12687c478bd9Sstevel@tonic-gate "Request Sense ",
12697c478bd9Sstevel@tonic-gate scsi_rname(pkt->pkt_reason),
12707c478bd9Sstevel@tonic-gate (ssc->ses_retries > 0)?
12717c478bd9Sstevel@tonic-gate "retrying": "giving up");
12727c478bd9Sstevel@tonic-gate pkt = (struct scsi_pkt *)bp->av_back;
12737c478bd9Sstevel@tonic-gate action = QUE_SENSE;
12747c478bd9Sstevel@tonic-gate } else {
12757c478bd9Sstevel@tonic-gate SES_LOG(ssc, CE_WARN, fail_msg,
12767c478bd9Sstevel@tonic-gate "", scsi_rname(pkt->pkt_reason),
12777c478bd9Sstevel@tonic-gate (ssc->ses_retries > 0)?
12787c478bd9Sstevel@tonic-gate "retrying": "giving up");
12797c478bd9Sstevel@tonic-gate action = QUE_COMMAND;
12807c478bd9Sstevel@tonic-gate }
12817c478bd9Sstevel@tonic-gate /* Device exists, allow full error recovery. */
12827c478bd9Sstevel@tonic-gate if (ssc->ses_retries > SES_NO_RETRY) {
12837c478bd9Sstevel@tonic-gate ssc->ses_present = SES_OPEN;
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate
12877c478bd9Sstevel@tonic-gate /*
12887c478bd9Sstevel@tonic-gate * Process status and sense data errors.
12897c478bd9Sstevel@tonic-gate */
12907c478bd9Sstevel@tonic-gate } else {
12917c478bd9Sstevel@tonic-gate ssc->ses_present = SES_OPEN;
12927c478bd9Sstevel@tonic-gate action = ses_decode_sense(pkt, &err);
12937c478bd9Sstevel@tonic-gate }
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate /*
12977c478bd9Sstevel@tonic-gate * Initiate error recovery action, as needed.
12987c478bd9Sstevel@tonic-gate */
12997c478bd9Sstevel@tonic-gate switch (action) {
13007c478bd9Sstevel@tonic-gate case QUE_COMMAND_NOW:
13017c478bd9Sstevel@tonic-gate /* SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd now"); */
13027c478bd9Sstevel@tonic-gate if (ssc->ses_retries > SES_NO_RETRY) {
13037c478bd9Sstevel@tonic-gate ssc->ses_retries -= SES_CMD_RETRY;
13047c478bd9Sstevel@tonic-gate scmd->uscsi_status = 0;
13057c478bd9Sstevel@tonic-gate if (ssc->ses_arq)
1306275c9da8Seschrock bzero(pkt->pkt_scbp,
1307275c9da8Seschrock sizeof (struct scsi_arq_status));
13087c478bd9Sstevel@tonic-gate
13097c478bd9Sstevel@tonic-gate if (scsi_transport((struct scsi_pkt *)bp->av_back)
13107c478bd9Sstevel@tonic-gate != TRAN_ACCEPT) {
13117c478bd9Sstevel@tonic-gate SES_ENABLE_RESTART(SES_RESTART_TIME,
13127c478bd9Sstevel@tonic-gate (struct scsi_pkt *)bp->av_back);
13137c478bd9Sstevel@tonic-gate }
13147c478bd9Sstevel@tonic-gate return;
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate break;
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate case QUE_COMMAND:
13197c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd");
13207c478bd9Sstevel@tonic-gate if (ssc->ses_retries > SES_NO_RETRY) {
13217c478bd9Sstevel@tonic-gate ssc->ses_retries -=
13227c478bd9Sstevel@tonic-gate (err == EBUSY)? SES_BUSY_RETRY: SES_CMD_RETRY;
13237c478bd9Sstevel@tonic-gate scmd->uscsi_status = 0;
13247c478bd9Sstevel@tonic-gate if (ssc->ses_arq)
1325275c9da8Seschrock bzero(pkt->pkt_scbp,
1326275c9da8Seschrock sizeof (struct scsi_arq_status));
13277c478bd9Sstevel@tonic-gate
13287c478bd9Sstevel@tonic-gate SES_ENABLE_RESTART(
13297c478bd9Sstevel@tonic-gate (err == EBUSY)? SES_BUSY_TIME: SES_RESTART_TIME,
13307c478bd9Sstevel@tonic-gate (struct scsi_pkt *)bp->av_back);
13317c478bd9Sstevel@tonic-gate return;
13327c478bd9Sstevel@tonic-gate }
13337c478bd9Sstevel@tonic-gate break;
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate case QUE_SENSE:
13367c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "retrying sense");
13377c478bd9Sstevel@tonic-gate if (ssc->ses_retries > SES_NO_RETRY) {
13387c478bd9Sstevel@tonic-gate ssc->ses_retries -= SES_SENSE_RETRY;
13397c478bd9Sstevel@tonic-gate scmd->uscsi_status = 0;
13400a2f1c3aSNikko He bzero(&ssc->ses_srqsbuf, MAX_SENSE_LENGTH);
13417c478bd9Sstevel@tonic-gate
13427c478bd9Sstevel@tonic-gate if (scsi_transport(ssc->ses_rqpkt) != TRAN_ACCEPT) {
13437c478bd9Sstevel@tonic-gate SES_ENABLE_RESTART(SES_RESTART_TIME,
13447c478bd9Sstevel@tonic-gate ssc->ses_rqpkt);
13457c478bd9Sstevel@tonic-gate }
13467c478bd9Sstevel@tonic-gate return;
13477c478bd9Sstevel@tonic-gate }
13487c478bd9Sstevel@tonic-gate break;
13497c478bd9Sstevel@tonic-gate
13507c478bd9Sstevel@tonic-gate case COMMAND_DONE:
13517c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG4, "cmd done");
13527c478bd9Sstevel@tonic-gate pkt = (struct scsi_pkt *)bp->av_back;
13537c478bd9Sstevel@tonic-gate bp->b_resid = pkt->pkt_resid;
13547c478bd9Sstevel@tonic-gate if (bp->b_resid) {
13557c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG6,
13567c478bd9Sstevel@tonic-gate "transfer residue %ld(%ld)",
13577c478bd9Sstevel@tonic-gate bp->b_bcount - bp->b_resid, bp->b_bcount);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate break;
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate pkt = (struct scsi_pkt *)bp->av_back;
13627c478bd9Sstevel@tonic-gate if (err) {
13637c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "SES: ERROR %d\n", err);
13647c478bd9Sstevel@tonic-gate SET_BP_ERROR(bp, err);
13657c478bd9Sstevel@tonic-gate bp->b_resid = bp->b_bcount;
13667c478bd9Sstevel@tonic-gate }
13677c478bd9Sstevel@tonic-gate scsi_destroy_pkt(pkt);
13687c478bd9Sstevel@tonic-gate SET_BP_PKT(bp, NULL);
13697c478bd9Sstevel@tonic-gate biodone(bp);
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate * Check status and sense data and determine recovery.
13757c478bd9Sstevel@tonic-gate */
13767c478bd9Sstevel@tonic-gate static int
ses_decode_sense(struct scsi_pkt * pkt,int * err)13777c478bd9Sstevel@tonic-gate ses_decode_sense(struct scsi_pkt *pkt, int *err)
13787c478bd9Sstevel@tonic-gate {
13797c478bd9Sstevel@tonic-gate ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
13807c478bd9Sstevel@tonic-gate struct scsi_extended_sense *sense =
13817c478bd9Sstevel@tonic-gate (struct scsi_extended_sense *)&ssc->ses_srqsbuf;
13827c478bd9Sstevel@tonic-gate Uscmd *scmd = &ssc->ses_uscsicmd;
13837c478bd9Sstevel@tonic-gate char sense_flag = 0;
13847c478bd9Sstevel@tonic-gate uchar_t status = SCBP_C(pkt) & STATUS_MASK;
13857c478bd9Sstevel@tonic-gate char *err_action;
13867c478bd9Sstevel@tonic-gate char action;
13870a2f1c3aSNikko He uchar_t rqlen;
13880a2f1c3aSNikko He int amt;
13897c478bd9Sstevel@tonic-gate
13907c478bd9Sstevel@tonic-gate /*
13917c478bd9Sstevel@tonic-gate * Process manual request sense.
13927c478bd9Sstevel@tonic-gate * Copy manual request sense to sense buffer.
13937c478bd9Sstevel@tonic-gate *
13947c478bd9Sstevel@tonic-gate * This is done if auto request sense is not enabled.
13957c478bd9Sstevel@tonic-gate * Or the auto request sense failed and the request
13967c478bd9Sstevel@tonic-gate * sense needs to be retried.
13977c478bd9Sstevel@tonic-gate */
13987c478bd9Sstevel@tonic-gate if (pkt->pkt_flags & FLAG_SENSING) {
13997c478bd9Sstevel@tonic-gate struct buf *sbp = ssc->ses_rqbp;
14000a2f1c3aSNikko He amt = min(MAX_SENSE_LENGTH,
14017c478bd9Sstevel@tonic-gate sbp->b_bcount - sbp->b_resid);
14020a2f1c3aSNikko He rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
14030a2f1c3aSNikko He bcopy(sbp->b_un.b_addr, sense, rqlen);
14040a2f1c3aSNikko He scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
14057c478bd9Sstevel@tonic-gate sense_flag = 1;
14067c478bd9Sstevel@tonic-gate /*
14077c478bd9Sstevel@tonic-gate * Process auto request sense.
14087c478bd9Sstevel@tonic-gate * Copy auto request sense to sense buffer.
14097c478bd9Sstevel@tonic-gate *
14107c478bd9Sstevel@tonic-gate * If auto request sense failed due to transport error,
14117c478bd9Sstevel@tonic-gate * retry the command. Otherwise process the status and
14127c478bd9Sstevel@tonic-gate * sense data.
14137c478bd9Sstevel@tonic-gate */
14147c478bd9Sstevel@tonic-gate } else if (ssc->ses_arq && pkt->pkt_state & STATE_ARQ_DONE) {
14157c478bd9Sstevel@tonic-gate struct scsi_arq_status *arq =
14167c478bd9Sstevel@tonic-gate (struct scsi_arq_status *)(pkt->pkt_scbp);
14177c478bd9Sstevel@tonic-gate uchar_t *arq_status = (uchar_t *)&arq->sts_rqpkt_status;
14180a2f1c3aSNikko He if (pkt->pkt_state & STATE_XARQ_DONE) {
14190a2f1c3aSNikko He amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
14200a2f1c3aSNikko He } else {
14210a2f1c3aSNikko He if (arq->sts_rqpkt_resid > SENSE_LENGTH) {
14220a2f1c3aSNikko He amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
14230a2f1c3aSNikko He } else {
14240a2f1c3aSNikko He amt = SENSE_LENGTH - arq->sts_rqpkt_resid;
14250a2f1c3aSNikko He }
14260a2f1c3aSNikko He }
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate if (arq->sts_rqpkt_reason != CMD_CMPLT) {
14297c478bd9Sstevel@tonic-gate return (QUE_COMMAND);
14307c478bd9Sstevel@tonic-gate }
14310a2f1c3aSNikko He
14320a2f1c3aSNikko He rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
14330a2f1c3aSNikko He bcopy(&arq->sts_sensedata, sense, rqlen);
14347c478bd9Sstevel@tonic-gate scmd->uscsi_status = status;
14350a2f1c3aSNikko He scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
14367c478bd9Sstevel@tonic-gate status = *arq_status & STATUS_MASK;
14377c478bd9Sstevel@tonic-gate pkt->pkt_state &= ~STATE_ARQ_DONE;
14387c478bd9Sstevel@tonic-gate sense_flag = 1;
14397c478bd9Sstevel@tonic-gate }
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate /*
14437c478bd9Sstevel@tonic-gate * Check status of REQUEST SENSE or command.
14447c478bd9Sstevel@tonic-gate *
14457c478bd9Sstevel@tonic-gate * If it's not successful, try retrying the original command
14467c478bd9Sstevel@tonic-gate * and hope that it goes away. If not, we'll eventually run
14477c478bd9Sstevel@tonic-gate * out of retries and die.
14487c478bd9Sstevel@tonic-gate */
14497c478bd9Sstevel@tonic-gate switch (status) {
14507c478bd9Sstevel@tonic-gate case STATUS_GOOD:
14517c478bd9Sstevel@tonic-gate case STATUS_INTERMEDIATE:
14527c478bd9Sstevel@tonic-gate case STATUS_MET:
14537c478bd9Sstevel@tonic-gate /*
14547c478bd9Sstevel@tonic-gate * If the command status is ok, we're done.
14557c478bd9Sstevel@tonic-gate * Otherwise, examine the request sense data.
14567c478bd9Sstevel@tonic-gate */
14577c478bd9Sstevel@tonic-gate if (! sense_flag) {
14587c478bd9Sstevel@tonic-gate *err = EOK;
14597c478bd9Sstevel@tonic-gate return (COMMAND_DONE);
14607c478bd9Sstevel@tonic-gate }
14617c478bd9Sstevel@tonic-gate break;
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate case STATUS_CHECK:
14647c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "status decode: check");
14657c478bd9Sstevel@tonic-gate *err = EIO;
14667c478bd9Sstevel@tonic-gate return (QUE_SENSE);
14677c478bd9Sstevel@tonic-gate /* break; */
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate case STATUS_BUSY:
14707c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "status decode: busy");
14717c478bd9Sstevel@tonic-gate /* SES_CMD_RETRY2(ssc->ses_retries); */
14727c478bd9Sstevel@tonic-gate *err = EBUSY;
14737c478bd9Sstevel@tonic-gate return (QUE_COMMAND);
14747c478bd9Sstevel@tonic-gate /* break; */
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate case STATUS_RESERVATION_CONFLICT:
14777c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "status decode: reserved");
14787c478bd9Sstevel@tonic-gate *err = EACCES;
14797c478bd9Sstevel@tonic-gate return (COMMAND_DONE_ERROR);
14807c478bd9Sstevel@tonic-gate /* break; */
14817c478bd9Sstevel@tonic-gate
14827c478bd9Sstevel@tonic-gate case STATUS_TERMINATED:
14837c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "status decode: terminated");
14847c478bd9Sstevel@tonic-gate *err = ECANCELED;
14857c478bd9Sstevel@tonic-gate return (COMMAND_DONE_ERROR);
14867c478bd9Sstevel@tonic-gate /* break; */
14877c478bd9Sstevel@tonic-gate
14887c478bd9Sstevel@tonic-gate default:
14897c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1, "status 0x%x", status);
14907c478bd9Sstevel@tonic-gate *err = EIO;
14917c478bd9Sstevel@tonic-gate return (QUE_COMMAND);
14927c478bd9Sstevel@tonic-gate /* break; */
14937c478bd9Sstevel@tonic-gate }
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate /*
14977c478bd9Sstevel@tonic-gate * Check REQUEST SENSE error code.
14987c478bd9Sstevel@tonic-gate *
14997c478bd9Sstevel@tonic-gate * Either there's no error, a retryable error,
15007c478bd9Sstevel@tonic-gate * or it's dead. SES devices aren't very complex.
15017c478bd9Sstevel@tonic-gate */
15027c478bd9Sstevel@tonic-gate err_action = "retrying";
15037c478bd9Sstevel@tonic-gate switch (sense->es_key) {
15047c478bd9Sstevel@tonic-gate case KEY_RECOVERABLE_ERROR:
15057c478bd9Sstevel@tonic-gate *err = EOK;
15067c478bd9Sstevel@tonic-gate err_action = "recovered";
15077c478bd9Sstevel@tonic-gate action = COMMAND_DONE;
15087c478bd9Sstevel@tonic-gate break;
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate case KEY_UNIT_ATTENTION:
15117c478bd9Sstevel@tonic-gate /*
15127c478bd9Sstevel@tonic-gate * This is common for RAID!
15137c478bd9Sstevel@tonic-gate */
15147c478bd9Sstevel@tonic-gate /* *err = EIO; */
15157c478bd9Sstevel@tonic-gate SES_CMD_RETRY1(ssc->ses_retries);
15167c478bd9Sstevel@tonic-gate action = QUE_COMMAND_NOW;
15177c478bd9Sstevel@tonic-gate break;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate case KEY_NOT_READY:
15207c478bd9Sstevel@tonic-gate case KEY_NO_SENSE:
15217c478bd9Sstevel@tonic-gate /* *err = EIO; */
15227c478bd9Sstevel@tonic-gate action = QUE_COMMAND;
15237c478bd9Sstevel@tonic-gate break;
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate default:
15267c478bd9Sstevel@tonic-gate /* *err = EIO; */
15277c478bd9Sstevel@tonic-gate err_action = "fatal";
15287c478bd9Sstevel@tonic-gate action = COMMAND_DONE_ERROR;
15297c478bd9Sstevel@tonic-gate break;
15307c478bd9Sstevel@tonic-gate }
15317c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG1,
15327c478bd9Sstevel@tonic-gate "cdb[0]= 0x%x %s, key=0x%x, ASC/ASCQ=0x%x/0x%x",
15337c478bd9Sstevel@tonic-gate scmd->uscsi_cdb[0], err_action,
15347c478bd9Sstevel@tonic-gate sense->es_key, sense->es_add_code, sense->es_qual_code);
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate #ifdef not
15377c478bd9Sstevel@tonic-gate /*
15387c478bd9Sstevel@tonic-gate * Dump cdb and sense data stat's for manufacturing.
15397c478bd9Sstevel@tonic-gate */
15407c478bd9Sstevel@tonic-gate if (DEBUGGING_ERR || sd_error_level == SDERR_ALL) {
15417c478bd9Sstevel@tonic-gate auto buf[128];
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate p = pkt->pkt_cdbp;
15447c478bd9Sstevel@tonic-gate if ((j = scsi_cdb_size[CDB_GROUPID(*p)]) == 0)
15457c478bd9Sstevel@tonic-gate j = CDB_SIZE;
15467c478bd9Sstevel@tonic-gate
15477c478bd9Sstevel@tonic-gate /* Print cdb */
15487c478bd9Sstevel@tonic-gate (void) sprintf(buf, "cmd:");
15497c478bd9Sstevel@tonic-gate for (i = 0; i < j; i++) {
15507c478bd9Sstevel@tonic-gate (void) sprintf(&buf[strlen(buf)],
15517c478bd9Sstevel@tonic-gate hex, (uchar_t)*p++);
15527c478bd9Sstevel@tonic-gate }
15537c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate /* Suppress trailing zero's in sense data */
15567c478bd9Sstevel@tonic-gate if (amt > 3) {
15577c478bd9Sstevel@tonic-gate p = (char *)devp->sd_sense + amt;
15587c478bd9Sstevel@tonic-gate for (j = amt; j > 3; j--) {
15597c478bd9Sstevel@tonic-gate if (*(--p)) break;
15607c478bd9Sstevel@tonic-gate }
15617c478bd9Sstevel@tonic-gate } else {
15627c478bd9Sstevel@tonic-gate j = amt;
15637c478bd9Sstevel@tonic-gate }
15647c478bd9Sstevel@tonic-gate
15657c478bd9Sstevel@tonic-gate /* Print sense data. */
15667c478bd9Sstevel@tonic-gate (void) sprintf(buf, "sense:");
15677c478bd9Sstevel@tonic-gate p = (char *)devp->sd_sense;
15687c478bd9Sstevel@tonic-gate for (i = 0; i < j; i++) {
15697c478bd9Sstevel@tonic-gate (void) sprintf(&buf[strlen(buf)],
15707c478bd9Sstevel@tonic-gate hex, (uchar_t)*p++);
15717c478bd9Sstevel@tonic-gate }
15727c478bd9Sstevel@tonic-gate SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
15737c478bd9Sstevel@tonic-gate }
15747c478bd9Sstevel@tonic-gate #endif /* not */
15757c478bd9Sstevel@tonic-gate return (action);
15767c478bd9Sstevel@tonic-gate }
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/
15807c478bd9Sstevel@tonic-gate void
ses_log(ses_softc_t * ssc,int level,const char * fmt,...)15817c478bd9Sstevel@tonic-gate ses_log(ses_softc_t *ssc, int level, const char *fmt, ...)
15827c478bd9Sstevel@tonic-gate {
15837c478bd9Sstevel@tonic-gate va_list ap;
15847c478bd9Sstevel@tonic-gate char buf[256];
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate va_start(ap, fmt);
15877c478bd9Sstevel@tonic-gate (void) vsprintf(buf, fmt, ap);
15887c478bd9Sstevel@tonic-gate va_end(ap);
15897c478bd9Sstevel@tonic-gate
15907c478bd9Sstevel@tonic-gate if (ssc == (ses_softc_t *)NULL) {
15917c478bd9Sstevel@tonic-gate switch (level) {
15927c478bd9Sstevel@tonic-gate case SES_CE_DEBUG1:
15937c478bd9Sstevel@tonic-gate if (ses_debug > 1)
15947c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
15957c478bd9Sstevel@tonic-gate break;
15967c478bd9Sstevel@tonic-gate case SES_CE_DEBUG2:
15977c478bd9Sstevel@tonic-gate if (ses_debug > 2)
15987c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
15997c478bd9Sstevel@tonic-gate break;
16007c478bd9Sstevel@tonic-gate case SES_CE_DEBUG3:
16017c478bd9Sstevel@tonic-gate if (ses_debug > 3)
16027c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16037c478bd9Sstevel@tonic-gate break;
16047c478bd9Sstevel@tonic-gate case SES_CE_DEBUG4:
16057c478bd9Sstevel@tonic-gate if (ses_debug > 4)
16067c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16077c478bd9Sstevel@tonic-gate break;
16087c478bd9Sstevel@tonic-gate case SES_CE_DEBUG5:
16097c478bd9Sstevel@tonic-gate if (ses_debug > 5)
16107c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16117c478bd9Sstevel@tonic-gate break;
16127c478bd9Sstevel@tonic-gate case SES_CE_DEBUG6:
16137c478bd9Sstevel@tonic-gate if (ses_debug > 6)
16147c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16157c478bd9Sstevel@tonic-gate break;
16167c478bd9Sstevel@tonic-gate case SES_CE_DEBUG7:
16177c478bd9Sstevel@tonic-gate if (ses_debug > 7)
16187c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16197c478bd9Sstevel@tonic-gate break;
16207c478bd9Sstevel@tonic-gate case SES_CE_DEBUG8:
16217c478bd9Sstevel@tonic-gate if (ses_debug > 8)
16227c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16237c478bd9Sstevel@tonic-gate break;
16247c478bd9Sstevel@tonic-gate case SES_CE_DEBUG9:
16257c478bd9Sstevel@tonic-gate if (ses_debug > 9)
16267c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16277c478bd9Sstevel@tonic-gate break;
16287c478bd9Sstevel@tonic-gate case CE_NOTE:
16297c478bd9Sstevel@tonic-gate case CE_WARN:
16307c478bd9Sstevel@tonic-gate case CE_PANIC:
16317c478bd9Sstevel@tonic-gate cmn_err(level, "%s", buf);
16327c478bd9Sstevel@tonic-gate break;
16337c478bd9Sstevel@tonic-gate case SES_CE_DEBUG:
16347c478bd9Sstevel@tonic-gate default:
16357c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, "%s", buf);
16367c478bd9Sstevel@tonic-gate break;
16377c478bd9Sstevel@tonic-gate }
16387c478bd9Sstevel@tonic-gate return;
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate
16417c478bd9Sstevel@tonic-gate switch (level) {
16427c478bd9Sstevel@tonic-gate case CE_CONT:
16437c478bd9Sstevel@tonic-gate case CE_NOTE:
16447c478bd9Sstevel@tonic-gate case CE_WARN:
16457c478bd9Sstevel@tonic-gate case CE_PANIC:
16467c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, level, Str, buf);
16477c478bd9Sstevel@tonic-gate break;
16487c478bd9Sstevel@tonic-gate case SES_CE_DEBUG1:
16497c478bd9Sstevel@tonic-gate if (ses_debug > 1)
16507c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16517c478bd9Sstevel@tonic-gate Str, buf);
16527c478bd9Sstevel@tonic-gate break;
16537c478bd9Sstevel@tonic-gate case SES_CE_DEBUG2:
16547c478bd9Sstevel@tonic-gate if (ses_debug > 2)
16557c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16567c478bd9Sstevel@tonic-gate Str, buf);
16577c478bd9Sstevel@tonic-gate break;
16587c478bd9Sstevel@tonic-gate case SES_CE_DEBUG3:
16597c478bd9Sstevel@tonic-gate if (ses_debug > 3)
16607c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16617c478bd9Sstevel@tonic-gate Str, buf);
16627c478bd9Sstevel@tonic-gate break;
16637c478bd9Sstevel@tonic-gate case SES_CE_DEBUG4:
16647c478bd9Sstevel@tonic-gate if (ses_debug > 4)
16657c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16667c478bd9Sstevel@tonic-gate Str, buf);
16677c478bd9Sstevel@tonic-gate break;
16687c478bd9Sstevel@tonic-gate case SES_CE_DEBUG5:
16697c478bd9Sstevel@tonic-gate if (ses_debug > 5)
16707c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16717c478bd9Sstevel@tonic-gate Str, buf);
16727c478bd9Sstevel@tonic-gate break;
16737c478bd9Sstevel@tonic-gate case SES_CE_DEBUG6:
16747c478bd9Sstevel@tonic-gate if (ses_debug > 6)
16757c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16767c478bd9Sstevel@tonic-gate Str, buf);
16777c478bd9Sstevel@tonic-gate break;
16787c478bd9Sstevel@tonic-gate case SES_CE_DEBUG7:
16797c478bd9Sstevel@tonic-gate if (ses_debug > 7)
16807c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16817c478bd9Sstevel@tonic-gate Str, buf);
16827c478bd9Sstevel@tonic-gate break;
16837c478bd9Sstevel@tonic-gate case SES_CE_DEBUG8:
16847c478bd9Sstevel@tonic-gate if (ses_debug > 8)
16857c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16867c478bd9Sstevel@tonic-gate Str, buf);
16877c478bd9Sstevel@tonic-gate break;
16887c478bd9Sstevel@tonic-gate case SES_CE_DEBUG9:
16897c478bd9Sstevel@tonic-gate if (ses_debug > 9)
16907c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
16917c478bd9Sstevel@tonic-gate Str, buf);
16927c478bd9Sstevel@tonic-gate break;
16937c478bd9Sstevel@tonic-gate case SES_CE_DEBUG:
16947c478bd9Sstevel@tonic-gate default:
16957c478bd9Sstevel@tonic-gate scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG, Str, buf);
16967c478bd9Sstevel@tonic-gate break;
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate /*
17007c478bd9Sstevel@tonic-gate * mode: c
17017c478bd9Sstevel@tonic-gate * Local variables:
17027c478bd9Sstevel@tonic-gate * c-indent-level: 8
17037c478bd9Sstevel@tonic-gate * c-brace-imaginary-offset: 0
17047c478bd9Sstevel@tonic-gate * c-brace-offset: -8
17057c478bd9Sstevel@tonic-gate * c-argdecl-indent: 8
17067c478bd9Sstevel@tonic-gate * c-label-offset: -8
17077c478bd9Sstevel@tonic-gate * c-continued-statement-offset: 8
17087c478bd9Sstevel@tonic-gate * c-continued-brace-offset: 0
17097c478bd9Sstevel@tonic-gate * End:
17107c478bd9Sstevel@tonic-gate */
1711