1*1709Smlf /* 2*1709Smlf * CDDL HEADER START 3*1709Smlf * 4*1709Smlf * The contents of this file are subject to the terms of the 5*1709Smlf * Common Development and Distribution License (the "License"). 6*1709Smlf * You may not use this file except in compliance with the License. 7*1709Smlf * 8*1709Smlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*1709Smlf * or http://www.opensolaris.org/os/licensing. 10*1709Smlf * See the License for the specific language governing permissions 11*1709Smlf * and limitations under the License. 12*1709Smlf * 13*1709Smlf * When distributing Covered Code, include this CDDL HEADER in each 14*1709Smlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*1709Smlf * If applicable, add the following below this CDDL HEADER, with the 16*1709Smlf * fields enclosed by brackets "[]" replaced with your own identifying 17*1709Smlf * information: Portions Copyright [yyyy] [name of copyright owner] 18*1709Smlf * 19*1709Smlf * CDDL HEADER END 20*1709Smlf */ 21*1709Smlf 22*1709Smlf /* 23*1709Smlf * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*1709Smlf * Use is subject to license terms. 25*1709Smlf */ 26*1709Smlf 27*1709Smlf #pragma ident "%Z%%M% %I% %E% SMI" 28*1709Smlf 29*1709Smlf #include <sys/scsi/scsi.h> 30*1709Smlf 31*1709Smlf #include <sys/dktp/dadev.h> 32*1709Smlf #include <sys/dktp/gda.h> 33*1709Smlf 34*1709Smlf /* 35*1709Smlf * Generic Direct Attached Device 36*1709Smlf */ 37*1709Smlf 38*1709Smlf static char *gda_name(uchar_t cmd, char **cmdvec); 39*1709Smlf 40*1709Smlf #ifdef GDA_DEBUG 41*1709Smlf #define DENT 0x0001 42*1709Smlf #define DPKT 0x0002 43*1709Smlf #define DERR 0x0004 44*1709Smlf static int gda_debug = DERR|DENT|DPKT; 45*1709Smlf 46*1709Smlf #endif /* GDA_DEBUG */ 47*1709Smlf 48*1709Smlf /* 49*1709Smlf * Local static data 50*1709Smlf */ 51*1709Smlf 52*1709Smlf /* 53*1709Smlf * global data 54*1709Smlf */ 55*1709Smlf 56*1709Smlf /* 57*1709Smlf * This is the loadable module wrapper 58*1709Smlf */ 59*1709Smlf #include <sys/modctl.h> 60*1709Smlf 61*1709Smlf extern struct mod_ops mod_miscops; 62*1709Smlf 63*1709Smlf static struct modlmisc modlmisc = { 64*1709Smlf &mod_miscops, /* Type of module */ 65*1709Smlf "Generic Direct Attached Device Utilities" 66*1709Smlf }; 67*1709Smlf 68*1709Smlf static struct modlinkage modlinkage = { 69*1709Smlf MODREV_1, (void *)&modlmisc, NULL 70*1709Smlf }; 71*1709Smlf 72*1709Smlf int 73*1709Smlf _init(void) 74*1709Smlf { 75*1709Smlf return (mod_install(&modlinkage)); 76*1709Smlf } 77*1709Smlf 78*1709Smlf int 79*1709Smlf _fini(void) 80*1709Smlf { 81*1709Smlf #ifdef GDA_DEBUG 82*1709Smlf if (gda_debug & DENT) 83*1709Smlf PRF("gda_fini: call\n"); 84*1709Smlf #endif 85*1709Smlf return (mod_remove(&modlinkage)); 86*1709Smlf } 87*1709Smlf 88*1709Smlf int 89*1709Smlf _info(struct modinfo *modinfop) 90*1709Smlf { 91*1709Smlf return (mod_info(&modlinkage, modinfop)); 92*1709Smlf } 93*1709Smlf 94*1709Smlf 95*1709Smlf void 96*1709Smlf gda_inqfill(char *p, int l, char *s) 97*1709Smlf { 98*1709Smlf register unsigned i = 0, c; 99*1709Smlf 100*1709Smlf if (!p) 101*1709Smlf return; 102*1709Smlf while (i++ < l) { 103*1709Smlf /* clean strings of non-printing chars */ 104*1709Smlf if ((c = *p++) < ' ' || c > 0176) { 105*1709Smlf c = ' '; 106*1709Smlf } 107*1709Smlf *s++ = (char)c; 108*1709Smlf } 109*1709Smlf *s++ = 0; 110*1709Smlf } 111*1709Smlf 112*1709Smlf static char * 113*1709Smlf gda_name(uchar_t cmd, char **cmdvec) 114*1709Smlf { 115*1709Smlf while (*cmdvec != NULL) { 116*1709Smlf if (cmd == **cmdvec) { 117*1709Smlf return (*cmdvec + 1); 118*1709Smlf } 119*1709Smlf cmdvec++; 120*1709Smlf } 121*1709Smlf return ("<undecoded cmd>"); 122*1709Smlf } 123*1709Smlf 124*1709Smlf 125*1709Smlf struct cmpkt * 126*1709Smlf gda_pktprep(opaque_t objp, struct cmpkt *in_pktp, opaque_t dmatoken, 127*1709Smlf int (*callback)(caddr_t), caddr_t arg) 128*1709Smlf { 129*1709Smlf register struct cmpkt *pktp; 130*1709Smlf register struct buf *bp = (struct buf *)dmatoken; 131*1709Smlf 132*1709Smlf if (in_pktp) { 133*1709Smlf pktp = in_pktp; 134*1709Smlf } else { 135*1709Smlf pktp = CTL_PKTALLOC(objp, callback, arg); 136*1709Smlf if (pktp == NULL) 137*1709Smlf return (NULL); 138*1709Smlf } 139*1709Smlf 140*1709Smlf if (bp) { 141*1709Smlf if (bp->b_bcount) { 142*1709Smlf if (CTL_MEMSETUP(objp, pktp, bp, callback, arg) == 143*1709Smlf NULL) { 144*1709Smlf if (!in_pktp) 145*1709Smlf CTL_PKTFREE(objp, pktp); 146*1709Smlf return (NULL); 147*1709Smlf } 148*1709Smlf } 149*1709Smlf bp->av_back = (struct buf *)pktp; 150*1709Smlf pktp->cp_bp = bp; 151*1709Smlf } 152*1709Smlf pktp->cp_retry = 0; 153*1709Smlf pktp->cp_objp = objp; 154*1709Smlf 155*1709Smlf 156*1709Smlf #ifdef GDA_DEBUG 157*1709Smlf if (gda_debug & DPKT) 158*1709Smlf PRF("gda_pktprep: pktp=0x%x \n", pktp); 159*1709Smlf #endif 160*1709Smlf return (pktp); 161*1709Smlf } 162*1709Smlf 163*1709Smlf void 164*1709Smlf gda_free(opaque_t objp, struct cmpkt *pktp, struct buf *bp) 165*1709Smlf { 166*1709Smlf if (pktp) { 167*1709Smlf CTL_MEMFREE(objp, pktp); 168*1709Smlf CTL_PKTFREE(objp, pktp); 169*1709Smlf } 170*1709Smlf 171*1709Smlf if (bp) { 172*1709Smlf if (bp->b_un.b_addr) 173*1709Smlf i_ddi_mem_free((caddr_t)bp->b_un.b_addr, 0); 174*1709Smlf freerbuf(bp); 175*1709Smlf } 176*1709Smlf } 177*1709Smlf 178*1709Smlf void 179*1709Smlf gda_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 180*1709Smlf { 181*1709Smlf auto char name[256]; 182*1709Smlf auto char buf [256]; 183*1709Smlf va_list ap; 184*1709Smlf int log_only = 0; 185*1709Smlf int boot_only = 0; 186*1709Smlf int console_only = 0; 187*1709Smlf 188*1709Smlf switch (*fmt) { 189*1709Smlf case '!': 190*1709Smlf log_only = 1; 191*1709Smlf fmt++; 192*1709Smlf break; 193*1709Smlf case '?': 194*1709Smlf boot_only = 1; 195*1709Smlf fmt++; 196*1709Smlf break; 197*1709Smlf case '^': 198*1709Smlf console_only = 1; 199*1709Smlf fmt++; 200*1709Smlf break; 201*1709Smlf } 202*1709Smlf 203*1709Smlf 204*1709Smlf if (dev) { 205*1709Smlf if (level == CE_PANIC || level == CE_WARN) { 206*1709Smlf (void) sprintf(name, "%s (%s%d):\n", 207*1709Smlf ddi_pathname(dev, buf), label, 208*1709Smlf ddi_get_instance(dev)); 209*1709Smlf } else if (level == CE_NOTE || 210*1709Smlf level >= (uint_t)SCSI_DEBUG) { 211*1709Smlf (void) sprintf(name, 212*1709Smlf "%s%d:", label, ddi_get_instance(dev)); 213*1709Smlf } else if (level == CE_CONT) { 214*1709Smlf name[0] = '\0'; 215*1709Smlf } 216*1709Smlf } else { 217*1709Smlf (void) sprintf(name, "%s:", label); 218*1709Smlf } 219*1709Smlf 220*1709Smlf va_start(ap, fmt); 221*1709Smlf (void) vsprintf(buf, fmt, ap); 222*1709Smlf va_end(ap); 223*1709Smlf 224*1709Smlf switch (level) { 225*1709Smlf case CE_NOTE: 226*1709Smlf level = CE_CONT; 227*1709Smlf /* FALLTHROUGH */ 228*1709Smlf case CE_CONT: 229*1709Smlf case CE_WARN: 230*1709Smlf case CE_PANIC: 231*1709Smlf if (boot_only) { 232*1709Smlf cmn_err(level, "?%s\t%s", name, buf); 233*1709Smlf } else if (console_only) { 234*1709Smlf cmn_err(level, "^%s\t%s", name, buf); 235*1709Smlf } else if (log_only) { 236*1709Smlf cmn_err(level, "!%s\t%s", name, buf); 237*1709Smlf } else { 238*1709Smlf cmn_err(level, "%s\t%s", name, buf); 239*1709Smlf } 240*1709Smlf break; 241*1709Smlf default: 242*1709Smlf cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, buf); 243*1709Smlf break; 244*1709Smlf } 245*1709Smlf } 246*1709Smlf 247*1709Smlf void 248*1709Smlf gda_errmsg(struct scsi_device *devp, struct cmpkt *pktp, char *label, 249*1709Smlf int severity, int blkno, int err_blkno, 250*1709Smlf char **cmdvec, char **senvec) 251*1709Smlf { 252*1709Smlf auto char buf[256]; 253*1709Smlf dev_info_t *dev = devp->sd_dev; 254*1709Smlf static char *error_classes[] = { 255*1709Smlf "All", "Unknown", "Informational", 256*1709Smlf "Recovered", "Retryable", "Fatal" 257*1709Smlf }; 258*1709Smlf 259*1709Smlf bzero((caddr_t)buf, 256); 260*1709Smlf (void) sprintf(buf, "Error for command '%s'\tError Level: %s", 261*1709Smlf gda_name(*(uchar_t *)pktp->cp_cdbp, cmdvec), 262*1709Smlf error_classes[severity]); 263*1709Smlf gda_log(dev, label, CE_WARN, buf); 264*1709Smlf 265*1709Smlf bzero((caddr_t)buf, 256); 266*1709Smlf if ((blkno != -1) && (err_blkno != -1)) { 267*1709Smlf (void) sprintf(buf, "Requested Block %d, Error Block: %d\n", 268*1709Smlf blkno, err_blkno); 269*1709Smlf gda_log(dev, label, CE_CONT, buf); 270*1709Smlf } 271*1709Smlf 272*1709Smlf bzero((caddr_t)buf, 256); 273*1709Smlf (void) sprintf(buf, "Sense Key: %s\n", 274*1709Smlf gda_name(*(uchar_t *)pktp->cp_scbp, senvec)); 275*1709Smlf 276*1709Smlf gda_log(dev, label, CE_CONT, buf); 277*1709Smlf bzero((caddr_t)buf, 256); 278*1709Smlf (void) strcpy(buf, "Vendor '"); 279*1709Smlf gda_inqfill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]); 280*1709Smlf (void) sprintf(&buf[strlen(buf)], 281*1709Smlf "' error code: 0x%x", 282*1709Smlf *(uchar_t *)pktp->cp_scbp); 283*1709Smlf gda_log(dev, label, CE_CONT, "%s\n", buf); 284*1709Smlf } 285