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