xref: /onnv-gate/usr/src/uts/intel/io/dktp/dcdev/gda.c (revision 7563:84ec90ffc3f7)
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*7563SPrasad.Singamsetty@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
241709Smlf  * Use is subject to license terms.
251709Smlf  */
261709Smlf 
271709Smlf #include <sys/scsi/scsi.h>
281709Smlf 
291709Smlf #include <sys/dktp/dadev.h>
301709Smlf #include <sys/dktp/gda.h>
311709Smlf 
321709Smlf /*
331709Smlf  *	Generic Direct Attached Device
341709Smlf  */
351709Smlf 
361709Smlf static char *gda_name(uchar_t cmd, char **cmdvec);
371709Smlf 
381709Smlf #ifdef	GDA_DEBUG
391709Smlf #define	DENT	0x0001
401709Smlf #define	DPKT	0x0002
411709Smlf #define	DERR	0x0004
421709Smlf static	int	gda_debug = DERR|DENT|DPKT;
431709Smlf 
441709Smlf #endif	/* GDA_DEBUG */
451709Smlf 
461709Smlf /*
471709Smlf  * Local static data
481709Smlf  */
491709Smlf 
501709Smlf /*
511709Smlf  *	global data
521709Smlf  */
531709Smlf 
541709Smlf /*
551709Smlf  *	This is the loadable module wrapper
561709Smlf  */
571709Smlf #include <sys/modctl.h>
581709Smlf 
591709Smlf extern struct mod_ops mod_miscops;
601709Smlf 
611709Smlf static struct modlmisc modlmisc = {
621709Smlf 	&mod_miscops,	/* Type of module */
631709Smlf 	"Generic Direct Attached Device Utilities"
641709Smlf };
651709Smlf 
661709Smlf static struct modlinkage modlinkage = {
671709Smlf 	MODREV_1, (void *)&modlmisc, NULL
681709Smlf };
691709Smlf 
701709Smlf int
_init(void)711709Smlf _init(void)
721709Smlf {
731709Smlf 	return (mod_install(&modlinkage));
741709Smlf }
751709Smlf 
761709Smlf int
_fini(void)771709Smlf _fini(void)
781709Smlf {
791709Smlf #ifdef GDA_DEBUG
801709Smlf 	if (gda_debug & DENT)
811709Smlf 		PRF("gda_fini: call\n");
821709Smlf #endif
831709Smlf 	return (mod_remove(&modlinkage));
841709Smlf }
851709Smlf 
861709Smlf int
_info(struct modinfo * modinfop)871709Smlf _info(struct modinfo *modinfop)
881709Smlf {
891709Smlf 	return (mod_info(&modlinkage, modinfop));
901709Smlf }
911709Smlf 
921709Smlf 
931709Smlf void
gda_inqfill(char * p,int l,char * s)941709Smlf gda_inqfill(char *p, int l, char *s)
951709Smlf {
961709Smlf 	register unsigned i = 0, c;
971709Smlf 
981709Smlf 	if (!p)
991709Smlf 		return;
1001709Smlf 	while (i++ < l) {
1011709Smlf /* 		clean strings of non-printing chars			*/
1021709Smlf 		if ((c = *p++) < ' ' || c > 0176) {
1031709Smlf 			c = ' ';
1041709Smlf 		}
1051709Smlf 		*s++ = (char)c;
1061709Smlf 	}
1071709Smlf 	*s++ = 0;
1081709Smlf }
1091709Smlf 
1101709Smlf static char *
gda_name(uchar_t cmd,char ** cmdvec)1111709Smlf gda_name(uchar_t cmd, char **cmdvec)
1121709Smlf {
1131709Smlf 	while (*cmdvec != NULL) {
1141709Smlf 		if (cmd == **cmdvec) {
1151709Smlf 			return (*cmdvec + 1);
1161709Smlf 		}
1171709Smlf 		cmdvec++;
1181709Smlf 	}
1191709Smlf 	return ("<undecoded cmd>");
1201709Smlf }
1211709Smlf 
1221709Smlf 
1231709Smlf struct cmpkt *
gda_pktprep(opaque_t objp,struct cmpkt * in_pktp,opaque_t dmatoken,int (* callback)(caddr_t),caddr_t arg)1241709Smlf gda_pktprep(opaque_t objp, struct cmpkt *in_pktp, opaque_t dmatoken,
1251709Smlf 	int (*callback)(caddr_t), caddr_t arg)
1261709Smlf {
1271709Smlf 	register struct	cmpkt *pktp;
1281709Smlf 	register struct	buf *bp = (struct buf *)dmatoken;
1291709Smlf 
1301709Smlf 	if (in_pktp) {
1311709Smlf 		pktp = in_pktp;
1321709Smlf 	} else {
1331709Smlf 		pktp = CTL_PKTALLOC(objp, callback, arg);
1341709Smlf 		if (pktp == NULL)
1351709Smlf 			return (NULL);
1361709Smlf 	}
1371709Smlf 
1381709Smlf 	if (bp) {
1391709Smlf 		if (bp->b_bcount) {
1401709Smlf 			if (CTL_MEMSETUP(objp, pktp, bp, callback, arg) ==
1411709Smlf 			    NULL) {
1421709Smlf 				if (!in_pktp)
1431709Smlf 					CTL_PKTFREE(objp, pktp);
1441709Smlf 				return (NULL);
1451709Smlf 			}
1461709Smlf 		}
1471709Smlf 		bp->av_back = (struct buf *)pktp;
1481709Smlf 		pktp->cp_bp = bp;
1491709Smlf 	}
1501709Smlf 	pktp->cp_retry = 0;
1511709Smlf 	pktp->cp_objp  = objp;
1521709Smlf 
1531709Smlf 
1541709Smlf #ifdef GDA_DEBUG
1551709Smlf 	if (gda_debug & DPKT)
1561709Smlf 		PRF("gda_pktprep: pktp=0x%x \n", pktp);
1571709Smlf #endif
1581709Smlf 	return (pktp);
1591709Smlf }
1601709Smlf 
1611709Smlf void
gda_free(opaque_t objp,struct cmpkt * pktp,struct buf * bp)1621709Smlf gda_free(opaque_t objp, struct cmpkt *pktp, struct buf *bp)
1631709Smlf {
1641709Smlf 	if (pktp) {
1651709Smlf 		CTL_MEMFREE(objp, pktp);
1661709Smlf 		CTL_PKTFREE(objp, pktp);
1671709Smlf 	}
1681709Smlf 
1691709Smlf 	if (bp) {
1701709Smlf 		if (bp->b_un.b_addr)
1711900Seota 			i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1721709Smlf 		freerbuf(bp);
1731709Smlf 	}
1741709Smlf }
1751709Smlf 
1761709Smlf void
gda_log(dev_info_t * dev,char * label,uint_t level,const char * fmt,...)1771709Smlf gda_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...)
1781709Smlf {
1791709Smlf 	auto char name[256];
1801709Smlf 	auto char buf [256];
1811709Smlf 	va_list ap;
1821709Smlf 	int log_only = 0;
1831709Smlf 	int boot_only = 0;
1841709Smlf 	int console_only = 0;
1851709Smlf 
1861709Smlf 	switch (*fmt) {
1871709Smlf 	case '!':
1881709Smlf 		log_only = 1;
1891709Smlf 		fmt++;
1901709Smlf 		break;
1911709Smlf 	case '?':
1921709Smlf 		boot_only = 1;
1931709Smlf 		fmt++;
1941709Smlf 		break;
1951709Smlf 	case '^':
1961709Smlf 		console_only = 1;
1971709Smlf 		fmt++;
1981709Smlf 		break;
1991709Smlf 	}
2001709Smlf 
2011709Smlf 
2021709Smlf 	if (dev) {
2031709Smlf 		if (level == CE_PANIC || level == CE_WARN) {
2041709Smlf 			(void) sprintf(name, "%s (%s%d):\n",
205*7563SPrasad.Singamsetty@Sun.COM 			    ddi_pathname(dev, buf), label,
206*7563SPrasad.Singamsetty@Sun.COM 			    ddi_get_instance(dev));
2071709Smlf 		} else if (level == CE_NOTE ||
2081709Smlf 		    level >= (uint_t)SCSI_DEBUG) {
2091709Smlf 			(void) sprintf(name,
2101709Smlf 			    "%s%d:", label, ddi_get_instance(dev));
2111709Smlf 		} else if (level == CE_CONT) {
2121709Smlf 			name[0] = '\0';
2131709Smlf 		}
2141709Smlf 	} else {
2151709Smlf 		(void) sprintf(name, "%s:", label);
2161709Smlf 	}
2171709Smlf 
2181709Smlf 	va_start(ap, fmt);
2191709Smlf 	(void) vsprintf(buf, fmt, ap);
2201709Smlf 	va_end(ap);
2211709Smlf 
2221709Smlf 	switch (level) {
2231709Smlf 		case CE_NOTE:
2241709Smlf 			level = CE_CONT;
2251709Smlf 			/* FALLTHROUGH */
2261709Smlf 		case CE_CONT:
2271709Smlf 		case CE_WARN:
2281709Smlf 		case CE_PANIC:
2291709Smlf 			if (boot_only) {
2301709Smlf 				cmn_err(level, "?%s\t%s", name, buf);
2311709Smlf 			} else if (console_only) {
2321709Smlf 				cmn_err(level, "^%s\t%s", name, buf);
2331709Smlf 			} else if (log_only) {
2341709Smlf 				cmn_err(level, "!%s\t%s", name, buf);
2351709Smlf 			} else {
2361709Smlf 				cmn_err(level, "%s\t%s", name, buf);
2371709Smlf 			}
2381709Smlf 			break;
2391709Smlf 		default:
2401709Smlf 			cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, buf);
2411709Smlf 			break;
2421709Smlf 	}
2431709Smlf }
2441709Smlf 
2451709Smlf void
gda_errmsg(struct scsi_device * devp,struct cmpkt * pktp,char * label,int severity,daddr_t blkno,daddr_t err_blkno,char ** cmdvec,char ** senvec)2461709Smlf gda_errmsg(struct scsi_device *devp, struct cmpkt *pktp, char *label,
247*7563SPrasad.Singamsetty@Sun.COM     int severity, daddr_t blkno, daddr_t err_blkno,
2481709Smlf     char **cmdvec, char **senvec)
2491709Smlf {
2501709Smlf 	auto char buf[256];
2511709Smlf 	dev_info_t *dev = devp->sd_dev;
2521709Smlf 	static char *error_classes[] = {
2531709Smlf 		"All", "Unknown", "Informational",
2541709Smlf 		"Recovered", "Retryable", "Fatal"
2551709Smlf 	};
2561709Smlf 
2571709Smlf 	bzero((caddr_t)buf, 256);
2581709Smlf 	(void) sprintf(buf, "Error for command '%s'\tError Level: %s",
259*7563SPrasad.Singamsetty@Sun.COM 	    gda_name(*(uchar_t *)pktp->cp_cdbp, cmdvec),
260*7563SPrasad.Singamsetty@Sun.COM 	    error_classes[severity]);
2611709Smlf 	gda_log(dev, label, CE_WARN, buf);
2621709Smlf 
2631709Smlf 	bzero((caddr_t)buf, 256);
2641709Smlf 	if ((blkno != -1) && (err_blkno != -1)) {
265*7563SPrasad.Singamsetty@Sun.COM 		(void) sprintf(buf, "Requested Block %ld, Error Block: %ld\n",
2661709Smlf 		    blkno, err_blkno);
2671709Smlf 		gda_log(dev, label, CE_CONT, buf);
2681709Smlf 	}
2691709Smlf 
2701709Smlf 	bzero((caddr_t)buf, 256);
2711709Smlf 	(void) sprintf(buf, "Sense Key: %s\n",
272*7563SPrasad.Singamsetty@Sun.COM 	    gda_name(*(uchar_t *)pktp->cp_scbp, senvec));
2731709Smlf 
2741709Smlf 	gda_log(dev, label, CE_CONT, buf);
2751709Smlf 	bzero((caddr_t)buf, 256);
2761709Smlf 	(void) strcpy(buf, "Vendor '");
2771709Smlf 	gda_inqfill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]);
2781709Smlf 	(void) sprintf(&buf[strlen(buf)],
279*7563SPrasad.Singamsetty@Sun.COM 	    "' error code: 0x%x",
280*7563SPrasad.Singamsetty@Sun.COM 	    *(uchar_t *)pktp->cp_scbp);
2811709Smlf 	gda_log(dev, label, CE_CONT, "%s\n", buf);
2821709Smlf }
283