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