MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / ieee1394 / csr1212.c
blob931464b6ce9eabd54371d64af4e515ab458efbeb
1 /*
2 * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
4 * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
5 * Steve Kinneberg <kinnebergsteve@acmsystems.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * 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 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /* TODO List:
32 * - Verify interface consistency: i.e., public functions that take a size
33 * parameter expect size to be in bytes.
34 * - Convenience functions for reading a block of data from a given offset.
37 #ifndef __KERNEL__
38 #include <string.h>
39 #endif
41 #include "csr1212.h"
44 /* Permitted key type for each key id */
45 #define __I (1 << CSR1212_KV_TYPE_IMMEDIATE)
46 #define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET)
47 #define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
48 #define __L (1 << CSR1212_KV_TYPE_LEAF)
49 static const u_int8_t csr1212_key_id_type_map[0x30] = {
50 0, /* Reserved */
51 __D | __L, /* Descriptor */
52 __I | __D | __L, /* Bus_Dependent_Info */
53 __I | __D | __L, /* Vendor */
54 __I, /* Hardware_Version */
55 0, 0, /* Reserved */
56 __D | __L, /* Module */
57 0, 0, 0, 0, /* Reserved */
58 __I, /* Node_Capabilities */
59 __L, /* EUI_64 */
60 0, 0, 0, /* Reserved */
61 __D, /* Unit */
62 __I, /* Specifier_ID */
63 __I, /* Version */
64 __I | __C | __D | __L, /* Dependent_Info */
65 __L, /* Unit_Location */
66 0, /* Reserved */
67 __I, /* Model */
68 __D, /* Instance */
69 __L, /* Keyword */
70 __D, /* Feature */
71 __L, /* Extended_ROM */
72 __I, /* Extended_Key_Specifier_ID */
73 __I, /* Extended_Key */
74 __I | __C | __D | __L, /* Extended_Data */
75 __L, /* Modifiable_Descriptor */
76 __I, /* Directory_ID */
77 __I, /* Revision */
79 #undef __I
80 #undef __C
81 #undef __D
82 #undef __L
85 #define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t))
86 #define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t))
88 static inline void free_keyval(struct csr1212_keyval *kv)
90 if (kv->key.type == CSR1212_KV_TYPE_LEAF)
91 CSR1212_FREE(kv->value.leaf.data);
93 CSR1212_FREE(kv);
96 static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length)
98 int shift;
99 u_int32_t data;
100 u_int16_t sum, crc = 0;
102 for (; length; length--) {
103 data = CSR1212_BE32_TO_CPU(*buffer);
104 buffer++;
105 for (shift = 28; shift >= 0; shift -= 4 ) {
106 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
107 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
109 crc &= 0xffff;
112 return CSR1212_CPU_TO_BE16(crc);
115 #if 0
116 /* Microsoft computes the CRC with the bytes in reverse order. Therefore we
117 * have a special version of the CRC algorithm to account for their buggy
118 * software. */
119 static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length)
121 int shift;
122 u_int32_t data;
123 u_int16_t sum, crc = 0;
125 for (; length; length--) {
126 data = CSR1212_LE32_TO_CPU(*buffer);
127 buffer++;
128 for (shift = 28; shift >= 0; shift -= 4 ) {
129 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
130 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
132 crc &= 0xffff;
135 return CSR1212_CPU_TO_BE16(crc);
137 #endif
139 static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir,
140 struct csr1212_keyval *kv)
142 struct csr1212_dentry *pos;
144 for (pos = dir->value.directory.dentries_head;
145 pos != NULL; pos = pos->next) {
146 if (pos->kv == kv)
147 return pos;
149 return NULL;
153 static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list,
154 u_int32_t offset)
156 struct csr1212_keyval *kv;
158 for (kv = kv_list; kv != NULL; kv = kv->next) {
159 if (kv->offset == offset)
160 return kv;
162 return NULL;
166 /* Creation Routines */
167 struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
168 size_t bus_info_size, void *private)
170 struct csr1212_csr *csr;
172 csr = CSR1212_MALLOC(sizeof(*csr));
173 if (!csr)
174 return NULL;
176 csr->cache_head =
177 csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
178 CSR1212_CONFIG_ROM_SPACE_SIZE);
179 if (!csr->cache_head) {
180 CSR1212_FREE(csr);
181 return NULL;
184 /* The keyval key id is not used for the root node, but a valid key id
185 * that can be used for a directory needs to be passed to
186 * csr1212_new_directory(). */
187 csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
188 if (!csr->root_kv) {
189 CSR1212_FREE(csr->cache_head);
190 CSR1212_FREE(csr);
191 return NULL;
194 csr->bus_info_data = csr->cache_head->data;
195 csr->bus_info_len = bus_info_size;
196 csr->crc_len = bus_info_size;
197 csr->ops = ops;
198 csr->private = private;
199 csr->cache_tail = csr->cache_head;
201 return csr;
206 void csr1212_init_local_csr(struct csr1212_csr *csr,
207 const u_int32_t *bus_info_data, int max_rom)
209 static const int mr_map[] = { 4, 64, 1024, 0 };
211 csr->max_rom = mr_map[max_rom];
212 memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
216 static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key)
218 struct csr1212_keyval *kv;
220 if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
221 return NULL;
223 kv = CSR1212_MALLOC(sizeof(*kv));
224 if (!kv)
225 return NULL;
227 kv->key.type = type;
228 kv->key.id = key;
230 kv->associate = NULL;
231 kv->refcnt = 1;
233 kv->next = NULL;
234 kv->prev = NULL;
235 kv->offset = 0;
236 kv->valid = 0;
237 return kv;
240 struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value)
242 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
244 if (!kv)
245 return NULL;
247 kv->value.immediate = value;
248 kv->valid = 1;
249 return kv;
252 struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len)
254 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
256 if (!kv)
257 return NULL;
259 if (data_len > 0) {
260 kv->value.leaf.data = CSR1212_MALLOC(data_len);
261 if (!kv->value.leaf.data) {
262 CSR1212_FREE(kv);
263 return NULL;
266 if (data)
267 memcpy(kv->value.leaf.data, data, data_len);
268 } else {
269 kv->value.leaf.data = NULL;
272 kv->value.leaf.len = bytes_to_quads(data_len);
273 kv->offset = 0;
274 kv->valid = 1;
276 return kv;
279 struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset)
281 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
283 if (!kv)
284 return NULL;
286 kv->value.csr_offset = csr_offset;
288 kv->offset = 0;
289 kv->valid = 1;
290 return kv;
293 struct csr1212_keyval *csr1212_new_directory(u_int8_t key)
295 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
297 if (!kv)
298 return NULL;
300 kv->value.directory.len = 0;
301 kv->offset = 0;
302 kv->value.directory.dentries_head = NULL;
303 kv->value.directory.dentries_tail = NULL;
304 kv->valid = 1;
305 return kv;
308 int csr1212_associate_keyval(struct csr1212_keyval *kv,
309 struct csr1212_keyval *associate)
311 if (!kv || !associate)
312 return CSR1212_EINVAL;
314 if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
315 (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
316 associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
317 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
318 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
319 associate->key.id < 0x30))
320 return CSR1212_EINVAL;
322 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
323 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY)
324 return CSR1212_EINVAL;
326 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
327 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA)
328 return CSR1212_EINVAL;
330 if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
331 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID)
332 return CSR1212_EINVAL;
334 if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
335 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)
336 return CSR1212_EINVAL;
338 if (kv->associate)
339 csr1212_release_keyval(kv->associate);
341 associate->refcnt++;
342 kv->associate = associate;
344 return CSR1212_SUCCESS;
347 int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
348 struct csr1212_keyval *kv)
350 struct csr1212_dentry *dentry;
352 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
353 return CSR1212_EINVAL;
355 dentry = CSR1212_MALLOC(sizeof(*dentry));
356 if (!dentry)
357 return CSR1212_ENOMEM;
359 dentry->kv = kv;
361 kv->refcnt++;
363 dentry->next = NULL;
364 dentry->prev = dir->value.directory.dentries_tail;
366 if (!dir->value.directory.dentries_head)
367 dir->value.directory.dentries_head = dentry;
369 if (dir->value.directory.dentries_tail)
370 dir->value.directory.dentries_tail->next = dentry;
371 dir->value.directory.dentries_tail = dentry;
373 return CSR1212_SUCCESS;
376 struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key,
377 u_int32_t value)
379 struct csr1212_keyval *kvs, *kvk, *kvv;
381 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
382 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
383 kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value);
385 if (!kvs || !kvk || !kvv) {
386 if (kvs)
387 free_keyval(kvs);
388 if (kvk)
389 free_keyval(kvk);
390 if (kvv)
391 free_keyval(kvv);
392 return NULL;
395 /* Don't keep a local reference to the extended key or value. */
396 kvk->refcnt = 0;
397 kvv->refcnt = 0;
399 csr1212_associate_keyval(kvk, kvv);
400 csr1212_associate_keyval(kvs, kvk);
402 return kvs;
405 struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key,
406 const void *data, size_t data_len)
408 struct csr1212_keyval *kvs, *kvk, *kvv;
410 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
411 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
412 kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len);
414 if (!kvs || !kvk || !kvv) {
415 if (kvs)
416 free_keyval(kvs);
417 if (kvk)
418 free_keyval(kvk);
419 if (kvv)
420 free_keyval(kvv);
421 return NULL;
424 /* Don't keep a local reference to the extended key or value. */
425 kvk->refcnt = 0;
426 kvv->refcnt = 0;
428 csr1212_associate_keyval(kvk, kvv);
429 csr1212_associate_keyval(kvs, kvk);
431 return kvs;
434 struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id,
435 const void *data, size_t data_len)
437 struct csr1212_keyval *kv;
439 kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
440 data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
441 if (!kv)
442 return NULL;
444 CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
445 CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
447 if (data) {
448 memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
451 return kv;
455 struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
456 u_int16_t cset,
457 u_int16_t language,
458 const void *data,
459 size_t data_len)
461 struct csr1212_keyval *kv;
462 char *lstr;
464 kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
465 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
466 if (!kv)
467 return NULL;
469 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth);
470 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset);
471 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
473 lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
475 /* make sure last quadlet is zeroed out */
476 *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0;
478 /* don't copy the NUL terminator */
479 memcpy(lstr, data, data_len);
481 return kv;
484 static int csr1212_check_minimal_ascii(const char *s)
486 static const char minimal_ascii_table[] = {
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
488 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27,
492 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
493 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
494 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
495 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
496 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
497 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
498 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
499 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
500 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
501 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
502 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
504 for (; *s; s++) {
505 if (minimal_ascii_table[*s & 0x7F] != *s)
506 return -1; /* failed */
508 /* String conforms to minimal-ascii, as specified by IEEE 1212,
509 * par. 7.4 */
510 return 0;
513 struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
515 /* Check if string conform to minimal_ascii format */
516 if (csr1212_check_minimal_ascii(s))
517 return NULL;
519 /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */
520 return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s));
523 struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
524 u_int8_t palette_depth,
525 u_int8_t color_space,
526 u_int16_t language,
527 u_int16_t hscan,
528 u_int16_t vscan,
529 u_int32_t *palette,
530 u_int32_t *pixels)
532 static const int pd[4] = { 0, 4, 16, 256 };
533 static const int cs[16] = { 4, 2 };
534 struct csr1212_keyval *kv;
535 int palette_size = pd[palette_depth] * cs[color_space];
536 int pixel_size = (hscan * vscan + 3) & ~0x3;
538 if ((palette_depth && !palette) || !pixels)
539 return NULL;
541 kv = csr1212_new_descriptor_leaf(1, 0, NULL,
542 palette_size + pixel_size +
543 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
544 if (!kv)
545 return NULL;
547 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version);
548 CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth);
549 CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space);
550 CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
551 CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan);
552 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan);
554 if (palette_size)
555 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,
556 palette_size);
558 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);
560 return kv;
563 struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
564 u_int64_t address)
566 struct csr1212_keyval *kv;
568 /* IEEE 1212, par. 7.5.4.3 Modifiable descriptors */
569 kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t));
570 if(!kv)
571 return NULL;
573 CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size);
574 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address);
575 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address);
577 return kv;
580 static int csr1212_check_keyword(const char *s)
582 for (; *s; s++) {
584 if (('A' <= *s) && (*s <= 'Z'))
585 continue;
586 if (('0' <= *s) && (*s <= '9'))
587 continue;
588 if (*s == '-')
589 continue;
591 return -1; /* failed */
593 /* String conforms to keyword, as specified by IEEE 1212,
594 * par. 7.6.5 */
595 return CSR1212_SUCCESS;
598 struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[])
600 struct csr1212_keyval *kv;
601 char *buffer;
602 int i, data_len = 0;
604 /* Check all keywords to see if they conform to restrictions:
605 * Only the following characters is allowed ['A'..'Z','0'..'9','-']
606 * Each word is zero-terminated.
607 * Also calculate the total length of the keywords.
609 for (i = 0; i < strc; i++) {
610 if (!strv[i] || csr1212_check_keyword(strv[i])) {
611 return NULL;
613 data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */
616 /* IEEE 1212, par. 7.6.5 Keyword leaves */
617 kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);
618 if (!kv)
619 return NULL;
621 buffer = (char *)kv->value.leaf.data;
623 /* make sure last quadlet is zeroed out */
624 *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;
626 /* Copy keyword(s) into leaf data buffer */
627 for (i = 0; i < strc; i++) {
628 int len = strlen(strv[i]) + 1;
629 memcpy(buffer, strv[i], len);
630 buffer += len;
632 return kv;
636 /* Destruction Routines */
638 void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
639 struct csr1212_keyval *kv)
641 struct csr1212_dentry *dentry;
643 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
644 return;
646 dentry = csr1212_find_keyval(dir, kv);
648 if (!dentry)
649 return;
651 if (dentry->prev)
652 dentry->prev->next = dentry->next;
653 if (dentry->next)
654 dentry->next->prev = dentry->prev;
655 if (dir->value.directory.dentries_head == dentry)
656 dir->value.directory.dentries_head = dentry->next;
657 if (dir->value.directory.dentries_tail == dentry)
658 dir->value.directory.dentries_tail = dentry->prev;
660 CSR1212_FREE(dentry);
662 csr1212_release_keyval(kv);
666 void csr1212_disassociate_keyval(struct csr1212_keyval *kv)
668 if (kv->associate) {
669 csr1212_release_keyval(kv->associate);
672 kv->associate = NULL;
676 /* This function is used to free the memory taken by a keyval. If the given
677 * keyval is a directory type, then any keyvals contained in that directory
678 * will be destroyed as well if their respective refcnts are 0. By means of
679 * list manipulation, this routine will descend a directory structure in a
680 * non-recursive manner. */
681 void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
683 struct csr1212_keyval *k, *a;
684 struct csr1212_dentry dentry;
685 struct csr1212_dentry *head, *tail;
687 dentry.kv = kv;
688 dentry.next = NULL;
689 dentry.prev = NULL;
691 head = &dentry;
692 tail = head;
694 while (head) {
695 k = head->kv;
697 while (k) {
698 k->refcnt--;
700 if (k->refcnt > 0)
701 break;
703 a = k->associate;
705 if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
706 /* If the current entry is a directory, then move all
707 * the entries to the destruction list. */
708 if (k->value.directory.dentries_head) {
709 tail->next = k->value.directory.dentries_head;
710 k->value.directory.dentries_head->prev = tail;
711 tail = k->value.directory.dentries_tail;
714 free_keyval(k);
715 k = a;
718 head = head->next;
719 if (head) {
720 if (head->prev && head->prev != &dentry) {
721 CSR1212_FREE(head->prev);
723 head->prev = NULL;
724 } else if (tail != &dentry)
725 CSR1212_FREE(tail);
730 void csr1212_destroy_csr(struct csr1212_csr *csr)
732 struct csr1212_csr_rom_cache *c, *oc;
733 struct csr1212_cache_region *cr, *ocr;
735 csr1212_release_keyval(csr->root_kv);
737 c = csr->cache_head;
738 while (c) {
739 oc = c;
740 cr = c->filled_head;
741 while (cr) {
742 ocr = cr;
743 cr = cr->next;
744 CSR1212_FREE(ocr);
746 c = c->next;
747 CSR1212_FREE(oc);
750 CSR1212_FREE(csr);
755 /* CSR Image Creation */
757 static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
759 struct csr1212_csr_rom_cache *cache;
760 u_int64_t csr_addr;
762 if (!csr || !csr->ops->allocate_addr_range ||
763 !csr->ops->release_addr)
764 return CSR1212_ENOMEM;
766 /* ROM size must be a multiple of csr->max_rom */
767 romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
769 csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
770 if (csr_addr == ~0ULL) {
771 return CSR1212_ENOMEM;
773 if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
774 /* Invalid address returned from allocate_addr_range(). */
775 csr->ops->release_addr(csr_addr, csr->private);
776 return CSR1212_ENOMEM;
779 cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
780 if (!cache) {
781 csr->ops->release_addr(csr_addr, csr->private);
782 return CSR1212_ENOMEM;
785 cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);
786 if (!cache->ext_rom) {
787 csr->ops->release_addr(csr_addr, csr->private);
788 CSR1212_FREE(cache);
789 return CSR1212_ENOMEM;
792 if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) {
793 csr1212_release_keyval(cache->ext_rom);
794 csr->ops->release_addr(csr_addr, csr->private);
795 CSR1212_FREE(cache);
796 return CSR1212_ENOMEM;
798 cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
799 cache->ext_rom->value.leaf.len = 0;
801 /* Add cache to tail of cache list */
802 cache->prev = csr->cache_tail;
803 csr->cache_tail->next = cache;
804 csr->cache_tail = cache;
805 return CSR1212_SUCCESS;
808 static inline void csr1212_remove_cache(struct csr1212_csr *csr,
809 struct csr1212_csr_rom_cache *cache)
811 if (csr->cache_head == cache)
812 csr->cache_head = cache->next;
813 if (csr->cache_tail == cache)
814 csr->cache_tail = cache->prev;
816 if (cache->prev)
817 cache->prev->next = cache->next;
818 if (cache->next)
819 cache->next->prev = cache->prev;
821 if (cache->ext_rom) {
822 csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
823 csr1212_release_keyval(cache->ext_rom);
826 CSR1212_FREE(cache);
829 static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
830 struct csr1212_keyval **layout_tail)
832 struct csr1212_dentry *dentry;
833 struct csr1212_keyval *dkv;
834 struct csr1212_keyval *last_extkey_spec = NULL;
835 struct csr1212_keyval *last_extkey = NULL;
836 int num_entries = 0;
838 for (dentry = dir->value.directory.dentries_head; dentry;
839 dentry = dentry->next) {
840 for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
841 /* Special Case: Extended Key Specifier_ID */
842 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
843 if (last_extkey_spec == NULL) {
844 last_extkey_spec = dkv;
845 } else if (dkv->value.immediate != last_extkey_spec->value.immediate) {
846 last_extkey_spec = dkv;
847 } else {
848 continue;
850 /* Special Case: Extended Key */
851 } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
852 if (last_extkey == NULL) {
853 last_extkey = dkv;
854 } else if (dkv->value.immediate != last_extkey->value.immediate) {
855 last_extkey = dkv;
856 } else {
857 continue;
861 num_entries += 1;
863 switch(dkv->key.type) {
864 default:
865 case CSR1212_KV_TYPE_IMMEDIATE:
866 case CSR1212_KV_TYPE_CSR_OFFSET:
867 continue;
868 case CSR1212_KV_TYPE_LEAF:
869 case CSR1212_KV_TYPE_DIRECTORY:
870 /* Remove from list */
871 if (dkv->prev)
872 dkv->prev->next = dkv->next;
873 if (dkv->next)
874 dkv->next->prev = dkv->prev;
875 if (dkv == *layout_tail)
876 *layout_tail = dkv->prev;
878 /* Special case: Extended ROM leafs */
879 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
880 dkv->value.leaf.len = 0; /* initialize to zero */
881 /* Don't add Extended ROM leafs in the layout list,
882 * they are handled differently. */
883 break;
886 /* Add to tail of list */
887 dkv->next = NULL;
888 dkv->prev = *layout_tail;
889 (*layout_tail)->next = dkv;
890 *layout_tail = dkv;
891 break;
895 return num_entries;
898 size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
900 struct csr1212_keyval *ltail = kv;
901 size_t agg_size = 0;
903 while(kv) {
904 switch(kv->key.type) {
905 case CSR1212_KV_TYPE_LEAF:
906 /* Add 1 quadlet for crc/len field */
907 agg_size += kv->value.leaf.len + 1;
908 break;
910 case CSR1212_KV_TYPE_DIRECTORY:
911 kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);
912 /* Add 1 quadlet for crc/len field */
913 agg_size += kv->value.directory.len + 1;
914 break;
916 kv = kv->next;
918 return quads_to_bytes(agg_size);
921 struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
922 struct csr1212_keyval *start_kv,
923 int start_pos)
925 struct csr1212_keyval *kv = start_kv;
926 struct csr1212_keyval *okv = start_kv;
927 int pos = start_pos;
928 int kv_len = 0, okv_len = 0;
930 cache->layout_head = kv;
932 while(kv && pos < cache->size) {
933 kv->offset = cache->offset + pos;
935 switch(kv->key.type) {
936 case CSR1212_KV_TYPE_LEAF:
937 kv_len = kv->value.leaf.len;
938 break;
940 case CSR1212_KV_TYPE_DIRECTORY:
941 kv_len = kv->value.directory.len;
942 break;
944 default:
945 /* Should never get here */
946 break;
949 pos += quads_to_bytes(kv_len + 1);
951 if (pos <= cache->size) {
952 okv = kv;
953 okv_len = kv_len;
954 kv = kv->next;
958 cache->layout_tail = okv;
959 cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
961 return kv;
964 static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,
965 u_int32_t *data_buffer)
967 struct csr1212_dentry *dentry;
968 struct csr1212_keyval *last_extkey_spec = NULL;
969 struct csr1212_keyval *last_extkey = NULL;
970 int index = 0;
972 for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
973 struct csr1212_keyval *a;
975 for (a = dentry->kv; a; a = a->associate) {
976 u_int32_t value = 0;
978 /* Special Case: Extended Key Specifier_ID */
979 if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
980 if (last_extkey_spec == NULL) {
981 last_extkey_spec = a;
982 } else if (a->value.immediate != last_extkey_spec->value.immediate) {
983 last_extkey_spec = a;
984 } else {
985 continue;
987 /* Special Case: Extended Key */
988 } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
989 if (last_extkey == NULL) {
990 last_extkey = a;
991 } else if (a->value.immediate != last_extkey->value.immediate) {
992 last_extkey = a;
993 } else {
994 continue;
998 switch(a->key.type) {
999 case CSR1212_KV_TYPE_IMMEDIATE:
1000 value = a->value.immediate;
1001 break;
1002 case CSR1212_KV_TYPE_CSR_OFFSET:
1003 value = a->value.csr_offset;
1004 break;
1005 case CSR1212_KV_TYPE_LEAF:
1006 value = a->offset;
1007 value -= dir->offset + quads_to_bytes(1+index);
1008 value = bytes_to_quads(value);
1009 break;
1010 case CSR1212_KV_TYPE_DIRECTORY:
1011 value = a->offset;
1012 value -= dir->offset + quads_to_bytes(1+index);
1013 value = bytes_to_quads(value);
1014 break;
1015 default:
1016 /* Should never get here */
1017 break; /* GDB breakpoint */
1020 value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;
1021 value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
1022 (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);
1023 data_buffer[index] = CSR1212_CPU_TO_BE32(value);
1024 index++;
1029 void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
1031 struct csr1212_keyval *kv, *nkv;
1032 struct csr1212_keyval_img *kvi;
1034 for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {
1035 kvi = (struct csr1212_keyval_img *)
1036 (cache->data + bytes_to_quads(kv->offset - cache->offset));
1037 switch(kv->key.type) {
1038 default:
1039 case CSR1212_KV_TYPE_IMMEDIATE:
1040 case CSR1212_KV_TYPE_CSR_OFFSET:
1041 /* Should never get here */
1042 break; /* GDB breakpoint */
1044 case CSR1212_KV_TYPE_LEAF:
1045 /* Don't copy over Extended ROM areas, they are
1046 * already filled out! */
1047 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1048 memcpy(kvi->data, kv->value.leaf.data,
1049 quads_to_bytes(kv->value.leaf.len));
1051 kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);
1052 kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
1053 break;
1055 case CSR1212_KV_TYPE_DIRECTORY:
1056 csr1212_generate_tree_subdir(kv, kvi->data);
1058 kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);
1059 kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
1060 break;
1063 nkv = kv->next;
1064 if (kv->prev)
1065 kv->prev->next = NULL;
1066 if (kv->next)
1067 kv->next->prev = NULL;
1068 kv->prev = NULL;
1069 kv->next = NULL;
1073 int csr1212_generate_csr_image(struct csr1212_csr *csr)
1075 struct csr1212_bus_info_block_img *bi;
1076 struct csr1212_csr_rom_cache *cache;
1077 struct csr1212_keyval *kv;
1078 size_t agg_size;
1079 int ret;
1080 int init_offset;
1082 if (!csr)
1083 return CSR1212_EINVAL;
1085 cache = csr->cache_head;
1087 bi = (struct csr1212_bus_info_block_img*)cache->data;
1089 bi->length = bytes_to_quads(csr->bus_info_len) - 1;
1090 bi->crc_length = bi->length;
1091 bi->crc = csr1212_crc16(bi->data, bi->crc_length);
1093 agg_size = csr1212_generate_layout_order(csr->root_kv);
1095 init_offset = csr->bus_info_len;
1097 for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
1098 if (!cache) {
1099 /* Estimate approximate number of additional cache
1100 * regions needed (it assumes that the cache holding
1101 * the first 1K Config ROM space always exists). */
1102 int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
1103 (2 * sizeof(u_int32_t))) + 1;
1105 /* Add additional cache regions, extras will be
1106 * removed later */
1107 for (; est_c; est_c--) {
1108 ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
1109 if (ret != CSR1212_SUCCESS)
1110 return ret;
1112 /* Need to re-layout for additional cache regions */
1113 agg_size = csr1212_generate_layout_order(csr->root_kv);
1114 kv = csr->root_kv;
1115 cache = csr->cache_head;
1116 init_offset = csr->bus_info_len;
1118 kv = csr1212_generate_positions(cache, kv, init_offset);
1119 agg_size -= cache->len;
1120 init_offset = sizeof(u_int32_t);
1123 /* Remove unused, excess cache regions */
1124 while (cache) {
1125 struct csr1212_csr_rom_cache *oc = cache;
1127 cache = cache->next;
1128 csr1212_remove_cache(csr, oc);
1131 /* Go through the list backward so that when done, the correct CRC
1132 * will be calculated for the Extended ROM areas. */
1133 for(cache = csr->cache_tail; cache; cache = cache->prev) {
1134 /* Only Extended ROM caches should have this set. */
1135 if (cache->ext_rom) {
1136 int leaf_size;
1138 /* Make sure the Extended ROM leaf is a multiple of
1139 * max_rom in size. */
1140 leaf_size = (cache->len + (csr->max_rom - 1)) &
1141 ~(csr->max_rom - 1);
1143 /* Zero out the unused ROM region */
1144 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1145 leaf_size - cache->len);
1147 /* Subtract leaf header */
1148 leaf_size -= sizeof(u_int32_t);
1150 /* Update the Extended ROM leaf length */
1151 cache->ext_rom->value.leaf.len =
1152 bytes_to_quads(leaf_size);
1153 } else {
1154 /* Zero out the unused ROM region */
1155 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1156 cache->size - cache->len);
1159 /* Copy the data into the cache buffer */
1160 csr1212_fill_cache(cache);
1163 return CSR1212_SUCCESS;
1166 int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len)
1168 struct csr1212_csr_rom_cache *cache;
1170 for (cache = csr->cache_head; cache; cache = cache->next) {
1171 if (offset >= cache->offset &&
1172 (offset + len) <= (cache->offset + cache->size)) {
1173 memcpy(buffer,
1174 &cache->data[bytes_to_quads(offset - cache->offset)],
1175 len);
1176 return CSR1212_SUCCESS;
1177 } else if (((offset < cache->offset) &&
1178 ((offset + len) >= cache->offset)) ||
1179 ((offset >= cache->offset) &&
1180 ((offset + len) > (cache->offset + cache->size)))) {
1181 return CSR1212_EINVAL;
1184 return CSR1212_ENOENT;
1189 /* Parse a chunk of data as a Config ROM */
1191 static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
1193 struct csr1212_bus_info_block_img *bi;
1194 struct csr1212_cache_region *cr;
1195 int i;
1196 int ret;
1198 /* IEEE 1212 says that the entire bus info block should be readable in
1199 * a single transaction regardless of the max_rom value.
1200 * Unfortunately, many IEEE 1394 devices do not abide by that, so the
1201 * bus info block will be read 1 quadlet at a time. The rest of the
1202 * ConfigROM will be read according to the max_rom field. */
1203 for (i = 0; i < csr->bus_info_len; i += sizeof(csr1212_quad_t)) {
1204 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1205 sizeof(csr1212_quad_t),
1206 &csr->cache_head->data[bytes_to_quads(i)],
1207 csr->private);
1208 if (ret != CSR1212_SUCCESS)
1209 return ret;
1212 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1213 csr->crc_len = quads_to_bytes(bi->crc_length);
1215 /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
1216 * always the case, so read the rest of the crc area 1 quadlet at a time. */
1217 for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) {
1218 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1219 sizeof(csr1212_quad_t),
1220 &csr->cache_head->data[bytes_to_quads(i)],
1221 csr->private);
1222 if (ret != CSR1212_SUCCESS)
1223 return ret;
1226 if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
1227 return CSR1212_EINVAL;
1229 #if 0
1230 /* Apparently there are too many differnt wrong implementations of the
1231 * CRC algorithm that verifying them is moot. */
1232 if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
1233 (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
1234 return CSR1212_EINVAL;
1235 #endif
1237 cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1238 if (!cr)
1239 return CSR1212_ENOMEM;
1241 cr->next = NULL;
1242 cr->prev = NULL;
1243 cr->offset_start = 0;
1244 cr->offset_end = csr->crc_len + 4;
1246 csr->cache_head->filled_head = cr;
1247 csr->cache_head->filled_tail = cr;
1249 return CSR1212_SUCCESS;
1252 static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
1253 csr1212_quad_t ki,
1254 u_int32_t kv_pos,
1255 struct csr1212_csr_rom_cache *cache)
1257 int ret = CSR1212_SUCCESS;
1258 struct csr1212_keyval *k = NULL;
1259 u_int32_t offset;
1261 switch(CSR1212_KV_KEY_TYPE(ki)) {
1262 case CSR1212_KV_TYPE_IMMEDIATE:
1263 k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
1264 CSR1212_KV_VAL(ki));
1265 if (!k) {
1266 ret = CSR1212_ENOMEM;
1267 goto fail;
1270 k->refcnt = 0; /* Don't keep local reference when parsing. */
1271 break;
1273 case CSR1212_KV_TYPE_CSR_OFFSET:
1274 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1275 CSR1212_KV_VAL(ki));
1276 if (!k) {
1277 ret = CSR1212_ENOMEM;
1278 goto fail;
1280 k->refcnt = 0; /* Don't keep local reference when parsing. */
1281 break;
1283 default:
1284 /* Compute the offset from 0xffff f000 0000. */
1285 offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
1286 if (offset == kv_pos) {
1287 /* Uh-oh. Can't have a relative offset of 0 for Leaves
1288 * or Directories. The Config ROM image is most likely
1289 * messed up, so we'll just abort here. */
1290 ret = CSR1212_EIO;
1291 goto fail;
1294 k = csr1212_find_keyval_offset(cache->layout_head, offset);
1296 if (k)
1297 break; /* Found it. */
1299 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1300 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1301 } else {
1302 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1304 if (!k) {
1305 ret = CSR1212_ENOMEM;
1306 goto fail;
1308 k->refcnt = 0; /* Don't keep local reference when parsing. */
1309 k->valid = 0; /* Contents not read yet so it's not valid. */
1310 k->offset = offset;
1312 k->prev = cache->layout_tail;
1313 k->next = NULL;
1314 if (cache->layout_tail)
1315 cache->layout_tail->next = k;
1316 cache->layout_tail = k;
1318 ret = csr1212_attach_keyval_to_directory(dir, k);
1320 fail:
1321 if (ret != CSR1212_SUCCESS) {
1322 if (k)
1323 free_keyval(k);
1325 return ret;
1328 int csr1212_parse_keyval(struct csr1212_keyval *kv,
1329 struct csr1212_csr_rom_cache *cache)
1331 struct csr1212_keyval_img *kvi;
1332 int i;
1333 int ret = CSR1212_SUCCESS;
1334 int kvi_len;
1336 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1337 cache->offset)];
1338 kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
1340 #if 0
1341 /* Apparently there are too many differnt wrong implementations of the
1342 * CRC algorithm that verifying them is moot. */
1343 if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
1344 (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
1345 ret = CSR1212_EINVAL;
1346 goto fail;
1348 #endif
1350 switch(kv->key.type) {
1351 case CSR1212_KV_TYPE_DIRECTORY:
1352 for (i = 0; i < kvi_len; i++) {
1353 csr1212_quad_t ki = kvi->data[i];
1355 /* Some devices put null entries in their unit
1356 * directories. If we come across such and entry,
1357 * then skip it. */
1358 if (ki == 0x0)
1359 continue;
1360 ret = csr1212_parse_dir_entry(kv, ki,
1361 (kv->offset +
1362 quads_to_bytes(i + 1)),
1363 cache);
1365 kv->value.directory.len = kvi_len;
1366 break;
1368 case CSR1212_KV_TYPE_LEAF:
1369 if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
1370 kv->value.leaf.data = cache->data;
1371 } else {
1372 kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
1373 if (!kv->value.leaf.data)
1375 ret = CSR1212_ENOMEM;
1376 goto fail;
1379 kv->value.leaf.len = kvi_len;
1380 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1382 break;
1385 kv->valid = 1;
1387 fail:
1388 return ret;
1392 int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1394 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1395 struct csr1212_keyval_img *kvi = NULL;
1396 struct csr1212_csr_rom_cache *cache;
1397 int cache_index;
1398 u_int64_t addr;
1399 u_int32_t *cache_ptr;
1400 u_int16_t kv_len = 0;
1403 if (!csr || !kv)
1404 return CSR1212_EINVAL;
1406 /* First find which cache the data should be in (or go in if not read
1407 * yet). */
1408 for (cache = csr->cache_head; cache; cache = cache->next) {
1409 if (kv->offset >= cache->offset &&
1410 kv->offset < (cache->offset + cache->size))
1411 break;
1414 if (!cache) {
1415 csr1212_quad_t q;
1416 struct csr1212_csr_rom_cache *nc;
1418 /* Only create a new cache for Extended ROM leaves. */
1419 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1420 return CSR1212_EINVAL;
1422 if (csr->ops->bus_read(csr,
1423 CSR1212_REGISTER_SPACE_BASE + kv->offset,
1424 sizeof(csr1212_quad_t), &q, csr->private)) {
1425 return CSR1212_EIO;
1428 kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16);
1430 nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len);
1431 cache->next = nc;
1432 nc->prev = cache;
1433 csr->cache_tail = nc;
1434 cache->filled_head =
1435 CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1436 if (!cache->filled_head) {
1437 return CSR1212_ENOMEM;
1440 cache->filled_head->offset_start = 0;
1441 cache->filled_head->offset_end = sizeof(csr1212_quad_t);
1442 cache->filled_tail = cache->filled_head;
1443 cache->filled_head->next = NULL;
1444 cache->filled_head->prev = NULL;
1445 cache->data[0] = q;
1448 cache_index = kv->offset - cache->offset;
1450 /* Now seach read portions of the cache to see if it is there. */
1451 for (cr = cache->filled_head; cr; cr = cr->next) {
1452 if (cache_index < cr->offset_start) {
1453 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1454 if (!newcr)
1455 return CSR1212_ENOMEM;
1457 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1458 newcr->offset_end = newcr->offset_start;
1459 newcr->next = cr;
1460 newcr->prev = cr->prev;
1461 cr->prev = newcr;
1462 cr = newcr;
1463 break;
1464 } else if ((cache_index >= cr->offset_start) &&
1465 (cache_index < cr->offset_end)) {
1466 kvi = (struct csr1212_keyval_img*)
1467 (&cache->data[bytes_to_quads(cache_index)]);
1468 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1470 break;
1471 } else if (cache_index == cr->offset_end)
1472 break;
1475 if (!cr) {
1476 cr = cache->filled_tail;
1477 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1478 if (!newcr)
1479 return CSR1212_ENOMEM;
1481 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1482 newcr->offset_end = newcr->offset_start;
1483 newcr->prev = cr;
1484 newcr->next = cr->next;
1485 cr->next = newcr;
1486 cr = newcr;
1487 cache->filled_tail = newcr;
1490 while(!kvi || cr->offset_end < cache_index + kv_len) {
1491 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1492 ~(csr->max_rom - 1))];
1494 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1495 cr->offset_end) & ~(csr->max_rom - 1);
1497 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1498 csr->private)) {
1499 if (csr->max_rom == 4)
1500 /* We've got problems! */
1501 return CSR1212_EIO;
1503 /* Apperently the max_rom value was a lie, set it to
1504 * do quadlet reads and try again. */
1505 csr->max_rom = 4;
1506 continue;
1509 cr->offset_end += csr->max_rom - (cr->offset_end &
1510 (csr->max_rom - 1));
1512 if (!kvi && (cr->offset_end > cache_index)) {
1513 kvi = (struct csr1212_keyval_img*)
1514 (&cache->data[bytes_to_quads(cache_index)]);
1515 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1519 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1520 /* The Leaf or Directory claims its length extends
1521 * beyond the ConfigROM image region and thus beyond the
1522 * end of our cache region. Therefore, we abort now
1523 * rather than seg faulting later. */
1524 return CSR1212_EIO;
1527 ncr = cr->next;
1529 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1530 /* consolidate region entries */
1531 ncr->offset_start = cr->offset_start;
1533 if (cr->prev)
1534 cr->prev->next = cr->next;
1535 ncr->prev = cr->prev;
1536 if (cache->filled_head == cr)
1537 cache->filled_head = ncr;
1538 CSR1212_FREE(cr);
1539 cr = ncr;
1543 return csr1212_parse_keyval(kv, cache);
1548 int csr1212_parse_csr(struct csr1212_csr *csr)
1550 static const int mr_map[] = { 4, 64, 1024, 0 };
1551 int ret;
1553 if (!csr || !csr->ops->bus_read)
1554 return CSR1212_EINVAL;
1556 ret = csr1212_parse_bus_info_block(csr);
1557 if (ret != CSR1212_SUCCESS)
1558 return ret;
1560 if (!csr->ops->get_max_rom)
1561 csr->max_rom = mr_map[0]; /* default value */
1562 else
1563 csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data,
1564 csr->private)];
1566 csr->cache_head->layout_head = csr->root_kv;
1567 csr->cache_head->layout_tail = csr->root_kv;
1569 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1570 csr->bus_info_len;
1572 csr->root_kv->valid = 0;
1573 csr1212_get_keyval(csr, csr->root_kv);
1575 return CSR1212_SUCCESS;