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