11709Smlf /* 21709Smlf * CDDL HEADER START 31709Smlf * 41709Smlf * The contents of this file are subject to the terms of the 51709Smlf * Common Development and Distribution License (the "License"). 61709Smlf * You may not use this file except in compliance with the License. 71709Smlf * 81709Smlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91709Smlf * or http://www.opensolaris.org/os/licensing. 101709Smlf * See the License for the specific language governing permissions 111709Smlf * and limitations under the License. 121709Smlf * 131709Smlf * When distributing Covered Code, include this CDDL HEADER in each 141709Smlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151709Smlf * If applicable, add the following below this CDDL HEADER, with the 161709Smlf * fields enclosed by brackets "[]" replaced with your own identifying 171709Smlf * information: Portions Copyright [yyyy] [name of copyright owner] 181709Smlf * 191709Smlf * CDDL HEADER END 201709Smlf */ 211709Smlf 221709Smlf /* 23*1900Seota * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241709Smlf * Use is subject to license terms. 251709Smlf */ 261709Smlf 271709Smlf #pragma ident "%Z%%M% %I% %E% SMI" 281709Smlf 291709Smlf #include <sys/scsi/scsi.h> 301709Smlf 311709Smlf #include <sys/dktp/dadev.h> 321709Smlf #include <sys/dktp/gda.h> 331709Smlf 341709Smlf /* 351709Smlf * Generic Direct Attached Device 361709Smlf */ 371709Smlf 381709Smlf static char *gda_name(uchar_t cmd, char **cmdvec); 391709Smlf 401709Smlf #ifdef GDA_DEBUG 411709Smlf #define DENT 0x0001 421709Smlf #define DPKT 0x0002 431709Smlf #define DERR 0x0004 441709Smlf static int gda_debug = DERR|DENT|DPKT; 451709Smlf 461709Smlf #endif /* GDA_DEBUG */ 471709Smlf 481709Smlf /* 491709Smlf * Local static data 501709Smlf */ 511709Smlf 521709Smlf /* 531709Smlf * global data 541709Smlf */ 551709Smlf 561709Smlf /* 571709Smlf * This is the loadable module wrapper 581709Smlf */ 591709Smlf #include <sys/modctl.h> 601709Smlf 611709Smlf extern struct mod_ops mod_miscops; 621709Smlf 631709Smlf static struct modlmisc modlmisc = { 641709Smlf &mod_miscops, /* Type of module */ 651709Smlf "Generic Direct Attached Device Utilities" 661709Smlf }; 671709Smlf 681709Smlf static struct modlinkage modlinkage = { 691709Smlf MODREV_1, (void *)&modlmisc, NULL 701709Smlf }; 711709Smlf 721709Smlf int 731709Smlf _init(void) 741709Smlf { 751709Smlf return (mod_install(&modlinkage)); 761709Smlf } 771709Smlf 781709Smlf int 791709Smlf _fini(void) 801709Smlf { 811709Smlf #ifdef GDA_DEBUG 821709Smlf if (gda_debug & DENT) 831709Smlf PRF("gda_fini: call\n"); 841709Smlf #endif 851709Smlf return (mod_remove(&modlinkage)); 861709Smlf } 871709Smlf 881709Smlf int 891709Smlf _info(struct modinfo *modinfop) 901709Smlf { 911709Smlf return (mod_info(&modlinkage, modinfop)); 921709Smlf } 931709Smlf 941709Smlf 951709Smlf void 961709Smlf gda_inqfill(char *p, int l, char *s) 971709Smlf { 981709Smlf register unsigned i = 0, c; 991709Smlf 1001709Smlf if (!p) 1011709Smlf return; 1021709Smlf while (i++ < l) { 1031709Smlf /* clean strings of non-printing chars */ 1041709Smlf if ((c = *p++) < ' ' || c > 0176) { 1051709Smlf c = ' '; 1061709Smlf } 1071709Smlf *s++ = (char)c; 1081709Smlf } 1091709Smlf *s++ = 0; 1101709Smlf } 1111709Smlf 1121709Smlf static char * 1131709Smlf gda_name(uchar_t cmd, char **cmdvec) 1141709Smlf { 1151709Smlf while (*cmdvec != NULL) { 1161709Smlf if (cmd == **cmdvec) { 1171709Smlf return (*cmdvec + 1); 1181709Smlf } 1191709Smlf cmdvec++; 1201709Smlf } 1211709Smlf return ("<undecoded cmd>"); 1221709Smlf } 1231709Smlf 1241709Smlf 1251709Smlf struct cmpkt * 1261709Smlf gda_pktprep(opaque_t objp, struct cmpkt *in_pktp, opaque_t dmatoken, 1271709Smlf int (*callback)(caddr_t), caddr_t arg) 1281709Smlf { 1291709Smlf register struct cmpkt *pktp; 1301709Smlf register struct buf *bp = (struct buf *)dmatoken; 1311709Smlf 1321709Smlf if (in_pktp) { 1331709Smlf pktp = in_pktp; 1341709Smlf } else { 1351709Smlf pktp = CTL_PKTALLOC(objp, callback, arg); 1361709Smlf if (pktp == NULL) 1371709Smlf return (NULL); 1381709Smlf } 1391709Smlf 1401709Smlf if (bp) { 1411709Smlf if (bp->b_bcount) { 1421709Smlf if (CTL_MEMSETUP(objp, pktp, bp, callback, arg) == 1431709Smlf NULL) { 1441709Smlf if (!in_pktp) 1451709Smlf CTL_PKTFREE(objp, pktp); 1461709Smlf return (NULL); 1471709Smlf } 1481709Smlf } 1491709Smlf bp->av_back = (struct buf *)pktp; 1501709Smlf pktp->cp_bp = bp; 1511709Smlf } 1521709Smlf pktp->cp_retry = 0; 1531709Smlf pktp->cp_objp = objp; 1541709Smlf 1551709Smlf 1561709Smlf #ifdef GDA_DEBUG 1571709Smlf if (gda_debug & DPKT) 1581709Smlf PRF("gda_pktprep: pktp=0x%x \n", pktp); 1591709Smlf #endif 1601709Smlf return (pktp); 1611709Smlf } 1621709Smlf 1631709Smlf void 1641709Smlf gda_free(opaque_t objp, struct cmpkt *pktp, struct buf *bp) 1651709Smlf { 1661709Smlf if (pktp) { 1671709Smlf CTL_MEMFREE(objp, pktp); 1681709Smlf CTL_PKTFREE(objp, pktp); 1691709Smlf } 1701709Smlf 1711709Smlf if (bp) { 1721709Smlf if (bp->b_un.b_addr) 173*1900Seota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 1741709Smlf freerbuf(bp); 1751709Smlf } 1761709Smlf } 1771709Smlf 1781709Smlf void 1791709Smlf gda_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 1801709Smlf { 1811709Smlf auto char name[256]; 1821709Smlf auto char buf [256]; 1831709Smlf va_list ap; 1841709Smlf int log_only = 0; 1851709Smlf int boot_only = 0; 1861709Smlf int console_only = 0; 1871709Smlf 1881709Smlf switch (*fmt) { 1891709Smlf case '!': 1901709Smlf log_only = 1; 1911709Smlf fmt++; 1921709Smlf break; 1931709Smlf case '?': 1941709Smlf boot_only = 1; 1951709Smlf fmt++; 1961709Smlf break; 1971709Smlf case '^': 1981709Smlf console_only = 1; 1991709Smlf fmt++; 2001709Smlf break; 2011709Smlf } 2021709Smlf 2031709Smlf 2041709Smlf if (dev) { 2051709Smlf if (level == CE_PANIC || level == CE_WARN) { 2061709Smlf (void) sprintf(name, "%s (%s%d):\n", 2071709Smlf ddi_pathname(dev, buf), label, 2081709Smlf ddi_get_instance(dev)); 2091709Smlf } else if (level == CE_NOTE || 2101709Smlf level >= (uint_t)SCSI_DEBUG) { 2111709Smlf (void) sprintf(name, 2121709Smlf "%s%d:", label, ddi_get_instance(dev)); 2131709Smlf } else if (level == CE_CONT) { 2141709Smlf name[0] = '\0'; 2151709Smlf } 2161709Smlf } else { 2171709Smlf (void) sprintf(name, "%s:", label); 2181709Smlf } 2191709Smlf 2201709Smlf va_start(ap, fmt); 2211709Smlf (void) vsprintf(buf, fmt, ap); 2221709Smlf va_end(ap); 2231709Smlf 2241709Smlf switch (level) { 2251709Smlf case CE_NOTE: 2261709Smlf level = CE_CONT; 2271709Smlf /* FALLTHROUGH */ 2281709Smlf case CE_CONT: 2291709Smlf case CE_WARN: 2301709Smlf case CE_PANIC: 2311709Smlf if (boot_only) { 2321709Smlf cmn_err(level, "?%s\t%s", name, buf); 2331709Smlf } else if (console_only) { 2341709Smlf cmn_err(level, "^%s\t%s", name, buf); 2351709Smlf } else if (log_only) { 2361709Smlf cmn_err(level, "!%s\t%s", name, buf); 2371709Smlf } else { 2381709Smlf cmn_err(level, "%s\t%s", name, buf); 2391709Smlf } 2401709Smlf break; 2411709Smlf default: 2421709Smlf cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, buf); 2431709Smlf break; 2441709Smlf } 2451709Smlf } 2461709Smlf 2471709Smlf void 2481709Smlf gda_errmsg(struct scsi_device *devp, struct cmpkt *pktp, char *label, 2491709Smlf int severity, int blkno, int err_blkno, 2501709Smlf char **cmdvec, char **senvec) 2511709Smlf { 2521709Smlf auto char buf[256]; 2531709Smlf dev_info_t *dev = devp->sd_dev; 2541709Smlf static char *error_classes[] = { 2551709Smlf "All", "Unknown", "Informational", 2561709Smlf "Recovered", "Retryable", "Fatal" 2571709Smlf }; 2581709Smlf 2591709Smlf bzero((caddr_t)buf, 256); 2601709Smlf (void) sprintf(buf, "Error for command '%s'\tError Level: %s", 2611709Smlf gda_name(*(uchar_t *)pktp->cp_cdbp, cmdvec), 2621709Smlf error_classes[severity]); 2631709Smlf gda_log(dev, label, CE_WARN, buf); 2641709Smlf 2651709Smlf bzero((caddr_t)buf, 256); 2661709Smlf if ((blkno != -1) && (err_blkno != -1)) { 2671709Smlf (void) sprintf(buf, "Requested Block %d, Error Block: %d\n", 2681709Smlf blkno, err_blkno); 2691709Smlf gda_log(dev, label, CE_CONT, buf); 2701709Smlf } 2711709Smlf 2721709Smlf bzero((caddr_t)buf, 256); 2731709Smlf (void) sprintf(buf, "Sense Key: %s\n", 2741709Smlf gda_name(*(uchar_t *)pktp->cp_scbp, senvec)); 2751709Smlf 2761709Smlf gda_log(dev, label, CE_CONT, buf); 2771709Smlf bzero((caddr_t)buf, 256); 2781709Smlf (void) strcpy(buf, "Vendor '"); 2791709Smlf gda_inqfill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]); 2801709Smlf (void) sprintf(&buf[strlen(buf)], 2811709Smlf "' error code: 0x%x", 2821709Smlf *(uchar_t *)pktp->cp_scbp); 2831709Smlf gda_log(dev, label, CE_CONT, "%s\n", buf); 2841709Smlf } 285