xref: /illumos-gate/usr/src/uts/sun4u/ngdr/io/dr_util.c (revision 141040e8a310da49386b596573e5dde5580572ec)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/cmn_err.h>
31 #include <sys/param.h>		/* for NULL */
32 #include <sys/sbd_ioctl.h>
33 #include <sys/dr_util.h>
34 #include <sys/varargs.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 
38 /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
39 extern sbd_etab_t sbd_etab[];
40 extern int sbd_etab_len;
41 
42 sbd_error_t *
43 sbd_err_new(int e_code, char *fmt, va_list args)
44 {
45 	sbd_error_t	*new;
46 
47 	new = GETSTRUCT(sbd_error_t, 1);
48 	new->e_code = e_code;
49 
50 	if (fmt)
51 		(void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
52 
53 	return (new);
54 }
55 
56 void
57 sbd_err_log(sbd_error_t *ep, int ce)
58 {
59 	char		 buf[32];
60 	char		*fmt;
61 	char		*txt;
62 	int		 i;
63 	sbd_etab_t	*tp;
64 
65 	if (!ep)
66 		return;
67 
68 	if (ep->e_rsc[0] == '\0')
69 		fmt = "%s";
70 	else
71 		fmt = "%s: %s";
72 
73 	for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
74 		if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
75 			break;
76 
77 	if (i < sbd_etab_len)
78 		txt = tp->t_text[ep->e_code - tp->t_base];
79 	else {
80 		snprintf(buf, sizeof (buf), "error %d", ep->e_code);
81 		txt = buf;
82 	}
83 
84 	cmn_err(ce, fmt, txt, ep->e_rsc);
85 }
86 
87 void
88 sbd_err_clear(sbd_error_t **ep)
89 {
90 	FREESTRUCT(*ep, sbd_error_t, 1);
91 	*ep = NULL;
92 }
93 
94 void
95 sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
96 {
97 	sbd_error_t	*tmp;
98 	va_list		args;
99 
100 	va_start(args, fmt);
101 
102 	tmp = sbd_err_new(e_code, fmt, args);
103 
104 	sbd_err_log(tmp, ce);
105 
106 	if (*ep == NULL)
107 		*ep = tmp;
108 	else
109 		sbd_err_clear(&tmp);
110 
111 	va_end(args);
112 }
113 
114 void
115 sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
116 {
117 	sbd_error_t	*tmp;
118 	va_list		args;
119 
120 	va_start(args, fmt);
121 
122 	tmp = sbd_err_new(e_code, fmt, args);
123 
124 	sbd_err_log(tmp, ce);
125 
126 	*ep = tmp;
127 
128 	va_end(args);
129 }
130 
131 sbd_error_t *
132 drerr_new_v(int e_code, char *fmt, va_list args)
133 {
134 	return (sbd_err_new(e_code, fmt, args));
135 }
136 
137 sbd_error_t *
138 drerr_new(int log, int e_code, char *fmt, ...)
139 {
140 	sbd_error_t	*ep;
141 	va_list		 args;
142 
143 	va_start(args, fmt);
144 	ep = sbd_err_new(e_code, fmt, args);
145 	va_end(args);
146 
147 	if (log)
148 		sbd_err_log(ep, CE_WARN);
149 
150 	return (ep);
151 }
152 
153 void
154 drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
155 {
156 	sbd_error_t	*err;
157 	va_list		 args;
158 
159 	va_start(args, fmt);
160 	err = sbd_err_new(e_code, fmt, args);
161 	va_end(args);
162 
163 	if (log)
164 		sbd_err_log(err, CE_WARN);
165 
166 	if (*ep == NULL)
167 		*ep = err;
168 	else
169 		sbd_err_clear(&err);
170 }
171 
172 
173 /*
174  * Memlist support.
175  */
176 void
177 memlist_delete(struct memlist *mlist)
178 {
179 	register struct memlist	*ml;
180 
181 	for (ml = mlist; ml; ml = mlist) {
182 		mlist = ml->next;
183 		FREESTRUCT(ml, struct memlist, 1);
184 	}
185 }
186 
187 int
188 memlist_intersect(struct memlist *al, struct memlist *bl)
189 {
190 	uint64_t	astart, aend, bstart, bend;
191 
192 	if ((al == NULL) || (bl == NULL))
193 		return (0);
194 
195 	aend = al->address + al->size;
196 	bstart = bl->address;
197 	bend = bl->address + bl->size;
198 
199 	while (al && bl) {
200 		while (al && (aend <= bstart))
201 			if ((al = al->next) != NULL)
202 				aend = al->address + al->size;
203 		if (al == NULL)
204 			return (0);
205 
206 		if ((astart = al->address) <= bstart)
207 			return (1);
208 
209 		while (bl && (bend <= astart))
210 			if ((bl = bl->next) != NULL)
211 				bend = bl->address + bl->size;
212 		if (bl == NULL)
213 			return (0);
214 
215 		if ((bstart = bl->address) <= astart)
216 			return (1);
217 	}
218 
219 	return (0);
220 }
221 
222 void
223 memlist_coalesce(struct memlist *mlist)
224 {
225 	uint64_t	end, nend;
226 
227 	if ((mlist == NULL) || (mlist->next == NULL))
228 		return;
229 
230 	while (mlist->next) {
231 		end = mlist->address + mlist->size;
232 		if (mlist->next->address <= end) {
233 			struct memlist 	*nl;
234 
235 			nend = mlist->next->address + mlist->next->size;
236 			if (nend > end)
237 				mlist->size += (nend - end);
238 			nl = mlist->next;
239 			mlist->next = mlist->next->next;
240 			if (nl) {
241 				FREESTRUCT(nl, struct memlist, 1);
242 			}
243 			if (mlist->next)
244 				mlist->next->prev = mlist;
245 		} else {
246 			mlist = mlist->next;
247 		}
248 	}
249 }
250 
251 #ifdef DEBUG
252 void
253 memlist_dump(struct memlist *mlist)
254 {
255 	register struct memlist *ml;
256 
257 	if (mlist == NULL)
258 		printf("memlist> EMPTY\n");
259 	else for (ml = mlist; ml; ml = ml->next)
260 		printf("memlist> 0x%lx, 0x%lx\n", ml->address, ml->size);
261 }
262 #endif
263