xref: /illumos-gate/usr/src/uts/sun4u/ngdr/io/dr_util.c (revision 56f33205)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
525cf1a30Sjl  * Common Development and Distribution License (the "License").
625cf1a30Sjl  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2107d06da5SSurya Prakki 
227c478bd9Sstevel@tonic-gate /*
23*56f33205SJonathan Adams  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
2404580fdfSmathue  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
297c478bd9Sstevel@tonic-gate #include <sys/param.h>		/* for NULL */
307c478bd9Sstevel@tonic-gate #include <sys/sbd_ioctl.h>
317c478bd9Sstevel@tonic-gate #include <sys/dr_util.h>
327c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/systm.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
377c478bd9Sstevel@tonic-gate extern sbd_etab_t sbd_etab[];
387c478bd9Sstevel@tonic-gate extern int sbd_etab_len;
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate sbd_error_t *
sbd_err_new(int e_code,char * fmt,va_list args)417c478bd9Sstevel@tonic-gate sbd_err_new(int e_code, char *fmt, va_list args)
427c478bd9Sstevel@tonic-gate {
437c478bd9Sstevel@tonic-gate 	sbd_error_t	*new;
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate 	new = GETSTRUCT(sbd_error_t, 1);
467c478bd9Sstevel@tonic-gate 	new->e_code = e_code;
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	if (fmt)
497c478bd9Sstevel@tonic-gate 		(void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate 	return (new);
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate void
sbd_err_log(sbd_error_t * ep,int ce)557c478bd9Sstevel@tonic-gate sbd_err_log(sbd_error_t *ep, int ce)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	char		 buf[32];
587c478bd9Sstevel@tonic-gate 	char		*fmt;
597c478bd9Sstevel@tonic-gate 	char		*txt;
607c478bd9Sstevel@tonic-gate 	int		 i;
617c478bd9Sstevel@tonic-gate 	sbd_etab_t	*tp;
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate 	if (!ep)
647c478bd9Sstevel@tonic-gate 		return;
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	if (ep->e_rsc[0] == '\0')
677c478bd9Sstevel@tonic-gate 		fmt = "%s";
687c478bd9Sstevel@tonic-gate 	else
697c478bd9Sstevel@tonic-gate 		fmt = "%s: %s";
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
727c478bd9Sstevel@tonic-gate 		if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
737c478bd9Sstevel@tonic-gate 			break;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	if (i < sbd_etab_len)
767c478bd9Sstevel@tonic-gate 		txt = tp->t_text[ep->e_code - tp->t_base];
777c478bd9Sstevel@tonic-gate 	else {
7807d06da5SSurya Prakki 		(void) snprintf(buf, sizeof (buf), "error %d", ep->e_code);
797c478bd9Sstevel@tonic-gate 		txt = buf;
807c478bd9Sstevel@tonic-gate 	}
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	cmn_err(ce, fmt, txt, ep->e_rsc);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate void
sbd_err_clear(sbd_error_t ** ep)867c478bd9Sstevel@tonic-gate sbd_err_clear(sbd_error_t **ep)
877c478bd9Sstevel@tonic-gate {
887c478bd9Sstevel@tonic-gate 	FREESTRUCT(*ep, sbd_error_t, 1);
897c478bd9Sstevel@tonic-gate 	*ep = NULL;
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate void
sbd_err_set_c(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)937c478bd9Sstevel@tonic-gate sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
947c478bd9Sstevel@tonic-gate {
957c478bd9Sstevel@tonic-gate 	sbd_error_t	*tmp;
967c478bd9Sstevel@tonic-gate 	va_list		args;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 	tmp = sbd_err_new(e_code, fmt, args);
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	sbd_err_log(tmp, ce);
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (*ep == NULL)
1057c478bd9Sstevel@tonic-gate 		*ep = tmp;
1067c478bd9Sstevel@tonic-gate 	else
1077c478bd9Sstevel@tonic-gate 		sbd_err_clear(&tmp);
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	va_end(args);
1107c478bd9Sstevel@tonic-gate }
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate void
sbd_err_set(sbd_error_t ** ep,int ce,int e_code,char * fmt,...)1137c478bd9Sstevel@tonic-gate sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	sbd_error_t	*tmp;
1167c478bd9Sstevel@tonic-gate 	va_list		args;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	tmp = sbd_err_new(e_code, fmt, args);
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	sbd_err_log(tmp, ce);
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	*ep = tmp;
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 	va_end(args);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate sbd_error_t *
drerr_new_v(int e_code,char * fmt,va_list args)1307c478bd9Sstevel@tonic-gate drerr_new_v(int e_code, char *fmt, va_list args)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	return (sbd_err_new(e_code, fmt, args));
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate sbd_error_t *
drerr_new(int log,int e_code,char * fmt,...)1367c478bd9Sstevel@tonic-gate drerr_new(int log, int e_code, char *fmt, ...)
1377c478bd9Sstevel@tonic-gate {
1387c478bd9Sstevel@tonic-gate 	sbd_error_t	*ep;
1397c478bd9Sstevel@tonic-gate 	va_list		 args;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
1427c478bd9Sstevel@tonic-gate 	ep = sbd_err_new(e_code, fmt, args);
1437c478bd9Sstevel@tonic-gate 	va_end(args);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	if (log)
1467c478bd9Sstevel@tonic-gate 		sbd_err_log(ep, CE_WARN);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	return (ep);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate void
drerr_set_c(int log,sbd_error_t ** ep,int e_code,char * fmt,...)1527c478bd9Sstevel@tonic-gate drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	sbd_error_t	*err;
1557c478bd9Sstevel@tonic-gate 	va_list		 args;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
1587c478bd9Sstevel@tonic-gate 	err = sbd_err_new(e_code, fmt, args);
1597c478bd9Sstevel@tonic-gate 	va_end(args);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	if (log)
1627c478bd9Sstevel@tonic-gate 		sbd_err_log(err, CE_WARN);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	if (*ep == NULL)
1657c478bd9Sstevel@tonic-gate 		*ep = err;
1667c478bd9Sstevel@tonic-gate 	else
1677c478bd9Sstevel@tonic-gate 		sbd_err_clear(&err);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate  * Memlist support.
1737c478bd9Sstevel@tonic-gate  */
1747c478bd9Sstevel@tonic-gate void
dr_memlist_delete(struct memlist * mlist)17525cf1a30Sjl dr_memlist_delete(struct memlist *mlist)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	register struct memlist	*ml;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	for (ml = mlist; ml; ml = mlist) {
180*56f33205SJonathan Adams 		mlist = ml->ml_next;
1817c478bd9Sstevel@tonic-gate 		FREESTRUCT(ml, struct memlist, 1);
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate int
dr_memlist_intersect(struct memlist * al,struct memlist * bl)18625cf1a30Sjl dr_memlist_intersect(struct memlist *al, struct memlist *bl)
1877c478bd9Sstevel@tonic-gate {
1887c478bd9Sstevel@tonic-gate 	uint64_t	astart, aend, bstart, bend;
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	if ((al == NULL) || (bl == NULL))
1917c478bd9Sstevel@tonic-gate 		return (0);
1927c478bd9Sstevel@tonic-gate 
193*56f33205SJonathan Adams 	aend = al->ml_address + al->ml_size;
194*56f33205SJonathan Adams 	bstart = bl->ml_address;
195*56f33205SJonathan Adams 	bend = bl->ml_address + bl->ml_size;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	while (al && bl) {
1987c478bd9Sstevel@tonic-gate 		while (al && (aend <= bstart))
199*56f33205SJonathan Adams 			if ((al = al->ml_next) != NULL)
200*56f33205SJonathan Adams 				aend = al->ml_address + al->ml_size;
2017c478bd9Sstevel@tonic-gate 		if (al == NULL)
2027c478bd9Sstevel@tonic-gate 			return (0);
2037c478bd9Sstevel@tonic-gate 
204*56f33205SJonathan Adams 		if ((astart = al->ml_address) <= bstart)
2057c478bd9Sstevel@tonic-gate 			return (1);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 		while (bl && (bend <= astart))
208*56f33205SJonathan Adams 			if ((bl = bl->ml_next) != NULL)
209*56f33205SJonathan Adams 				bend = bl->ml_address + bl->ml_size;
2107c478bd9Sstevel@tonic-gate 		if (bl == NULL)
2117c478bd9Sstevel@tonic-gate 			return (0);
2127c478bd9Sstevel@tonic-gate 
213*56f33205SJonathan Adams 		if ((bstart = bl->ml_address) <= astart)
2147c478bd9Sstevel@tonic-gate 			return (1);
2157c478bd9Sstevel@tonic-gate 	}
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate 	return (0);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate void
dr_memlist_coalesce(struct memlist * mlist)22125cf1a30Sjl dr_memlist_coalesce(struct memlist *mlist)
2227c478bd9Sstevel@tonic-gate {
2237c478bd9Sstevel@tonic-gate 	uint64_t	end, nend;
2247c478bd9Sstevel@tonic-gate 
225*56f33205SJonathan Adams 	if ((mlist == NULL) || (mlist->ml_next == NULL))
2267c478bd9Sstevel@tonic-gate 		return;
2277c478bd9Sstevel@tonic-gate 
228*56f33205SJonathan Adams 	while (mlist->ml_next) {
229*56f33205SJonathan Adams 		end = mlist->ml_address + mlist->ml_size;
230*56f33205SJonathan Adams 		if (mlist->ml_next->ml_address <= end) {
2317c478bd9Sstevel@tonic-gate 			struct memlist 	*nl;
2327c478bd9Sstevel@tonic-gate 
233*56f33205SJonathan Adams 			nend = mlist->ml_next->ml_address +
234*56f33205SJonathan Adams 			    mlist->ml_next->ml_size;
2357c478bd9Sstevel@tonic-gate 			if (nend > end)
236*56f33205SJonathan Adams 				mlist->ml_size += (nend - end);
237*56f33205SJonathan Adams 			nl = mlist->ml_next;
238*56f33205SJonathan Adams 			mlist->ml_next = mlist->ml_next->ml_next;
2397c478bd9Sstevel@tonic-gate 			if (nl) {
2407c478bd9Sstevel@tonic-gate 				FREESTRUCT(nl, struct memlist, 1);
2417c478bd9Sstevel@tonic-gate 			}
242*56f33205SJonathan Adams 			if (mlist->ml_next)
243*56f33205SJonathan Adams 				mlist->ml_next->ml_prev = mlist;
2447c478bd9Sstevel@tonic-gate 		} else {
245*56f33205SJonathan Adams 			mlist = mlist->ml_next;
2467c478bd9Sstevel@tonic-gate 		}
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate #ifdef DEBUG
2517c478bd9Sstevel@tonic-gate void
memlist_dump(struct memlist * mlist)2527c478bd9Sstevel@tonic-gate memlist_dump(struct memlist *mlist)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	register struct memlist *ml;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if (mlist == NULL)
2577c478bd9Sstevel@tonic-gate 		printf("memlist> EMPTY\n");
258*56f33205SJonathan Adams 	else for (ml = mlist; ml; ml = ml->ml_next)
259*56f33205SJonathan Adams 		printf("memlist> 0x%lx, 0x%lx\n", ml->ml_address, ml->ml_size);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate #endif
26225cf1a30Sjl 
26325cf1a30Sjl struct memlist *
dr_memlist_dup(struct memlist * mlist)26425cf1a30Sjl dr_memlist_dup(struct memlist *mlist)
26525cf1a30Sjl {
26625cf1a30Sjl 	struct memlist *hl = NULL, *tl, **mlp;
26725cf1a30Sjl 
26825cf1a30Sjl 	if (mlist == NULL)
26925cf1a30Sjl 		return (NULL);
27025cf1a30Sjl 
27125cf1a30Sjl 	mlp = &hl;
27225cf1a30Sjl 	tl = *mlp;
273*56f33205SJonathan Adams 	for (; mlist; mlist = mlist->ml_next) {
27425cf1a30Sjl 		*mlp = GETSTRUCT(struct memlist, 1);
275*56f33205SJonathan Adams 		(*mlp)->ml_address = mlist->ml_address;
276*56f33205SJonathan Adams 		(*mlp)->ml_size = mlist->ml_size;
277*56f33205SJonathan Adams 		(*mlp)->ml_prev = tl;
27825cf1a30Sjl 		tl = *mlp;
279*56f33205SJonathan Adams 		mlp = &((*mlp)->ml_next);
28025cf1a30Sjl 	}
28125cf1a30Sjl 	*mlp = NULL;
28225cf1a30Sjl 
28325cf1a30Sjl 	return (hl);
28425cf1a30Sjl }
28525cf1a30Sjl 
28625cf1a30Sjl struct memlist *
dr_memlist_add_span(struct memlist * mlist,uint64_t base,uint64_t len)28725cf1a30Sjl dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len)
28825cf1a30Sjl {
28925cf1a30Sjl 	struct memlist	*ml, *tl, *nl;
29025cf1a30Sjl 
29125cf1a30Sjl 	if (len == 0ull)
29225cf1a30Sjl 		return (NULL);
29325cf1a30Sjl 
29425cf1a30Sjl 	if (mlist == NULL) {
29525cf1a30Sjl 		mlist = GETSTRUCT(struct memlist, 1);
296*56f33205SJonathan Adams 		mlist->ml_address = base;
297*56f33205SJonathan Adams 		mlist->ml_size = len;
298*56f33205SJonathan Adams 		mlist->ml_next = mlist->ml_prev = NULL;
29925cf1a30Sjl 
30025cf1a30Sjl 		return (mlist);
30125cf1a30Sjl 	}
30225cf1a30Sjl 
303*56f33205SJonathan Adams 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
304*56f33205SJonathan Adams 		if (base < ml->ml_address) {
305*56f33205SJonathan Adams 			if ((base + len) < ml->ml_address) {
30625cf1a30Sjl 				nl = GETSTRUCT(struct memlist, 1);
307*56f33205SJonathan Adams 				nl->ml_address = base;
308*56f33205SJonathan Adams 				nl->ml_size = len;
309*56f33205SJonathan Adams 				nl->ml_next = ml;
310*56f33205SJonathan Adams 				if ((nl->ml_prev = ml->ml_prev) != NULL)
311*56f33205SJonathan Adams 					nl->ml_prev->ml_next = nl;
312*56f33205SJonathan Adams 				ml->ml_prev = nl;
31325cf1a30Sjl 				if (mlist == ml)
31425cf1a30Sjl 					mlist = nl;
31525cf1a30Sjl 			} else {
316*56f33205SJonathan Adams 				ml->ml_size = MAX((base + len),
317*56f33205SJonathan Adams 				    (ml->ml_address + ml->ml_size)) - base;
318*56f33205SJonathan Adams 				ml->ml_address = base;
31925cf1a30Sjl 			}
32025cf1a30Sjl 			break;
32125cf1a30Sjl 
322*56f33205SJonathan Adams 		} else if (base <= (ml->ml_address + ml->ml_size)) {
323*56f33205SJonathan Adams 			ml->ml_size = MAX((base + len),
324*56f33205SJonathan Adams 			    (ml->ml_address + ml->ml_size)) -
325*56f33205SJonathan Adams 			    MIN(ml->ml_address, base);
326*56f33205SJonathan Adams 			ml->ml_address = MIN(ml->ml_address, base);
32725cf1a30Sjl 			break;
32825cf1a30Sjl 		}
32925cf1a30Sjl 	}
33025cf1a30Sjl 	if (ml == NULL) {
33125cf1a30Sjl 		nl = GETSTRUCT(struct memlist, 1);
332*56f33205SJonathan Adams 		nl->ml_address = base;
333*56f33205SJonathan Adams 		nl->ml_size = len;
334*56f33205SJonathan Adams 		nl->ml_next = NULL;
335*56f33205SJonathan Adams 		nl->ml_prev = tl;
336*56f33205SJonathan Adams 		tl->ml_next = nl;
33725cf1a30Sjl 	}
33825cf1a30Sjl 
33925cf1a30Sjl 	dr_memlist_coalesce(mlist);
34025cf1a30Sjl 
34125cf1a30Sjl 	return (mlist);
34225cf1a30Sjl }
34325cf1a30Sjl 
34425cf1a30Sjl struct memlist *
dr_memlist_del_span(struct memlist * mlist,uint64_t base,uint64_t len)34525cf1a30Sjl dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
34625cf1a30Sjl {
34725cf1a30Sjl 	uint64_t	end;
34825cf1a30Sjl 	struct memlist	*ml, *tl, *nlp;
34925cf1a30Sjl 
35025cf1a30Sjl 	if (mlist == NULL)
35125cf1a30Sjl 		return (NULL);
35225cf1a30Sjl 
35325cf1a30Sjl 	end = base + len;
354*56f33205SJonathan Adams 	if ((end <= mlist->ml_address) || (base == end))
35525cf1a30Sjl 		return (mlist);
35625cf1a30Sjl 
35725cf1a30Sjl 	for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
35825cf1a30Sjl 		uint64_t	mend;
35925cf1a30Sjl 
360*56f33205SJonathan Adams 		nlp = ml->ml_next;
36125cf1a30Sjl 
362*56f33205SJonathan Adams 		if (end <= ml->ml_address)
36325cf1a30Sjl 			break;
36425cf1a30Sjl 
365*56f33205SJonathan Adams 		mend = ml->ml_address + ml->ml_size;
36625cf1a30Sjl 		if (base < mend) {
367*56f33205SJonathan Adams 			if (base <= ml->ml_address) {
368*56f33205SJonathan Adams 				ml->ml_address = end;
36925cf1a30Sjl 				if (end >= mend)
370*56f33205SJonathan Adams 					ml->ml_size = 0ull;
37125cf1a30Sjl 				else
372*56f33205SJonathan Adams 					ml->ml_size = mend - ml->ml_address;
37325cf1a30Sjl 			} else {
374*56f33205SJonathan Adams 				ml->ml_size = base - ml->ml_address;
37525cf1a30Sjl 				if (end < mend) {
37625cf1a30Sjl 					struct memlist	*nl;
37725cf1a30Sjl 					/*
37825cf1a30Sjl 					 * splitting an memlist entry.
37925cf1a30Sjl 					 */
38025cf1a30Sjl 					nl = GETSTRUCT(struct memlist, 1);
381*56f33205SJonathan Adams 					nl->ml_address = end;
382*56f33205SJonathan Adams 					nl->ml_size = mend - nl->ml_address;
383*56f33205SJonathan Adams 					if ((nl->ml_next = nlp) != NULL)
384*56f33205SJonathan Adams 						nlp->ml_prev = nl;
385*56f33205SJonathan Adams 					nl->ml_prev = ml;
386*56f33205SJonathan Adams 					ml->ml_next = nl;
38725cf1a30Sjl 					nlp = nl;
38825cf1a30Sjl 				}
38925cf1a30Sjl 			}
390*56f33205SJonathan Adams 			if (ml->ml_size == 0ull) {
39125cf1a30Sjl 				if (ml == mlist) {
39225cf1a30Sjl 					if ((mlist = nlp) != NULL)
393*56f33205SJonathan Adams 						nlp->ml_prev = NULL;
39425cf1a30Sjl 					FREESTRUCT(ml, struct memlist, 1);
39525cf1a30Sjl 					if (mlist == NULL)
39625cf1a30Sjl 						break;
39725cf1a30Sjl 					ml = nlp;
39825cf1a30Sjl 				} else {
399*56f33205SJonathan Adams 					if ((tl->ml_next = nlp) != NULL)
400*56f33205SJonathan Adams 						nlp->ml_prev = tl;
40125cf1a30Sjl 					FREESTRUCT(ml, struct memlist, 1);
40225cf1a30Sjl 					ml = tl;
40325cf1a30Sjl 				}
40425cf1a30Sjl 			}
40525cf1a30Sjl 		}
40625cf1a30Sjl 	}
40725cf1a30Sjl 
40825cf1a30Sjl 	return (mlist);
40925cf1a30Sjl }
41025cf1a30Sjl 
41125cf1a30Sjl /*
41225cf1a30Sjl  * add span without merging
41325cf1a30Sjl  */
41425cf1a30Sjl struct memlist *
dr_memlist_cat_span(struct memlist * mlist,uint64_t base,uint64_t len)41525cf1a30Sjl dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len)
41625cf1a30Sjl {
41725cf1a30Sjl 	struct memlist	*ml, *tl, *nl;
41825cf1a30Sjl 
41925cf1a30Sjl 	if (len == 0ull)
42025cf1a30Sjl 		return (NULL);
42125cf1a30Sjl 
42225cf1a30Sjl 	if (mlist == NULL) {
42325cf1a30Sjl 		mlist = GETSTRUCT(struct memlist, 1);
424*56f33205SJonathan Adams 		mlist->ml_address = base;
425*56f33205SJonathan Adams 		mlist->ml_size = len;
426*56f33205SJonathan Adams 		mlist->ml_next = mlist->ml_prev = NULL;
42725cf1a30Sjl 
42825cf1a30Sjl 		return (mlist);
42925cf1a30Sjl 	}
43025cf1a30Sjl 
431*56f33205SJonathan Adams 	for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
432*56f33205SJonathan Adams 		if (base < ml->ml_address) {
43325cf1a30Sjl 			nl = GETSTRUCT(struct memlist, 1);
434*56f33205SJonathan Adams 			nl->ml_address = base;
435*56f33205SJonathan Adams 			nl->ml_size = len;
436*56f33205SJonathan Adams 			nl->ml_next = ml;
437*56f33205SJonathan Adams 			if ((nl->ml_prev = ml->ml_prev) != NULL)
438*56f33205SJonathan Adams 				nl->ml_prev->ml_next = nl;
439*56f33205SJonathan Adams 			ml->ml_prev = nl;
44025cf1a30Sjl 			if (mlist == ml)
44125cf1a30Sjl 				mlist = nl;
44225cf1a30Sjl 			break;
44325cf1a30Sjl 		}
44425cf1a30Sjl 	}
44525cf1a30Sjl 
44625cf1a30Sjl 	if (ml == NULL) {
44725cf1a30Sjl 		nl = GETSTRUCT(struct memlist, 1);
448*56f33205SJonathan Adams 		nl->ml_address = base;
449*56f33205SJonathan Adams 		nl->ml_size = len;
450*56f33205SJonathan Adams 		nl->ml_next = NULL;
451*56f33205SJonathan Adams 		nl->ml_prev = tl;
452*56f33205SJonathan Adams 		tl->ml_next = nl;
45325cf1a30Sjl 	}
45425cf1a30Sjl 
45525cf1a30Sjl 	return (mlist);
45625cf1a30Sjl }
457