xref: /titanic_44/usr/src/uts/i86pc/io/dr/dr_util.c (revision a31148363f598def767ac48c5d82e1572e44b935)
1*a3114836SGerry Liu /*
2*a3114836SGerry Liu  * CDDL HEADER START
3*a3114836SGerry Liu  *
4*a3114836SGerry Liu  * The contents of this file are subject to the terms of the
5*a3114836SGerry Liu  * Common Development and Distribution License (the "License").
6*a3114836SGerry Liu  * You may not use this file except in compliance with the License.
7*a3114836SGerry Liu  *
8*a3114836SGerry Liu  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*a3114836SGerry Liu  * or http://www.opensolaris.org/os/licensing.
10*a3114836SGerry Liu  * See the License for the specific language governing permissions
11*a3114836SGerry Liu  * and limitations under the License.
12*a3114836SGerry Liu  *
13*a3114836SGerry Liu  * When distributing Covered Code, include this CDDL HEADER in each
14*a3114836SGerry Liu  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*a3114836SGerry Liu  * If applicable, add the following below this CDDL HEADER, with the
16*a3114836SGerry Liu  * fields enclosed by brackets "[]" replaced with your own identifying
17*a3114836SGerry Liu  * information: Portions Copyright [yyyy] [name of copyright owner]
18*a3114836SGerry Liu  *
19*a3114836SGerry Liu  * CDDL HEADER END
20*a3114836SGerry Liu  */
21*a3114836SGerry Liu 
22*a3114836SGerry Liu /*
23*a3114836SGerry Liu  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*a3114836SGerry Liu  * Use is subject to license terms.
25*a3114836SGerry Liu  */
26*a3114836SGerry Liu 
27*a3114836SGerry Liu #include <sys/types.h>
28*a3114836SGerry Liu #include <sys/cmn_err.h>
29*a3114836SGerry Liu #include <sys/param.h>		/* for NULL */
30*a3114836SGerry Liu #include <sys/sbd_ioctl.h>
31*a3114836SGerry Liu #include <sys/dr_util.h>
32*a3114836SGerry Liu #include <sys/varargs.h>
33*a3114836SGerry Liu #include <sys/sysmacros.h>
34*a3114836SGerry Liu #include <sys/systm.h>
35*a3114836SGerry Liu 
36*a3114836SGerry Liu /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
37*a3114836SGerry Liu extern sbd_etab_t sbd_etab[];
38*a3114836SGerry Liu extern int sbd_etab_len;
39*a3114836SGerry Liu 
40*a3114836SGerry Liu sbd_error_t *
sbd_err_new(int e_code,char * fmt,va_list args)41*a3114836SGerry Liu sbd_err_new(int e_code, char *fmt, va_list args)
42*a3114836SGerry Liu {
43*a3114836SGerry Liu 	sbd_error_t	*new;
44*a3114836SGerry Liu 
45*a3114836SGerry Liu 	new = GETSTRUCT(sbd_error_t, 1);
46*a3114836SGerry Liu 	new->e_code = e_code;
47*a3114836SGerry Liu 
48*a3114836SGerry Liu 	if (fmt)
49*a3114836SGerry Liu 		(void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
50*a3114836SGerry Liu 
51*a3114836SGerry Liu 	return (new);
52*a3114836SGerry Liu }
53*a3114836SGerry Liu 
54*a3114836SGerry Liu void
sbd_err_log(sbd_error_t * ep,int ce)55*a3114836SGerry Liu sbd_err_log(sbd_error_t *ep, int ce)
56*a3114836SGerry Liu {
57*a3114836SGerry Liu 	char		 buf[32];
58*a3114836SGerry Liu 	char		*fmt;
59*a3114836SGerry Liu 	char		*txt;
60*a3114836SGerry Liu 	int		 i;
61*a3114836SGerry Liu 	sbd_etab_t	*tp;
62*a3114836SGerry Liu 
63*a3114836SGerry Liu 	if (!ep)
64*a3114836SGerry Liu 		return;
65*a3114836SGerry Liu 
66*a3114836SGerry Liu 	if (ep->e_rsc[0] == '\0')
67*a3114836SGerry Liu 		fmt = "%s";
68*a3114836SGerry Liu 	else
69*a3114836SGerry Liu 		fmt = "%s: %s";
70*a3114836SGerry Liu 
71*a3114836SGerry Liu 	for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
72*a3114836SGerry Liu 		if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
73*a3114836SGerry Liu 			break;
74*a3114836SGerry Liu 
75*a3114836SGerry Liu 	if (i < sbd_etab_len)
76*a3114836SGerry Liu 		txt = tp->t_text[ep->e_code - tp->t_base];
77*a3114836SGerry Liu 	else {
78*a3114836SGerry Liu 		(void) snprintf(buf, sizeof (buf), "error %d", ep->e_code);
79*a3114836SGerry Liu 		txt = buf;
80*a3114836SGerry Liu 	}
81*a3114836SGerry Liu 
82*a3114836SGerry Liu 	cmn_err(ce, fmt, txt, ep->e_rsc);
83*a3114836SGerry Liu }
84*a3114836SGerry Liu 
85*a3114836SGerry Liu void
sbd_err_clear(sbd_error_t ** ep)86*a3114836SGerry Liu sbd_err_clear(sbd_error_t **ep)
87*a3114836SGerry Liu {
88*a3114836SGerry Liu 	FREESTRUCT(*ep, sbd_error_t, 1);
89*a3114836SGerry Liu 	*ep = NULL;
90*a3114836SGerry Liu }
91*a3114836SGerry Liu 
92*a3114836SGerry Liu void
sbd_err_set_c(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)93*a3114836SGerry Liu sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
94*a3114836SGerry Liu {
95*a3114836SGerry Liu 	sbd_error_t	*tmp;
96*a3114836SGerry Liu 	va_list		args;
97*a3114836SGerry Liu 
98*a3114836SGerry Liu 	va_start(args, fmt);
99*a3114836SGerry Liu 
100*a3114836SGerry Liu 	tmp = sbd_err_new(e_code, fmt, args);
101*a3114836SGerry Liu 
102*a3114836SGerry Liu 	sbd_err_log(tmp, ce);
103*a3114836SGerry Liu 
104*a3114836SGerry Liu 	if (*ep == NULL)
105*a3114836SGerry Liu 		*ep = tmp;
106*a3114836SGerry Liu 	else
107*a3114836SGerry Liu 		sbd_err_clear(&tmp);
108*a3114836SGerry Liu 
109*a3114836SGerry Liu 	va_end(args);
110*a3114836SGerry Liu }
111*a3114836SGerry Liu 
112*a3114836SGerry Liu void
sbd_err_set(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)113*a3114836SGerry Liu sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
114*a3114836SGerry Liu {
115*a3114836SGerry Liu 	sbd_error_t	*tmp;
116*a3114836SGerry Liu 	va_list		args;
117*a3114836SGerry Liu 
118*a3114836SGerry Liu 	va_start(args, fmt);
119*a3114836SGerry Liu 
120*a3114836SGerry Liu 	tmp = sbd_err_new(e_code, fmt, args);
121*a3114836SGerry Liu 
122*a3114836SGerry Liu 	sbd_err_log(tmp, ce);
123*a3114836SGerry Liu 
124*a3114836SGerry Liu 	*ep = tmp;
125*a3114836SGerry Liu 
126*a3114836SGerry Liu 	va_end(args);
127*a3114836SGerry Liu }
128*a3114836SGerry Liu 
129*a3114836SGerry Liu sbd_error_t *
drerr_new_v(int e_code,char * fmt,va_list args)130*a3114836SGerry Liu drerr_new_v(int e_code, char *fmt, va_list args)
131*a3114836SGerry Liu {
132*a3114836SGerry Liu 	return (sbd_err_new(e_code, fmt, args));
133*a3114836SGerry Liu }
134*a3114836SGerry Liu 
135*a3114836SGerry Liu sbd_error_t *
drerr_new(int log,int e_code,char * fmt,...)136*a3114836SGerry Liu drerr_new(int log, int e_code, char *fmt, ...)
137*a3114836SGerry Liu {
138*a3114836SGerry Liu 	sbd_error_t	*ep;
139*a3114836SGerry Liu 	va_list		 args;
140*a3114836SGerry Liu 
141*a3114836SGerry Liu 	va_start(args, fmt);
142*a3114836SGerry Liu 	ep = sbd_err_new(e_code, fmt, args);
143*a3114836SGerry Liu 	va_end(args);
144*a3114836SGerry Liu 
145*a3114836SGerry Liu 	if (log)
146*a3114836SGerry Liu 		sbd_err_log(ep, CE_WARN);
147*a3114836SGerry Liu 
148*a3114836SGerry Liu 	return (ep);
149*a3114836SGerry Liu }
150*a3114836SGerry Liu 
151*a3114836SGerry Liu void
drerr_set_c(int log,sbd_error_t ** ep,int e_code,char * fmt,...)152*a3114836SGerry Liu drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
153*a3114836SGerry Liu {
154*a3114836SGerry Liu 	sbd_error_t	*err;
155*a3114836SGerry Liu 	va_list		 args;
156*a3114836SGerry Liu 
157*a3114836SGerry Liu 	va_start(args, fmt);
158*a3114836SGerry Liu 	err = sbd_err_new(e_code, fmt, args);
159*a3114836SGerry Liu 	va_end(args);
160*a3114836SGerry Liu 
161*a3114836SGerry Liu 	if (log)
162*a3114836SGerry Liu 		sbd_err_log(err, CE_WARN);
163*a3114836SGerry Liu 
164*a3114836SGerry Liu 	if (*ep == NULL)
165*a3114836SGerry Liu 		*ep = err;
166*a3114836SGerry Liu 	else
167*a3114836SGerry Liu 		sbd_err_clear(&err);
168*a3114836SGerry Liu }
169*a3114836SGerry Liu 
170*a3114836SGerry Liu 
171*a3114836SGerry Liu /*
172*a3114836SGerry Liu  * Memlist support.
173*a3114836SGerry Liu  */
174*a3114836SGerry Liu void
dr_memlist_delete(struct memlist * mlist)175*a3114836SGerry Liu dr_memlist_delete(struct memlist *mlist)
176*a3114836SGerry Liu {
177*a3114836SGerry Liu 	register struct memlist	*ml;
178*a3114836SGerry Liu 
179*a3114836SGerry Liu 	for (ml = mlist; ml; ml = mlist) {
180*a3114836SGerry Liu 		mlist = ml->ml_next;
181*a3114836SGerry Liu 		FREESTRUCT(ml, struct memlist, 1);
182*a3114836SGerry Liu 	}
183*a3114836SGerry Liu }
184*a3114836SGerry Liu 
185*a3114836SGerry Liu int
dr_memlist_intersect(struct memlist * al,struct memlist * bl)186*a3114836SGerry Liu dr_memlist_intersect(struct memlist *al, struct memlist *bl)
187*a3114836SGerry Liu {
188*a3114836SGerry Liu 	uint64_t	astart, aend, bstart, bend;
189*a3114836SGerry Liu 
190*a3114836SGerry Liu 	if ((al == NULL) || (bl == NULL))
191*a3114836SGerry Liu 		return (0);
192*a3114836SGerry Liu 
193*a3114836SGerry Liu 	aend = al->ml_address + al->ml_size;
194*a3114836SGerry Liu 	bstart = bl->ml_address;
195*a3114836SGerry Liu 	bend = bl->ml_address + bl->ml_size;
196*a3114836SGerry Liu 
197*a3114836SGerry Liu 	while (al && bl) {
198*a3114836SGerry Liu 		while (al && (aend <= bstart))
199*a3114836SGerry Liu 			if ((al = al->ml_next) != NULL)
200*a3114836SGerry Liu 				aend = al->ml_address + al->ml_size;
201*a3114836SGerry Liu 		if (al == NULL)
202*a3114836SGerry Liu 			return (0);
203*a3114836SGerry Liu 
204*a3114836SGerry Liu 		if ((astart = al->ml_address) <= bstart)
205*a3114836SGerry Liu 			return (1);
206*a3114836SGerry Liu 
207*a3114836SGerry Liu 		while (bl && (bend <= astart))
208*a3114836SGerry Liu 			if ((bl = bl->ml_next) != NULL)
209*a3114836SGerry Liu 				bend = bl->ml_address + bl->ml_size;
210*a3114836SGerry Liu 		if (bl == NULL)
211*a3114836SGerry Liu 			return (0);
212*a3114836SGerry Liu 
213*a3114836SGerry Liu 		if ((bstart = bl->ml_address) <= astart)
214*a3114836SGerry Liu 			return (1);
215*a3114836SGerry Liu 	}
216*a3114836SGerry Liu 
217*a3114836SGerry Liu 	return (0);
218*a3114836SGerry Liu }
219*a3114836SGerry Liu 
220*a3114836SGerry Liu void
dr_memlist_coalesce(struct memlist * mlist)221*a3114836SGerry Liu dr_memlist_coalesce(struct memlist *mlist)
222*a3114836SGerry Liu {
223*a3114836SGerry Liu 	uint64_t	end, nend;
224*a3114836SGerry Liu 
225*a3114836SGerry Liu 	if ((mlist == NULL) || (mlist->ml_next == NULL))
226*a3114836SGerry Liu 		return;
227*a3114836SGerry Liu 
228*a3114836SGerry Liu 	while (mlist->ml_next) {
229*a3114836SGerry Liu 		end = mlist->ml_address + mlist->ml_size;
230*a3114836SGerry Liu 		if (mlist->ml_next->ml_address <= end) {
231*a3114836SGerry Liu 			struct memlist 	*nl;
232*a3114836SGerry Liu 
233*a3114836SGerry Liu 			nend = mlist->ml_next->ml_address +
234*a3114836SGerry Liu 			    mlist->ml_next->ml_size;
235*a3114836SGerry Liu 			if (nend > end)
236*a3114836SGerry Liu 				mlist->ml_size += (nend - end);
237*a3114836SGerry Liu 			nl = mlist->ml_next;
238*a3114836SGerry Liu 			mlist->ml_next = mlist->ml_next->ml_next;
239*a3114836SGerry Liu 			if (nl) {
240*a3114836SGerry Liu 				FREESTRUCT(nl, struct memlist, 1);
241*a3114836SGerry Liu 			}
242*a3114836SGerry Liu 			if (mlist->ml_next)
243*a3114836SGerry Liu 				mlist->ml_next->ml_prev = mlist;
244*a3114836SGerry Liu 		} else {
245*a3114836SGerry Liu 			mlist = mlist->ml_next;
246*a3114836SGerry Liu 		}
247*a3114836SGerry Liu 	}
248*a3114836SGerry Liu }
249*a3114836SGerry Liu 
250*a3114836SGerry Liu #ifdef DEBUG
251*a3114836SGerry Liu void
memlist_dump(struct memlist * mlist)252*a3114836SGerry Liu memlist_dump(struct memlist *mlist)
253*a3114836SGerry Liu {
254*a3114836SGerry Liu 	register struct memlist *ml;
255*a3114836SGerry Liu 
256*a3114836SGerry Liu 	if (mlist == NULL)
257*a3114836SGerry Liu 		printf("memlist> EMPTY\n");
258*a3114836SGerry Liu 	else for (ml = mlist; ml; ml = ml->ml_next)
259*a3114836SGerry Liu 		printf("memlist> 0x%" PRIx64 ", 0x%" PRIx64 "\n",
260*a3114836SGerry Liu 		    ml->ml_address, ml->ml_size);
261*a3114836SGerry Liu }
262*a3114836SGerry Liu #endif
263*a3114836SGerry Liu 
264*a3114836SGerry Liu struct memlist *
dr_memlist_dup(struct memlist * mlist)265*a3114836SGerry Liu dr_memlist_dup(struct memlist *mlist)
266*a3114836SGerry Liu {
267*a3114836SGerry Liu 	struct memlist *hl = NULL, *tl, **mlp;
268*a3114836SGerry Liu 
269*a3114836SGerry Liu 	if (mlist == NULL)
270*a3114836SGerry Liu 		return (NULL);
271*a3114836SGerry Liu 
272*a3114836SGerry Liu 	mlp = &hl;
273*a3114836SGerry Liu 	tl = *mlp;
274*a3114836SGerry Liu 	for (; mlist; mlist = mlist->ml_next) {
275*a3114836SGerry Liu 		*mlp = GETSTRUCT(struct memlist, 1);
276*a3114836SGerry Liu 		(*mlp)->ml_address = mlist->ml_address;
277*a3114836SGerry Liu 		(*mlp)->ml_size = mlist->ml_size;
278*a3114836SGerry Liu 		(*mlp)->ml_prev = tl;
279*a3114836SGerry Liu 		tl = *mlp;
280*a3114836SGerry Liu 		mlp = &((*mlp)->ml_next);
281*a3114836SGerry Liu 	}
282*a3114836SGerry Liu 	*mlp = NULL;
283*a3114836SGerry Liu 
284*a3114836SGerry Liu 	return (hl);
285*a3114836SGerry Liu }
286*a3114836SGerry Liu 
287*a3114836SGerry Liu struct memlist *
dr_memlist_add_span(struct memlist * mlist,uint64_t base,uint64_t len)288*a3114836SGerry Liu dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len)
289*a3114836SGerry Liu {
290*a3114836SGerry Liu 	struct memlist	*ml, *tl, *nl;
291*a3114836SGerry Liu 
292*a3114836SGerry Liu 	if (len == 0ull)
293*a3114836SGerry Liu 		return (NULL);
294*a3114836SGerry Liu 
295*a3114836SGerry Liu 	if (mlist == NULL) {
296*a3114836SGerry Liu 		mlist = GETSTRUCT(struct memlist, 1);
297*a3114836SGerry Liu 		mlist->ml_address = base;
298*a3114836SGerry Liu 		mlist->ml_size = len;
299*a3114836SGerry Liu 		mlist->ml_next = mlist->ml_prev = NULL;
300*a3114836SGerry Liu 
301*a3114836SGerry Liu 		return (mlist);
302*a3114836SGerry Liu 	}
303*a3114836SGerry Liu 
304*a3114836SGerry Liu 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
305*a3114836SGerry Liu 		if (base < ml->ml_address) {
306*a3114836SGerry Liu 			if ((base + len) < ml->ml_address) {
307*a3114836SGerry Liu 				nl = GETSTRUCT(struct memlist, 1);
308*a3114836SGerry Liu 				nl->ml_address = base;
309*a3114836SGerry Liu 				nl->ml_size = len;
310*a3114836SGerry Liu 				nl->ml_next = ml;
311*a3114836SGerry Liu 				if ((nl->ml_prev = ml->ml_prev) != NULL)
312*a3114836SGerry Liu 					nl->ml_prev->ml_next = nl;
313*a3114836SGerry Liu 				ml->ml_prev = nl;
314*a3114836SGerry Liu 				if (mlist == ml)
315*a3114836SGerry Liu 					mlist = nl;
316*a3114836SGerry Liu 			} else {
317*a3114836SGerry Liu 				ml->ml_size = MAX((base + len),
318*a3114836SGerry Liu 				    (ml->ml_address + ml->ml_size)) - base;
319*a3114836SGerry Liu 				ml->ml_address = base;
320*a3114836SGerry Liu 			}
321*a3114836SGerry Liu 			break;
322*a3114836SGerry Liu 
323*a3114836SGerry Liu 		} else if (base <= (ml->ml_address + ml->ml_size)) {
324*a3114836SGerry Liu 			ml->ml_size = MAX((base + len),
325*a3114836SGerry Liu 			    (ml->ml_address + ml->ml_size)) -
326*a3114836SGerry Liu 			    MIN(ml->ml_address, base);
327*a3114836SGerry Liu 			ml->ml_address = MIN(ml->ml_address, base);
328*a3114836SGerry Liu 			break;
329*a3114836SGerry Liu 		}
330*a3114836SGerry Liu 	}
331*a3114836SGerry Liu 	if (ml == NULL) {
332*a3114836SGerry Liu 		nl = GETSTRUCT(struct memlist, 1);
333*a3114836SGerry Liu 		nl->ml_address = base;
334*a3114836SGerry Liu 		nl->ml_size = len;
335*a3114836SGerry Liu 		nl->ml_next = NULL;
336*a3114836SGerry Liu 		nl->ml_prev = tl;
337*a3114836SGerry Liu 		tl->ml_next = nl;
338*a3114836SGerry Liu 	}
339*a3114836SGerry Liu 
340*a3114836SGerry Liu 	dr_memlist_coalesce(mlist);
341*a3114836SGerry Liu 
342*a3114836SGerry Liu 	return (mlist);
343*a3114836SGerry Liu }
344*a3114836SGerry Liu 
345*a3114836SGerry Liu struct memlist *
dr_memlist_del_span(struct memlist * mlist,uint64_t base,uint64_t len)346*a3114836SGerry Liu dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
347*a3114836SGerry Liu {
348*a3114836SGerry Liu 	uint64_t	end;
349*a3114836SGerry Liu 	struct memlist	*ml, *tl, *nlp;
350*a3114836SGerry Liu 
351*a3114836SGerry Liu 	if (mlist == NULL)
352*a3114836SGerry Liu 		return (NULL);
353*a3114836SGerry Liu 
354*a3114836SGerry Liu 	end = base + len;
355*a3114836SGerry Liu 	if ((end <= mlist->ml_address) || (base == end))
356*a3114836SGerry Liu 		return (mlist);
357*a3114836SGerry Liu 
358*a3114836SGerry Liu 	for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
359*a3114836SGerry Liu 		uint64_t	mend;
360*a3114836SGerry Liu 
361*a3114836SGerry Liu 		nlp = ml->ml_next;
362*a3114836SGerry Liu 
363*a3114836SGerry Liu 		if (end <= ml->ml_address)
364*a3114836SGerry Liu 			break;
365*a3114836SGerry Liu 
366*a3114836SGerry Liu 		mend = ml->ml_address + ml->ml_size;
367*a3114836SGerry Liu 		if (base < mend) {
368*a3114836SGerry Liu 			if (base <= ml->ml_address) {
369*a3114836SGerry Liu 				ml->ml_address = end;
370*a3114836SGerry Liu 				if (end >= mend)
371*a3114836SGerry Liu 					ml->ml_size = 0ull;
372*a3114836SGerry Liu 				else
373*a3114836SGerry Liu 					ml->ml_size = mend - ml->ml_address;
374*a3114836SGerry Liu 			} else {
375*a3114836SGerry Liu 				ml->ml_size = base - ml->ml_address;
376*a3114836SGerry Liu 				if (end < mend) {
377*a3114836SGerry Liu 					struct memlist	*nl;
378*a3114836SGerry Liu 					/*
379*a3114836SGerry Liu 					 * splitting an memlist entry.
380*a3114836SGerry Liu 					 */
381*a3114836SGerry Liu 					nl = GETSTRUCT(struct memlist, 1);
382*a3114836SGerry Liu 					nl->ml_address = end;
383*a3114836SGerry Liu 					nl->ml_size = mend - nl->ml_address;
384*a3114836SGerry Liu 					if ((nl->ml_next = nlp) != NULL)
385*a3114836SGerry Liu 						nlp->ml_prev = nl;
386*a3114836SGerry Liu 					nl->ml_prev = ml;
387*a3114836SGerry Liu 					ml->ml_next = nl;
388*a3114836SGerry Liu 					nlp = nl;
389*a3114836SGerry Liu 				}
390*a3114836SGerry Liu 			}
391*a3114836SGerry Liu 			if (ml->ml_size == 0ull) {
392*a3114836SGerry Liu 				if (ml == mlist) {
393*a3114836SGerry Liu 					if ((mlist = nlp) != NULL)
394*a3114836SGerry Liu 						nlp->ml_prev = NULL;
395*a3114836SGerry Liu 					FREESTRUCT(ml, struct memlist, 1);
396*a3114836SGerry Liu 					if (mlist == NULL)
397*a3114836SGerry Liu 						break;
398*a3114836SGerry Liu 					ml = nlp;
399*a3114836SGerry Liu 				} else {
400*a3114836SGerry Liu 					if ((tl->ml_next = nlp) != NULL)
401*a3114836SGerry Liu 						nlp->ml_prev = tl;
402*a3114836SGerry Liu 					FREESTRUCT(ml, struct memlist, 1);
403*a3114836SGerry Liu 					ml = tl;
404*a3114836SGerry Liu 				}
405*a3114836SGerry Liu 			}
406*a3114836SGerry Liu 		}
407*a3114836SGerry Liu 	}
408*a3114836SGerry Liu 
409*a3114836SGerry Liu 	return (mlist);
410*a3114836SGerry Liu }
411*a3114836SGerry Liu 
412*a3114836SGerry Liu /*
413*a3114836SGerry Liu  * add span without merging
414*a3114836SGerry Liu  */
415*a3114836SGerry Liu struct memlist *
dr_memlist_cat_span(struct memlist * mlist,uint64_t base,uint64_t len)416*a3114836SGerry Liu dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len)
417*a3114836SGerry Liu {
418*a3114836SGerry Liu 	struct memlist	*ml, *tl, *nl;
419*a3114836SGerry Liu 
420*a3114836SGerry Liu 	if (len == 0ull)
421*a3114836SGerry Liu 		return (NULL);
422*a3114836SGerry Liu 
423*a3114836SGerry Liu 	if (mlist == NULL) {
424*a3114836SGerry Liu 		mlist = GETSTRUCT(struct memlist, 1);
425*a3114836SGerry Liu 		mlist->ml_address = base;
426*a3114836SGerry Liu 		mlist->ml_size = len;
427*a3114836SGerry Liu 		mlist->ml_next = mlist->ml_prev = NULL;
428*a3114836SGerry Liu 
429*a3114836SGerry Liu 		return (mlist);
430*a3114836SGerry Liu 	}
431*a3114836SGerry Liu 
432*a3114836SGerry Liu 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
433*a3114836SGerry Liu 		if (base < ml->ml_address) {
434*a3114836SGerry Liu 			nl = GETSTRUCT(struct memlist, 1);
435*a3114836SGerry Liu 			nl->ml_address = base;
436*a3114836SGerry Liu 			nl->ml_size = len;
437*a3114836SGerry Liu 			nl->ml_next = ml;
438*a3114836SGerry Liu 			if ((nl->ml_prev = ml->ml_prev) != NULL)
439*a3114836SGerry Liu 				nl->ml_prev->ml_next = nl;
440*a3114836SGerry Liu 			ml->ml_prev = nl;
441*a3114836SGerry Liu 			if (mlist == ml)
442*a3114836SGerry Liu 				mlist = nl;
443*a3114836SGerry Liu 			break;
444*a3114836SGerry Liu 		}
445*a3114836SGerry Liu 	}
446*a3114836SGerry Liu 
447*a3114836SGerry Liu 	if (ml == NULL) {
448*a3114836SGerry Liu 		nl = GETSTRUCT(struct memlist, 1);
449*a3114836SGerry Liu 		nl->ml_address = base;
450*a3114836SGerry Liu 		nl->ml_size = len;
451*a3114836SGerry Liu 		nl->ml_next = NULL;
452*a3114836SGerry Liu 		nl->ml_prev = tl;
453*a3114836SGerry Liu 		tl->ml_next = nl;
454*a3114836SGerry Liu 	}
455*a3114836SGerry Liu 
456*a3114836SGerry Liu 	return (mlist);
457*a3114836SGerry Liu }
458