xref: /onnv-gate/usr/src/uts/intel/io/dktp/dcdev/gda.c (revision 1900)
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