diff options
Diffstat (limited to 'usr/src/uts/sun4u/ngdr/io/dr_util.c')
-rw-r--r-- | usr/src/uts/sun4u/ngdr/io/dr_util.c | 209 |
1 files changed, 202 insertions, 7 deletions
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_util.c b/usr/src/uts/sun4u/ngdr/io/dr_util.c index 7a17df1190..eaf8c95178 100644 --- a/usr/src/uts/sun4u/ngdr/io/dr_util.c +++ b/usr/src/uts/sun4u/ngdr/io/dr_util.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -174,7 +173,7 @@ drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...) * Memlist support. */ void -memlist_delete(struct memlist *mlist) +dr_memlist_delete(struct memlist *mlist) { register struct memlist *ml; @@ -185,7 +184,7 @@ memlist_delete(struct memlist *mlist) } int -memlist_intersect(struct memlist *al, struct memlist *bl) +dr_memlist_intersect(struct memlist *al, struct memlist *bl) { uint64_t astart, aend, bstart, bend; @@ -220,7 +219,7 @@ memlist_intersect(struct memlist *al, struct memlist *bl) } void -memlist_coalesce(struct memlist *mlist) +dr_memlist_coalesce(struct memlist *mlist) { uint64_t end, nend; @@ -260,3 +259,199 @@ memlist_dump(struct memlist *mlist) printf("memlist> 0x%lx, 0x%lx\n", ml->address, ml->size); } #endif + +struct memlist * +dr_memlist_dup(struct memlist *mlist) +{ + struct memlist *hl = NULL, *tl, **mlp; + + if (mlist == NULL) + return (NULL); + + mlp = &hl; + tl = *mlp; + for (; mlist; mlist = mlist->next) { + *mlp = GETSTRUCT(struct memlist, 1); + (*mlp)->address = mlist->address; + (*mlp)->size = mlist->size; + (*mlp)->prev = tl; + tl = *mlp; + mlp = &((*mlp)->next); + } + *mlp = NULL; + + return (hl); +} + +struct memlist * +dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) +{ + struct memlist *ml, *tl, *nl; + + if (len == 0ull) + return (NULL); + + if (mlist == NULL) { + mlist = GETSTRUCT(struct memlist, 1); + mlist->address = base; + mlist->size = len; + mlist->next = mlist->prev = NULL; + + return (mlist); + } + + for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { + if (base < ml->address) { + if ((base + len) < ml->address) { + nl = GETSTRUCT(struct memlist, 1); + nl->address = base; + nl->size = len; + nl->next = ml; + if ((nl->prev = ml->prev) != NULL) + nl->prev->next = nl; + ml->prev = nl; + if (mlist == ml) + mlist = nl; + } else { + ml->size = MAX((base + len), + (ml->address + ml->size)) - + base; + ml->address = base; + } + break; + + } else if (base <= (ml->address + ml->size)) { + ml->size = MAX((base + len), + (ml->address + ml->size)) - + MIN(ml->address, base); + ml->address = MIN(ml->address, base); + break; + } + } + if (ml == NULL) { + nl = GETSTRUCT(struct memlist, 1); + nl->address = base; + nl->size = len; + nl->next = NULL; + nl->prev = tl; + tl->next = nl; + } + + dr_memlist_coalesce(mlist); + + return (mlist); +} + +struct memlist * +dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) +{ + uint64_t end; + struct memlist *ml, *tl, *nlp; + + if (mlist == NULL) + return (NULL); + + end = base + len; + if ((end <= mlist->address) || (base == end)) + return (mlist); + + for (tl = ml = mlist; ml; tl = ml, ml = nlp) { + uint64_t mend; + + nlp = ml->next; + + if (end <= ml->address) + break; + + mend = ml->address + ml->size; + if (base < mend) { + if (base <= ml->address) { + ml->address = end; + if (end >= mend) + ml->size = 0ull; + else + ml->size = mend - ml->address; + } else { + ml->size = base - ml->address; + if (end < mend) { + struct memlist *nl; + /* + * splitting an memlist entry. + */ + nl = GETSTRUCT(struct memlist, 1); + nl->address = end; + nl->size = mend - nl->address; + if ((nl->next = nlp) != NULL) + nlp->prev = nl; + nl->prev = ml; + ml->next = nl; + nlp = nl; + } + } + if (ml->size == 0ull) { + if (ml == mlist) { + if ((mlist = nlp) != NULL) + nlp->prev = NULL; + FREESTRUCT(ml, struct memlist, 1); + if (mlist == NULL) + break; + ml = nlp; + } else { + if ((tl->next = nlp) != NULL) + nlp->prev = tl; + FREESTRUCT(ml, struct memlist, 1); + ml = tl; + } + } + } + } + + return (mlist); +} + +/* + * add span without merging + */ +struct memlist * +dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) +{ + struct memlist *ml, *tl, *nl; + + if (len == 0ull) + return (NULL); + + if (mlist == NULL) { + mlist = GETSTRUCT(struct memlist, 1); + mlist->address = base; + mlist->size = len; + mlist->next = mlist->prev = NULL; + + return (mlist); + } + + for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { + if (base < ml->address) { + nl = GETSTRUCT(struct memlist, 1); + nl->address = base; + nl->size = len; + nl->next = ml; + if ((nl->prev = ml->prev) != NULL) + nl->prev->next = nl; + ml->prev = nl; + if (mlist == ml) + mlist = nl; + break; + } + } + + if (ml == NULL) { + nl = GETSTRUCT(struct memlist, 1); + nl->address = base; + nl->size = len; + nl->next = NULL; + nl->prev = tl; + tl->next = nl; + } + + return (mlist); +} |