citrus_mapper_zone.c revision 1.3 1 1.3 tshiozak /* $NetBSD: citrus_mapper_zone.c,v 1.3 2003/07/01 08:33:06 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.3 tshiozak __RCSID("$NetBSD: citrus_mapper_zone.c,v 1.3 2003/07/01 08:33:06 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.2 tshiozak #include <sys/queue.h>
40 1.1 tshiozak
41 1.1 tshiozak #include "citrus_namespace.h"
42 1.1 tshiozak #include "citrus_types.h"
43 1.1 tshiozak #include "citrus_bcs.h"
44 1.1 tshiozak #include "citrus_module.h"
45 1.1 tshiozak #include "citrus_region.h"
46 1.1 tshiozak #include "citrus_memstream.h"
47 1.1 tshiozak #include "citrus_mmap.h"
48 1.1 tshiozak #include "citrus_hash.h"
49 1.1 tshiozak #include "citrus_mapper.h"
50 1.1 tshiozak #include "citrus_mapper_zone.h"
51 1.1 tshiozak
52 1.1 tshiozak /* ---------------------------------------------------------------------- */
53 1.1 tshiozak
54 1.1 tshiozak _CITRUS_MAPPER_DECLS(mapper_zone);
55 1.1 tshiozak _CITRUS_MAPPER_DEF_OPS(mapper_zone);
56 1.1 tshiozak
57 1.1 tshiozak
58 1.1 tshiozak /* ---------------------------------------------------------------------- */
59 1.1 tshiozak
60 1.1 tshiozak struct _zone {
61 1.1 tshiozak u_int32_t z_begin;
62 1.1 tshiozak u_int32_t z_end;
63 1.1 tshiozak };
64 1.1 tshiozak
65 1.1 tshiozak struct _citrus_mapper_zone {
66 1.1 tshiozak struct _zone mz_row;
67 1.1 tshiozak struct _zone mz_col;
68 1.1 tshiozak int mz_col_bits;
69 1.1 tshiozak int32_t mz_row_offset;
70 1.1 tshiozak int32_t mz_col_offset;
71 1.1 tshiozak };
72 1.1 tshiozak
73 1.1 tshiozak struct _parse_state {
74 1.1 tshiozak enum { S_BEGIN, S_OFFSET } ps_state;
75 1.1 tshiozak union {
76 1.1 tshiozak u_int32_t u_imm;
77 1.1 tshiozak int32_t s_imm;
78 1.1 tshiozak struct _zone zone;
79 1.1 tshiozak } u;
80 1.1 tshiozak #define ps_u_imm u.u_imm
81 1.1 tshiozak #define ps_s_imm u.s_imm
82 1.1 tshiozak #define ps_zone u.zone
83 1.1 tshiozak int ps_top;
84 1.1 tshiozak };
85 1.1 tshiozak
86 1.1 tshiozak int
87 1.1 tshiozak _citrus_mapper_zone_mapper_getops(struct _citrus_mapper_ops *ops,
88 1.1 tshiozak size_t lenops, uint32_t expected_version)
89 1.1 tshiozak {
90 1.1 tshiozak if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
91 1.1 tshiozak return EINVAL;
92 1.1 tshiozak
93 1.1 tshiozak memcpy(ops, &_citrus_mapper_zone_mapper_ops,
94 1.1 tshiozak sizeof(_citrus_mapper_zone_mapper_ops));
95 1.1 tshiozak
96 1.1 tshiozak return 0;
97 1.1 tshiozak }
98 1.1 tshiozak
99 1.1 tshiozak #define BUFSIZE 20
100 1.1 tshiozak #define T_ERR 0x100
101 1.1 tshiozak #define T_IMM 0x101
102 1.1 tshiozak
103 1.1 tshiozak static int
104 1.1 tshiozak get_imm(struct _memstream *ms, struct _parse_state *ps)
105 1.1 tshiozak {
106 1.1 tshiozak int sign = 0;
107 1.1 tshiozak int c, i;
108 1.1 tshiozak char buf[BUFSIZE+1], *p;
109 1.1 tshiozak
110 1.1 tshiozak for (i=0; i<BUFSIZE; i++) {
111 1.1 tshiozak retry:
112 1.1 tshiozak c = _memstream_peek(ms);
113 1.1 tshiozak if (i==0) {
114 1.1 tshiozak if (sign == 0 && (c == '+' || c == '-')) {
115 1.1 tshiozak sign = c;
116 1.1 tshiozak _memstream_getc(ms);
117 1.1 tshiozak goto retry;
118 1.1 tshiozak } else if (!_bcs_isdigit(c))
119 1.1 tshiozak break;
120 1.1 tshiozak } else if (!_bcs_isxdigit(c))
121 1.1 tshiozak if (!(i==1 && c == 'x'))
122 1.1 tshiozak break;
123 1.1 tshiozak buf[i] = _memstream_getc(ms);
124 1.1 tshiozak }
125 1.1 tshiozak buf[i] = '\0';
126 1.1 tshiozak ps->ps_u_imm = strtoul(buf, &p, 0);
127 1.1 tshiozak if ((p-buf) != i)
128 1.1 tshiozak return T_ERR;
129 1.1 tshiozak if (sign == '-')
130 1.1 tshiozak ps->ps_u_imm = (unsigned long)-(long)ps->ps_u_imm;
131 1.1 tshiozak return T_IMM;
132 1.1 tshiozak }
133 1.1 tshiozak
134 1.1 tshiozak static int
135 1.1 tshiozak get_tok(struct _memstream *ms, struct _parse_state *ps)
136 1.1 tshiozak {
137 1.1 tshiozak int c;
138 1.1 tshiozak
139 1.1 tshiozak loop:
140 1.1 tshiozak c = _memstream_peek(ms);
141 1.1 tshiozak if (c==0x00)
142 1.1 tshiozak return EOF;
143 1.1 tshiozak if (_bcs_isspace(c)) {
144 1.1 tshiozak _memstream_getc(ms);
145 1.1 tshiozak goto loop;
146 1.1 tshiozak }
147 1.1 tshiozak
148 1.1 tshiozak switch (ps->ps_state) {
149 1.1 tshiozak case S_BEGIN:
150 1.1 tshiozak switch (c) {
151 1.1 tshiozak case ':':
152 1.1 tshiozak case '-':
153 1.1 tshiozak case '/':
154 1.1 tshiozak _memstream_getc(ms);
155 1.1 tshiozak return c;
156 1.1 tshiozak case '0':
157 1.1 tshiozak case '1':
158 1.1 tshiozak case '2':
159 1.1 tshiozak case '3':
160 1.1 tshiozak case '4':
161 1.1 tshiozak case '5':
162 1.1 tshiozak case '6':
163 1.1 tshiozak case '7':
164 1.1 tshiozak case '8':
165 1.1 tshiozak case '9':
166 1.1 tshiozak return get_imm(ms, ps);
167 1.1 tshiozak }
168 1.1 tshiozak break;
169 1.1 tshiozak case S_OFFSET:
170 1.1 tshiozak switch (c) {
171 1.1 tshiozak case '/':
172 1.1 tshiozak _memstream_getc(ms);
173 1.1 tshiozak return c;
174 1.1 tshiozak case '+':
175 1.1 tshiozak case '-':
176 1.1 tshiozak case '0':
177 1.1 tshiozak case '1':
178 1.1 tshiozak case '2':
179 1.1 tshiozak case '3':
180 1.1 tshiozak case '4':
181 1.1 tshiozak case '5':
182 1.1 tshiozak case '6':
183 1.1 tshiozak case '7':
184 1.1 tshiozak case '8':
185 1.1 tshiozak case '9':
186 1.1 tshiozak return get_imm(ms, ps);
187 1.1 tshiozak }
188 1.1 tshiozak break;
189 1.1 tshiozak }
190 1.1 tshiozak return T_ERR;
191 1.1 tshiozak }
192 1.1 tshiozak
193 1.1 tshiozak static int
194 1.1 tshiozak parse_zone(struct _memstream *ms, struct _parse_state *ps, struct _zone *z)
195 1.1 tshiozak {
196 1.1 tshiozak if (get_tok(ms, ps) != T_IMM)
197 1.1 tshiozak return -1;
198 1.1 tshiozak z->z_begin = ps->ps_u_imm;
199 1.1 tshiozak if (get_tok(ms, ps) != '-')
200 1.1 tshiozak return -1;
201 1.1 tshiozak if (get_tok(ms, ps) != T_IMM)
202 1.1 tshiozak return -1;
203 1.1 tshiozak z->z_end = ps->ps_u_imm;
204 1.1 tshiozak
205 1.1 tshiozak if (z->z_begin > z->z_end)
206 1.1 tshiozak return -1;
207 1.1 tshiozak
208 1.1 tshiozak return 0;
209 1.1 tshiozak }
210 1.1 tshiozak
211 1.1 tshiozak static int
212 1.1 tshiozak check_rowcol(struct _zone *z, int32_t ofs, uint32_t maxval)
213 1.1 tshiozak {
214 1.1 tshiozak u_int32_t remain;
215 1.1 tshiozak
216 1.1 tshiozak if (maxval != 0 && z->z_end >= maxval)
217 1.1 tshiozak return -1;
218 1.1 tshiozak
219 1.1 tshiozak if (ofs > 0) {
220 1.1 tshiozak if (maxval == 0) {
221 1.1 tshiozak /* this should 0x100000000 - z->z_end */
222 1.1 tshiozak if (z->z_end == 0) {
223 1.1 tshiozak remain = 0xFFFFFFFF;
224 1.1 tshiozak } else {
225 1.1 tshiozak remain = 0xFFFFFFFF - z->z_end + 1;
226 1.1 tshiozak }
227 1.1 tshiozak } else
228 1.1 tshiozak remain = maxval - z->z_end;
229 1.1 tshiozak if ((u_int32_t)ofs > remain)
230 1.1 tshiozak return -1;
231 1.1 tshiozak } else if (ofs < 0) {
232 1.1 tshiozak if (z->z_begin < (u_int32_t)-ofs)
233 1.1 tshiozak return -1;
234 1.1 tshiozak }
235 1.1 tshiozak
236 1.1 tshiozak return 0;
237 1.1 tshiozak }
238 1.1 tshiozak
239 1.1 tshiozak static int
240 1.1 tshiozak parse_var(struct _citrus_mapper_zone *mz, struct _memstream *ms)
241 1.1 tshiozak {
242 1.1 tshiozak struct _parse_state ps;
243 1.1 tshiozak int ret, isrc;
244 1.1 tshiozak uint32_t rowmax, colmax;
245 1.1 tshiozak
246 1.1 tshiozak ps.ps_state = S_BEGIN;
247 1.1 tshiozak
248 1.1 tshiozak if (parse_zone(ms, &ps, &mz->mz_col))
249 1.1 tshiozak return -1;
250 1.1 tshiozak
251 1.1 tshiozak ret = get_tok(ms, &ps);
252 1.1 tshiozak if (ret == '/') {
253 1.1 tshiozak /* rowzone / colzone / bits */
254 1.1 tshiozak isrc = 1;
255 1.1 tshiozak mz->mz_row = mz->mz_col;
256 1.1 tshiozak
257 1.1 tshiozak if (parse_zone(ms, &ps, &mz->mz_col))
258 1.1 tshiozak return -1;
259 1.1 tshiozak if (get_tok(ms, &ps) != '/')
260 1.1 tshiozak return -1;
261 1.1 tshiozak if (get_tok(ms, &ps) != T_IMM)
262 1.1 tshiozak return -1;
263 1.1 tshiozak mz->mz_col_bits = ps.ps_u_imm;
264 1.1 tshiozak if (mz->mz_col_bits<0 || mz->mz_col_bits>32)
265 1.1 tshiozak return -1;
266 1.1 tshiozak ret = get_tok(ms, &ps);
267 1.1 tshiozak } else {
268 1.1 tshiozak /* colzone */
269 1.1 tshiozak isrc = 0;
270 1.1 tshiozak mz->mz_col_bits = 32;
271 1.1 tshiozak mz->mz_row.z_begin = mz->mz_row.z_end = 0;
272 1.1 tshiozak }
273 1.1 tshiozak if (ret == ':') {
274 1.1 tshiozak /* offset */
275 1.1 tshiozak ps.ps_state = S_OFFSET;
276 1.1 tshiozak if (get_tok(ms, &ps) != T_IMM)
277 1.1 tshiozak return -1;
278 1.1 tshiozak mz->mz_col_offset = ps.ps_s_imm;
279 1.1 tshiozak if (isrc) {
280 1.1 tshiozak /* row/col */
281 1.1 tshiozak mz->mz_row_offset = mz->mz_col_offset;
282 1.1 tshiozak if (get_tok(ms, &ps) != '/')
283 1.1 tshiozak return -1;
284 1.1 tshiozak if (get_tok(ms, &ps) != T_IMM)
285 1.1 tshiozak return -1;
286 1.1 tshiozak mz->mz_col_offset = ps.ps_s_imm;
287 1.1 tshiozak } else
288 1.1 tshiozak mz->mz_row_offset = 0;
289 1.1 tshiozak ret = get_tok(ms, &ps);
290 1.1 tshiozak }
291 1.1 tshiozak if (ret != EOF)
292 1.1 tshiozak return -1;
293 1.1 tshiozak
294 1.1 tshiozak /* sanity check */
295 1.1 tshiozak if (mz->mz_col_bits==32)
296 1.1 tshiozak colmax = 0;
297 1.1 tshiozak else
298 1.1 tshiozak colmax = 1 << mz->mz_col_bits;
299 1.1 tshiozak if (mz->mz_col_bits==0)
300 1.1 tshiozak rowmax = 0;
301 1.1 tshiozak else
302 1.1 tshiozak rowmax = 1 << (32-mz->mz_col_bits);
303 1.1 tshiozak if (check_rowcol(&mz->mz_col, mz->mz_col_offset, colmax))
304 1.1 tshiozak return -1;
305 1.1 tshiozak if (check_rowcol(&mz->mz_row, mz->mz_row_offset, rowmax))
306 1.1 tshiozak return -1;
307 1.1 tshiozak
308 1.1 tshiozak return 0;
309 1.1 tshiozak }
310 1.1 tshiozak
311 1.1 tshiozak static int
312 1.1 tshiozak /*ARGSUSED*/
313 1.1 tshiozak _citrus_mapper_zone_mapper_init(struct _citrus_mapper_area *__restrict ma,
314 1.1 tshiozak struct _citrus_mapper * __restrict cm,
315 1.1 tshiozak const char * __restrict dir,
316 1.1 tshiozak const void * __restrict var, size_t lenvar,
317 1.1 tshiozak struct _citrus_mapper_traits * __restrict mt,
318 1.1 tshiozak size_t lenmt)
319 1.1 tshiozak {
320 1.1 tshiozak struct _citrus_mapper_zone *mz;
321 1.1 tshiozak struct _memstream ms;
322 1.1 tshiozak struct _region r;
323 1.1 tshiozak
324 1.1 tshiozak _DIAGASSERT(cm && dir && mt);
325 1.1 tshiozak
326 1.1 tshiozak if (lenmt<sizeof(*mt))
327 1.1 tshiozak return EINVAL;
328 1.1 tshiozak
329 1.1 tshiozak mz = malloc(sizeof(*mz));
330 1.1 tshiozak if (mz == NULL)
331 1.1 tshiozak return errno;
332 1.3 tshiozak
333 1.3 tshiozak mz->mz_col.z_begin = mz->mz_col.z_end = 0;
334 1.3 tshiozak mz->mz_row.z_begin = mz->mz_row.z_end = 0;
335 1.3 tshiozak mz->mz_col_bits = 0;
336 1.3 tshiozak mz->mz_row_offset = 0;
337 1.3 tshiozak mz->mz_col_offset = 0;
338 1.1 tshiozak
339 1.1 tshiozak _region_init(&r, (void *)var, lenvar);
340 1.1 tshiozak _memstream_bind(&ms, &r);
341 1.1 tshiozak if (parse_var(mz, &ms)) {
342 1.1 tshiozak free(mz);
343 1.1 tshiozak return EINVAL;
344 1.1 tshiozak }
345 1.1 tshiozak cm->cm_closure = mz;
346 1.1 tshiozak mt->mt_src_max = mt->mt_dst_max = 1; /* 1:1 converter */
347 1.1 tshiozak mt->mt_state_size = 0; /* stateless */
348 1.1 tshiozak
349 1.1 tshiozak return 0;
350 1.1 tshiozak }
351 1.1 tshiozak
352 1.1 tshiozak static void
353 1.1 tshiozak /*ARGSUSED*/
354 1.1 tshiozak _citrus_mapper_zone_mapper_uninit(struct _citrus_mapper *cm)
355 1.1 tshiozak {
356 1.1 tshiozak }
357 1.1 tshiozak
358 1.1 tshiozak static int
359 1.1 tshiozak /*ARGSUSED*/
360 1.1 tshiozak _citrus_mapper_zone_mapper_convert(struct _citrus_mapper * __restrict cm,
361 1.1 tshiozak _citrus_index_t * __restrict dst,
362 1.1 tshiozak _citrus_index_t src, void * __restrict ps)
363 1.1 tshiozak {
364 1.1 tshiozak u_int32_t row, col;
365 1.1 tshiozak struct _citrus_mapper_zone *mz = cm->cm_closure;
366 1.1 tshiozak
367 1.1 tshiozak if (mz->mz_col_bits == 32) {
368 1.1 tshiozak col = src;
369 1.1 tshiozak row = 0;
370 1.1 tshiozak if (col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
371 1.1 tshiozak return _CITRUS_MAPPER_CONVERT_INVAL;
372 1.1 tshiozak if (mz->mz_col_offset>0)
373 1.1 tshiozak col += (u_int32_t)mz->mz_col_offset;
374 1.1 tshiozak else
375 1.1 tshiozak col -= (u_int32_t)-mz->mz_col_offset;
376 1.1 tshiozak *dst = col;
377 1.1 tshiozak } else {
378 1.1 tshiozak col = src & (((u_int32_t)1<<mz->mz_col_bits)-1);
379 1.1 tshiozak row = src >> mz->mz_col_bits;
380 1.1 tshiozak if (row < mz->mz_row.z_begin || row > mz->mz_row.z_end ||
381 1.1 tshiozak col < mz->mz_col.z_begin || col > mz->mz_col.z_end)
382 1.1 tshiozak return _CITRUS_MAPPER_CONVERT_INVAL;
383 1.1 tshiozak if (mz->mz_col_offset>0)
384 1.1 tshiozak col += (u_int32_t)mz->mz_col_offset;
385 1.1 tshiozak else
386 1.1 tshiozak col -= (u_int32_t)-mz->mz_col_offset;
387 1.1 tshiozak if (mz->mz_row_offset>0)
388 1.1 tshiozak row += (u_int32_t)mz->mz_row_offset;
389 1.1 tshiozak else
390 1.1 tshiozak row -= (u_int32_t)-mz->mz_row_offset;
391 1.1 tshiozak *dst = col | (row << mz->mz_col_bits);
392 1.1 tshiozak }
393 1.1 tshiozak return _CITRUS_MAPPER_CONVERT_SUCCESS;
394 1.1 tshiozak }
395 1.1 tshiozak
396 1.1 tshiozak static void
397 1.1 tshiozak /*ARGSUSED*/
398 1.1 tshiozak _citrus_mapper_zone_mapper_init_state(struct _citrus_mapper * __restrict cm,
399 1.1 tshiozak void * __restrict ps)
400 1.1 tshiozak {
401 1.1 tshiozak }
402