1507c3241Smlf /* 2507c3241Smlf * CDDL HEADER START 3507c3241Smlf * 4507c3241Smlf * The contents of this file are subject to the terms of the 5507c3241Smlf * Common Development and Distribution License (the "License"). 6507c3241Smlf * You may not use this file except in compliance with the License. 7507c3241Smlf * 8507c3241Smlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9507c3241Smlf * or http://www.opensolaris.org/os/licensing. 10507c3241Smlf * See the License for the specific language governing permissions 11507c3241Smlf * and limitations under the License. 12507c3241Smlf * 13507c3241Smlf * When distributing Covered Code, include this CDDL HEADER in each 14507c3241Smlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15507c3241Smlf * If applicable, add the following below this CDDL HEADER, with the 16507c3241Smlf * fields enclosed by brackets "[]" replaced with your own identifying 17507c3241Smlf * information: Portions Copyright [yyyy] [name of copyright owner] 18507c3241Smlf * 19507c3241Smlf * CDDL HEADER END 20507c3241Smlf */ 21507c3241Smlf 22507c3241Smlf /* 23*342440ecSPrasad Singamsetty * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24507c3241Smlf * Use is subject to license terms. 25507c3241Smlf */ 26507c3241Smlf 27507c3241Smlf #include <sys/scsi/scsi.h> 28507c3241Smlf 29507c3241Smlf #include <sys/dktp/dadev.h> 30507c3241Smlf #include <sys/dktp/gda.h> 31507c3241Smlf 32507c3241Smlf /* 33507c3241Smlf * Generic Direct Attached Device 34507c3241Smlf */ 35507c3241Smlf 36507c3241Smlf static char *gda_name(uchar_t cmd, char **cmdvec); 37507c3241Smlf 38507c3241Smlf #ifdef GDA_DEBUG 39507c3241Smlf #define DENT 0x0001 40507c3241Smlf #define DPKT 0x0002 41507c3241Smlf #define DERR 0x0004 42507c3241Smlf static int gda_debug = DERR|DENT|DPKT; 43507c3241Smlf 44507c3241Smlf #endif /* GDA_DEBUG */ 45507c3241Smlf 46507c3241Smlf /* 47507c3241Smlf * Local static data 48507c3241Smlf */ 49507c3241Smlf 50507c3241Smlf /* 51507c3241Smlf * global data 52507c3241Smlf */ 53507c3241Smlf 54507c3241Smlf /* 55507c3241Smlf * This is the loadable module wrapper 56507c3241Smlf */ 57507c3241Smlf #include <sys/modctl.h> 58507c3241Smlf 59507c3241Smlf extern struct mod_ops mod_miscops; 60507c3241Smlf 61507c3241Smlf static struct modlmisc modlmisc = { 62507c3241Smlf &mod_miscops, /* Type of module */ 63507c3241Smlf "Generic Direct Attached Device Utilities" 64507c3241Smlf }; 65507c3241Smlf 66507c3241Smlf static struct modlinkage modlinkage = { 67507c3241Smlf MODREV_1, (void *)&modlmisc, NULL 68507c3241Smlf }; 69507c3241Smlf 70507c3241Smlf int 71507c3241Smlf _init(void) 72507c3241Smlf { 73507c3241Smlf return (mod_install(&modlinkage)); 74507c3241Smlf } 75507c3241Smlf 76507c3241Smlf int 77507c3241Smlf _fini(void) 78507c3241Smlf { 79507c3241Smlf #ifdef GDA_DEBUG 80507c3241Smlf if (gda_debug & DENT) 81507c3241Smlf PRF("gda_fini: call\n"); 82507c3241Smlf #endif 83507c3241Smlf return (mod_remove(&modlinkage)); 84507c3241Smlf } 85507c3241Smlf 86507c3241Smlf int 87507c3241Smlf _info(struct modinfo *modinfop) 88507c3241Smlf { 89507c3241Smlf return (mod_info(&modlinkage, modinfop)); 90507c3241Smlf } 91507c3241Smlf 92507c3241Smlf 93507c3241Smlf void 94507c3241Smlf gda_inqfill(char *p, int l, char *s) 95507c3241Smlf { 96507c3241Smlf register unsigned i = 0, c; 97507c3241Smlf 98507c3241Smlf if (!p) 99507c3241Smlf return; 100507c3241Smlf while (i++ < l) { 101507c3241Smlf /* clean strings of non-printing chars */ 102507c3241Smlf if ((c = *p++) < ' ' || c > 0176) { 103507c3241Smlf c = ' '; 104507c3241Smlf } 105507c3241Smlf *s++ = (char)c; 106507c3241Smlf } 107507c3241Smlf *s++ = 0; 108507c3241Smlf } 109507c3241Smlf 110507c3241Smlf static char * 111507c3241Smlf gda_name(uchar_t cmd, char **cmdvec) 112507c3241Smlf { 113507c3241Smlf while (*cmdvec != NULL) { 114507c3241Smlf if (cmd == **cmdvec) { 115507c3241Smlf return (*cmdvec + 1); 116507c3241Smlf } 117507c3241Smlf cmdvec++; 118507c3241Smlf } 119507c3241Smlf return ("<undecoded cmd>"); 120507c3241Smlf } 121507c3241Smlf 122507c3241Smlf 123507c3241Smlf struct cmpkt * 124507c3241Smlf gda_pktprep(opaque_t objp, struct cmpkt *in_pktp, opaque_t dmatoken, 125507c3241Smlf int (*callback)(caddr_t), caddr_t arg) 126507c3241Smlf { 127507c3241Smlf register struct cmpkt *pktp; 128507c3241Smlf register struct buf *bp = (struct buf *)dmatoken; 129507c3241Smlf 130507c3241Smlf if (in_pktp) { 131507c3241Smlf pktp = in_pktp; 132507c3241Smlf } else { 133507c3241Smlf pktp = CTL_PKTALLOC(objp, callback, arg); 134507c3241Smlf if (pktp == NULL) 135507c3241Smlf return (NULL); 136507c3241Smlf } 137507c3241Smlf 138507c3241Smlf if (bp) { 139507c3241Smlf if (bp->b_bcount) { 140507c3241Smlf if (CTL_MEMSETUP(objp, pktp, bp, callback, arg) == 141507c3241Smlf NULL) { 142507c3241Smlf if (!in_pktp) 143507c3241Smlf CTL_PKTFREE(objp, pktp); 144507c3241Smlf return (NULL); 145507c3241Smlf } 146507c3241Smlf } 147507c3241Smlf bp->av_back = (struct buf *)pktp; 148507c3241Smlf pktp->cp_bp = bp; 149507c3241Smlf } 150507c3241Smlf pktp->cp_retry = 0; 151507c3241Smlf pktp->cp_objp = objp; 152507c3241Smlf 153507c3241Smlf 154507c3241Smlf #ifdef GDA_DEBUG 155507c3241Smlf if (gda_debug & DPKT) 156507c3241Smlf PRF("gda_pktprep: pktp=0x%x \n", pktp); 157507c3241Smlf #endif 158507c3241Smlf return (pktp); 159507c3241Smlf } 160507c3241Smlf 161507c3241Smlf void 162507c3241Smlf gda_free(opaque_t objp, struct cmpkt *pktp, struct buf *bp) 163507c3241Smlf { 164507c3241Smlf if (pktp) { 165507c3241Smlf CTL_MEMFREE(objp, pktp); 166507c3241Smlf CTL_PKTFREE(objp, pktp); 167507c3241Smlf } 168507c3241Smlf 169507c3241Smlf if (bp) { 170507c3241Smlf if (bp->b_un.b_addr) 1717b93957cSeota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 172507c3241Smlf freerbuf(bp); 173507c3241Smlf } 174507c3241Smlf } 175507c3241Smlf 176507c3241Smlf void 177507c3241Smlf gda_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 178507c3241Smlf { 179507c3241Smlf auto char name[256]; 180507c3241Smlf auto char buf [256]; 181507c3241Smlf va_list ap; 182507c3241Smlf int log_only = 0; 183507c3241Smlf int boot_only = 0; 184507c3241Smlf int console_only = 0; 185507c3241Smlf 186507c3241Smlf switch (*fmt) { 187507c3241Smlf case '!': 188507c3241Smlf log_only = 1; 189507c3241Smlf fmt++; 190507c3241Smlf break; 191507c3241Smlf case '?': 192507c3241Smlf boot_only = 1; 193507c3241Smlf fmt++; 194507c3241Smlf break; 195507c3241Smlf case '^': 196507c3241Smlf console_only = 1; 197507c3241Smlf fmt++; 198507c3241Smlf break; 199507c3241Smlf } 200507c3241Smlf 201507c3241Smlf 202507c3241Smlf if (dev) { 203507c3241Smlf if (level == CE_PANIC || level == CE_WARN) { 204507c3241Smlf (void) sprintf(name, "%s (%s%d):\n", 205507c3241Smlf ddi_pathname(dev, buf), label, 206507c3241Smlf ddi_get_instance(dev)); 207507c3241Smlf } else if (level == CE_NOTE || 208507c3241Smlf level >= (uint_t)SCSI_DEBUG) { 209507c3241Smlf (void) sprintf(name, 210507c3241Smlf "%s%d:", label, ddi_get_instance(dev)); 211507c3241Smlf } else if (level == CE_CONT) { 212507c3241Smlf name[0] = '\0'; 213507c3241Smlf } 214507c3241Smlf } else { 215507c3241Smlf (void) sprintf(name, "%s:", label); 216507c3241Smlf } 217507c3241Smlf 218507c3241Smlf va_start(ap, fmt); 219507c3241Smlf (void) vsprintf(buf, fmt, ap); 220507c3241Smlf va_end(ap); 221507c3241Smlf 222507c3241Smlf switch (level) { 223507c3241Smlf case CE_NOTE: 224507c3241Smlf level = CE_CONT; 225507c3241Smlf /* FALLTHROUGH */ 226507c3241Smlf case CE_CONT: 227507c3241Smlf case CE_WARN: 228507c3241Smlf case CE_PANIC: 229507c3241Smlf if (boot_only) { 230507c3241Smlf cmn_err(level, "?%s\t%s", name, buf); 231507c3241Smlf } else if (console_only) { 232507c3241Smlf cmn_err(level, "^%s\t%s", name, buf); 233507c3241Smlf } else if (log_only) { 234507c3241Smlf cmn_err(level, "!%s\t%s", name, buf); 235507c3241Smlf } else { 236507c3241Smlf cmn_err(level, "%s\t%s", name, buf); 237507c3241Smlf } 238507c3241Smlf break; 239507c3241Smlf default: 240507c3241Smlf cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, buf); 241507c3241Smlf break; 242507c3241Smlf } 243507c3241Smlf } 244507c3241Smlf 245507c3241Smlf void 246507c3241Smlf gda_errmsg(struct scsi_device *devp, struct cmpkt *pktp, char *label, 247*342440ecSPrasad Singamsetty int severity, daddr_t blkno, daddr_t err_blkno, 248507c3241Smlf char **cmdvec, char **senvec) 249507c3241Smlf { 250507c3241Smlf auto char buf[256]; 251507c3241Smlf dev_info_t *dev = devp->sd_dev; 252507c3241Smlf static char *error_classes[] = { 253507c3241Smlf "All", "Unknown", "Informational", 254507c3241Smlf "Recovered", "Retryable", "Fatal" 255507c3241Smlf }; 256507c3241Smlf 257507c3241Smlf bzero((caddr_t)buf, 256); 258507c3241Smlf (void) sprintf(buf, "Error for command '%s'\tError Level: %s", 259507c3241Smlf gda_name(*(uchar_t *)pktp->cp_cdbp, cmdvec), 260507c3241Smlf error_classes[severity]); 261507c3241Smlf gda_log(dev, label, CE_WARN, buf); 262507c3241Smlf 263507c3241Smlf bzero((caddr_t)buf, 256); 264507c3241Smlf if ((blkno != -1) && (err_blkno != -1)) { 265*342440ecSPrasad Singamsetty (void) sprintf(buf, "Requested Block %ld, Error Block: %ld\n", 266507c3241Smlf blkno, err_blkno); 267507c3241Smlf gda_log(dev, label, CE_CONT, buf); 268507c3241Smlf } 269507c3241Smlf 270507c3241Smlf bzero((caddr_t)buf, 256); 271507c3241Smlf (void) sprintf(buf, "Sense Key: %s\n", 272507c3241Smlf gda_name(*(uchar_t *)pktp->cp_scbp, senvec)); 273507c3241Smlf 274507c3241Smlf gda_log(dev, label, CE_CONT, buf); 275507c3241Smlf bzero((caddr_t)buf, 256); 276507c3241Smlf (void) strcpy(buf, "Vendor '"); 277507c3241Smlf gda_inqfill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]); 278507c3241Smlf (void) sprintf(&buf[strlen(buf)], 279507c3241Smlf "' error code: 0x%x", 280507c3241Smlf *(uchar_t *)pktp->cp_scbp); 281507c3241Smlf gda_log(dev, label, CE_CONT, "%s\n", buf); 282507c3241Smlf } 283