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