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