1 /* $NetBSD: citrus_mapper_zone.c,v 1.4 2003/07/12 15:39:21 tshiozak Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c)2003 Citrus Project, 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 #include <sys/queue.h> 33 34 #include <assert.h> 35 #include <errno.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include "citrus_namespace.h" 41 #include "citrus_types.h" 42 #include "citrus_bcs.h" 43 #include "citrus_module.h" 44 #include "citrus_region.h" 45 #include "citrus_memstream.h" 46 #include "citrus_mmap.h" 47 #include "citrus_hash.h" 48 #include "citrus_mapper.h" 49 #include "citrus_mapper_zone.h" 50 51 /* ---------------------------------------------------------------------- */ 52 53 _CITRUS_MAPPER_DECLS(mapper_zone); 54 _CITRUS_MAPPER_DEF_OPS(mapper_zone); 55 56 57 /* ---------------------------------------------------------------------- */ 58 59 struct _zone { 60 uint32_t z_begin; 61 uint32_t z_end; 62 }; 63 64 struct _citrus_mapper_zone { 65 struct _zone mz_col; 66 struct _zone mz_row; 67 int32_t mz_col_offset; 68 int32_t mz_row_offset; 69 int mz_col_bits; 70 }; 71 72 struct _parse_state { 73 enum { S_BEGIN, S_OFFSET } ps_state; 74 union { 75 uint32_t u_imm; 76 int32_t s_imm; 77 struct _zone zone; 78 } u; 79 #define ps_u_imm u.u_imm 80 #define ps_s_imm u.s_imm 81 #define ps_zone u.zone 82 int ps_top; 83 }; 84 85 int 86 _citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops) 87 { 88 89 memcpy(ops, &_citrus_mapper_zone_mapper_ops, 90 sizeof(_citrus_mapper_zone_mapper_ops)); 91 92 return (0); 93 } 94 95 #define BUFSIZE 20 96 #define T_ERR 0x100 97 #define T_IMM 0x101 98 99 static int 100 get_imm(struct _memstream *ms, struct _parse_state *ps) 101 { 102 int c, i, sign = 0; 103 char buf[BUFSIZE + 1]; 104 char *p; 105 106 for (i = 0; i < BUFSIZE; i++) { 107 retry: 108 c = _memstream_peek(ms); 109 if (i == 0) { 110 if (sign == 0 && (c == '+' || c == '-')) { 111 sign = c; 112 _memstream_getc(ms); 113 goto retry; 114 } else if (!_bcs_isdigit(c)) 115 break; 116 } else if (!_bcs_isxdigit(c)) 117 if (!(i == 1 && c == 'x')) 118 break; 119 buf[i] = _memstream_getc(ms); 120 } 121 buf[i] = '\0'; 122 ps->ps_u_imm = strtoul(buf, &p, 0); 123 if ((p - buf) != i) 124 return (T_ERR); 125 if (sign == '-') 126 ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm; 127 return (T_IMM); 128 } 129 130 static int 131 get_tok(struct _memstream *ms, struct _parse_state *ps) 132 { 133 int c; 134 135 loop: 136 c = _memstream_peek(ms); 137 if (c == 0x00) 138 return (EOF); 139 if (_bcs_isspace(c)) { 140 _memstream_getc(ms); 141 goto loop; 142 } 143 144 switch (ps->ps_state) { 145 case S_BEGIN: 146 switch (c) { 147 case ':': 148 case '-': 149 case '/': 150 _memstream_getc(ms); 151 return (c); 152 case '0': 153 case '1': 154 case '2': 155 case '3': 156 case '4': 157 case '5': 158 case '6': 159 case '7': 160 case '8': 161 case '9': 162 return (get_imm(ms, ps)); 163 } 164 break; 165 case S_OFFSET: 166 switch (c) { 167 case '/': 168 _memstream_getc(ms); 169 return (c); 170 case '+': 171 case '-': 172 case '0': 173 case '1': 174 case '2': 175 case '3': 176 case '4': 177 case '5': 178 case '6': 179 case '7': 180 case '8': 181 case '9': 182 return (get_imm(ms, ps)); 183 } 184 break; 185 } 186 return (T_ERR); 187 } 188 189 static int 190 parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z) 191 { 192 193 if (get_tok(ms, ps) != T_IMM) 194 return (-1); 195 z->z_begin = ps->ps_u_imm; 196 if (get_tok(ms, ps) != '-') 197 return (-1); 198 if (get_tok(ms, ps) != T_IMM) 199 return (-1); 200 z->z_end = ps->ps_u_imm; 201 202 if (z->z_begin > z->z_end) 203 return (-1); 204 205 return (0); 206 } 207 208 static int 209 check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval) 210 { 211 uint32_t remain; 212 213 if (maxval != 0 && z->z_end >= maxval) 214 return (-1); 215 216 if (ofs > 0) { 217 if (maxval == 0) 218 /* this should 0x100000000 - z->z_end */ 219 remain = (z->z_end == 0) ? 0xFFFFFFFF : 220 0xFFFFFFFF - z->z_end + 1; 221 else 222 remain = maxval - z->z_end; 223 if ((uint32_t)ofs > remain) 224 return (-1); 225 } else if (ofs < 0) { 226 if (z->z_begin < (uint32_t)-ofs) 227 return (-1); 228 } 229 230 return (0); 231 } 232 233 static int 234 parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms) 235 { 236 struct _parse_state ps; 237 uint32_t colmax, rowmax; 238 int isrc, ret; 239 240 ps.ps_state = S_BEGIN; 241 242 if (parse_zone(ms, &ps, &mz->mz_col)) 243 return (-1); 244 245 ret = get_tok(ms, &ps); 246 if (ret == '/') { 247 /* rowzone / colzone / bits */ 248 isrc = 1; 249 mz->mz_row = mz->mz_col; 250 251 if (parse_zone(ms, &ps, &mz->mz_col)) 252 return (-1); 253 if (get_tok(ms, &ps) != '/') 254 return (-1); 255 if (get_tok(ms, &ps) != T_IMM) 256 return (-1); 257 mz->mz_col_bits = ps.ps_u_imm; 258 if (mz->mz_col_bits < 0 || mz->mz_col_bits > 32) 259 return (-1); 260 ret = get_tok(ms, &ps); 261 } else { 262 /* colzone */ 263 isrc = 0; 264 mz->mz_col_bits = 32; 265 mz->mz_row.z_begin = mz->mz_row.z_end = 0; 266 } 267 if (ret == ':') { 268 /* offset */ 269 ps.ps_state = S_OFFSET; 270 if (get_tok(ms, &ps) != T_IMM) 271 return (-1); 272 mz->mz_col_offset = ps.ps_s_imm; 273 if (isrc) { 274 /* row/col */ 275 mz->mz_row_offset = mz->mz_col_offset; 276 if (get_tok(ms, &ps) != '/') 277 return (-1); 278 if (get_tok(ms, &ps) != T_IMM) 279 return (-1); 280 mz->mz_col_offset = ps.ps_s_imm; 281 } else 282 mz->mz_row_offset = 0; 283 ret = get_tok(ms, &ps); 284 } 285 if (ret != EOF) 286 return (-1); 287 288 /* sanity check */ 289 colmax = (mz->mz_col_bits == 32) ? 0 : 1 << mz->mz_col_bits; 290 rowmax = (mz->mz_col_bits == 0) ? 0 : 1 << (32-mz->mz_col_bits); 291 if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax)) 292 return (-1); 293 if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax)) 294 return (-1); 295 296 return (0); 297 } 298 299 static int 300 /*ARGSUSED*/ 301 _citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma __unused, 302 struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused, 303 const void * __restrict var, size_t lenvar, 304 struct _citrus_mapper_traits * __restrict mt, size_t lenmt) 305 { 306 struct _citrus_mapper_zone *mz; 307 struct _memstream ms; 308 struct _region r; 309 310 if (lenmt < sizeof(*mt)) 311 return (EINVAL); 312 313 mz = malloc(sizeof(*mz)); 314 if (mz == NULL) 315 return (errno); 316 317 mz->mz_col.z_begin = mz->mz_col.z_end = 0; 318 mz->mz_row.z_begin = mz->mz_row.z_end = 0; 319 mz->mz_col_bits = 0; 320 mz->mz_row_offset = 0; 321 mz->mz_col_offset = 0; 322 323 _region_init(&r, __DECONST(void *, var), lenvar); 324 _memstream_bind(&ms, &r); 325 if (parse_var(mz, &ms)) { 326 free(mz); 327 return (EINVAL); 328 } 329 cm->cm_closure = mz; 330 mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */ 331 mt->mt_state_size = 0; /* stateless */ 332 333 return (0); 334 } 335 336 static void 337 /*ARGSUSED*/ 338 _citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm __unused) 339 { 340 341 } 342 343 static int 344 /*ARGSUSED*/ 345 _citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm, 346 _citrus_index_t * __restrict dst, _citrus_index_t src, 347 void * __restrict ps __unused) 348 { 349 struct _citrus_mapper_zone *mz = cm->cm_closure; 350 uint32_t col, row; 351 352 if (mz->mz_col_bits == 32) { 353 col = src; 354 row = 0; 355 if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end) 356 return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL); 357 if (mz->mz_col_offset > 0) 358 col += (uint32_t)mz->mz_col_offset; 359 else 360 col -= (uint32_t)-mz->mz_col_offset; 361 *dst = col; 362 } else { 363 col = src & (((uint32_t)1 << mz->mz_col_bits) - 1); 364 row = src >> mz->mz_col_bits; 365 if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end || 366 col < mz->mz_col.z_begin || col > mz->mz_col.z_end) 367 return (_CITRUS_MAPPER_CONVERT_NONIDENTICAL); 368 if (mz->mz_col_offset > 0) 369 col += (uint32_t)mz->mz_col_offset; 370 else 371 col -= (uint32_t)-mz->mz_col_offset; 372 if (mz->mz_row_offset > 0) 373 row += (uint32_t)mz->mz_row_offset; 374 else 375 row -= (uint32_t)-mz->mz_row_offset; 376 *dst = col | (row << mz->mz_col_bits); 377 } 378 return (_CITRUS_MAPPER_CONVERT_SUCCESS); 379 } 380 381 static void 382 /*ARGSUSED*/ 383 _citrus_mapper_zone_mapper_init_state(void) 384 { 385 386 } 387