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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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