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.
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.
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] = {
51 __D | __L, /* Descriptor */
52 __I | __D | __L, /* Bus_Dependent_Info */
53 __I | __D | __L, /* Vendor */
54 __I, /* Hardware_Version */
56 __D | __L, /* Module */
57 0, 0, 0, 0, /* Reserved */
58 __I, /* Node_Capabilities */
60 0, 0, 0, /* Reserved */
62 __I, /* Specifier_ID */
64 __I | __C | __D | __L, /* Dependent_Info */
65 __L, /* Unit_Location */
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 */
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 (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM))
92 CSR1212_FREE(kv->value.leaf.data);
97 static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length)
101 u_int16_t sum, crc = 0;
103 for (; length; length--) {
104 data = CSR1212_BE32_TO_CPU(*buffer);
106 for (shift = 28; shift >= 0; shift -= 4 ) {
107 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
108 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
113 return CSR1212_CPU_TO_BE16(crc);
117 /* Microsoft computes the CRC with the bytes in reverse order. Therefore we
118 * have a special version of the CRC algorithm to account for their buggy
120 static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length)
124 u_int16_t sum, crc = 0;
126 for (; length; length--) {
127 data = CSR1212_LE32_TO_CPU(*buffer);
129 for (shift = 28; shift >= 0; shift -= 4 ) {
130 sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
131 crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
136 return CSR1212_CPU_TO_BE16(crc);
140 static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir,
141 struct csr1212_keyval *kv)
143 struct csr1212_dentry *pos;
145 for (pos = dir->value.directory.dentries_head;
146 pos != NULL; pos = pos->next) {
154 static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list,
157 struct csr1212_keyval *kv;
159 for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) {
160 if (kv->offset == offset)
167 /* Creation Routines */
168 struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
169 size_t bus_info_size, void *private)
171 struct csr1212_csr *csr;
173 csr = CSR1212_MALLOC(sizeof(*csr));
178 csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
179 CSR1212_CONFIG_ROM_SPACE_SIZE);
180 if (!csr->cache_head) {
185 /* The keyval key id is not used for the root node, but a valid key id
186 * that can be used for a directory needs to be passed to
187 * csr1212_new_directory(). */
188 csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
190 CSR1212_FREE(csr->cache_head);
195 csr->bus_info_data = csr->cache_head->data;
196 csr->bus_info_len = bus_info_size;
197 csr->crc_len = bus_info_size;
199 csr->private = private;
200 csr->cache_tail = csr->cache_head;
207 void csr1212_init_local_csr(struct csr1212_csr *csr,
208 const u_int32_t *bus_info_data, int max_rom)
210 static const int mr_map[] = { 4, 64, 1024, 0 };
212 csr->max_rom = mr_map[max_rom];
213 memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
217 static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key)
219 struct csr1212_keyval *kv;
221 if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
224 kv = CSR1212_MALLOC(sizeof(*kv));
231 kv->associate = NULL;
241 struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value)
243 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
248 kv->value.immediate = value;
253 struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len)
255 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
261 kv->value.leaf.data = CSR1212_MALLOC(data_len);
262 if (!kv->value.leaf.data) {
268 memcpy(kv->value.leaf.data, data, data_len);
270 kv->value.leaf.data = NULL;
273 kv->value.leaf.len = bytes_to_quads(data_len);
280 struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset)
282 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
287 kv->value.csr_offset = csr_offset;
294 struct csr1212_keyval *csr1212_new_directory(u_int8_t key)
296 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
301 kv->value.directory.len = 0;
303 kv->value.directory.dentries_head = NULL;
304 kv->value.directory.dentries_tail = NULL;
309 int csr1212_associate_keyval(struct csr1212_keyval *kv,
310 struct csr1212_keyval *associate)
312 if (!kv || !associate)
313 return CSR1212_EINVAL;
315 if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
316 (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
317 associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
318 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
319 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
320 associate->key.id < 0x30))
321 return CSR1212_EINVAL;
323 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
324 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY)
325 return CSR1212_EINVAL;
327 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
328 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA)
329 return CSR1212_EINVAL;
331 if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
332 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID)
333 return CSR1212_EINVAL;
335 if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
336 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)
337 return CSR1212_EINVAL;
340 csr1212_release_keyval(kv->associate);
343 kv->associate = associate;
345 return CSR1212_SUCCESS;
348 int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
349 struct csr1212_keyval *kv)
351 struct csr1212_dentry *dentry;
353 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
354 return CSR1212_EINVAL;
356 dentry = CSR1212_MALLOC(sizeof(*dentry));
358 return CSR1212_ENOMEM;
365 dentry->prev = dir->value.directory.dentries_tail;
367 if (!dir->value.directory.dentries_head)
368 dir->value.directory.dentries_head = dentry;
370 if (dir->value.directory.dentries_tail)
371 dir->value.directory.dentries_tail->next = dentry;
372 dir->value.directory.dentries_tail = dentry;
374 return CSR1212_SUCCESS;
377 struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key,
380 struct csr1212_keyval *kvs, *kvk, *kvv;
382 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
383 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
384 kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value);
386 if (!kvs || !kvk || !kvv) {
396 /* Don't keep a local reference to the extended key or value. */
400 csr1212_associate_keyval(kvk, kvv);
401 csr1212_associate_keyval(kvs, kvk);
406 struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key,
407 const void *data, size_t data_len)
409 struct csr1212_keyval *kvs, *kvk, *kvv;
411 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
412 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
413 kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len);
415 if (!kvs || !kvk || !kvv) {
425 /* Don't keep a local reference to the extended key or value. */
429 csr1212_associate_keyval(kvk, kvv);
430 csr1212_associate_keyval(kvs, kvk);
435 struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id,
436 const void *data, size_t data_len)
438 struct csr1212_keyval *kv;
440 kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
441 data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
445 CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
446 CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
449 memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
456 struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
462 struct csr1212_keyval *kv;
465 kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
466 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
470 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth);
471 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset);
472 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
474 lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
476 /* make sure last quadlet is zeroed out */
477 *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0;
479 /* don't copy the NUL terminator */
480 memcpy(lstr, data, data_len);
485 static int csr1212_check_minimal_ascii(const char *s)
487 static const char minimal_ascii_table[] = {
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
489 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
491 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
492 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27,
493 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
494 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
495 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
496 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
497 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
498 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
499 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
500 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
501 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
502 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
503 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
506 if (minimal_ascii_table[*s & 0x7F] != *s)
507 return -1; /* failed */
509 /* String conforms to minimal-ascii, as specified by IEEE 1212,
514 struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
516 /* Check if string conform to minimal_ascii format */
517 if (csr1212_check_minimal_ascii(s))
520 /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */
521 return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s));
524 struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
525 u_int8_t palette_depth,
526 u_int8_t color_space,
533 static const int pd[4] = { 0, 4, 16, 256 };
534 static const int cs[16] = { 4, 2 };
535 struct csr1212_keyval *kv;
536 int palette_size = pd[palette_depth] * cs[color_space];
537 int pixel_size = (hscan * vscan + 3) & ~0x3;
539 if ((palette_depth && !palette) || !pixels)
542 kv = csr1212_new_descriptor_leaf(1, 0, NULL,
543 palette_size + pixel_size +
544 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
548 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version);
549 CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth);
550 CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space);
551 CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
552 CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan);
553 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan);
556 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,
559 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);
564 struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
567 struct csr1212_keyval *kv;
569 /* IEEE 1212, par. 7.5.4.3 Modifiable descriptors */
570 kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t));
574 CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size);
575 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address);
576 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address);
581 static int csr1212_check_keyword(const char *s)
585 if (('A' <= *s) && (*s <= 'Z'))
587 if (('0' <= *s) && (*s <= '9'))
592 return -1; /* failed */
594 /* String conforms to keyword, as specified by IEEE 1212,
596 return CSR1212_SUCCESS;
599 struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[])
601 struct csr1212_keyval *kv;
605 /* Check all keywords to see if they conform to restrictions:
606 * Only the following characters is allowed ['A'..'Z','0'..'9','-']
607 * Each word is zero-terminated.
608 * Also calculate the total length of the keywords.
610 for (i = 0; i < strc; i++) {
611 if (!strv[i] || csr1212_check_keyword(strv[i])) {
614 data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */
617 /* IEEE 1212, par. 7.6.5 Keyword leaves */
618 kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);
622 buffer = (char *)kv->value.leaf.data;
624 /* make sure last quadlet is zeroed out */
625 *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;
627 /* Copy keyword(s) into leaf data buffer */
628 for (i = 0; i < strc; i++) {
629 int len = strlen(strv[i]) + 1;
630 memcpy(buffer, strv[i], len);
637 /* Destruction Routines */
639 void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
640 struct csr1212_keyval *kv)
642 struct csr1212_dentry *dentry;
644 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
647 dentry = csr1212_find_keyval(dir, kv);
653 dentry->prev->next = dentry->next;
655 dentry->next->prev = dentry->prev;
656 if (dir->value.directory.dentries_head == dentry)
657 dir->value.directory.dentries_head = dentry->next;
658 if (dir->value.directory.dentries_tail == dentry)
659 dir->value.directory.dentries_tail = dentry->prev;
661 CSR1212_FREE(dentry);
663 csr1212_release_keyval(kv);
667 void csr1212_disassociate_keyval(struct csr1212_keyval *kv)
670 csr1212_release_keyval(kv->associate);
673 kv->associate = NULL;
677 /* This function is used to free the memory taken by a keyval. If the given
678 * keyval is a directory type, then any keyvals contained in that directory
679 * will be destroyed as well if their respective refcnts are 0. By means of
680 * list manipulation, this routine will descend a directory structure in a
681 * non-recursive manner. */
682 void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
684 struct csr1212_keyval *k, *a;
685 struct csr1212_dentry dentry;
686 struct csr1212_dentry *head, *tail;
706 if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
707 /* If the current entry is a directory, then move all
708 * the entries to the destruction list. */
709 if (k->value.directory.dentries_head) {
710 tail->next = k->value.directory.dentries_head;
711 k->value.directory.dentries_head->prev = tail;
712 tail = k->value.directory.dentries_tail;
721 if (head->prev && head->prev != &dentry) {
722 CSR1212_FREE(head->prev);
725 } else if (tail != &dentry)
731 void csr1212_destroy_csr(struct csr1212_csr *csr)
733 struct csr1212_csr_rom_cache *c, *oc;
734 struct csr1212_cache_region *cr, *ocr;
736 csr1212_release_keyval(csr->root_kv);
756 /* CSR Image Creation */
758 static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
760 struct csr1212_csr_rom_cache *cache;
763 if (!csr || !csr->ops->allocate_addr_range ||
764 !csr->ops->release_addr)
765 return CSR1212_ENOMEM;
767 /* ROM size must be a multiple of csr->max_rom */
768 romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
770 csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
771 if (csr_addr == ~0ULL) {
772 return CSR1212_ENOMEM;
774 if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
775 /* Invalid address returned from allocate_addr_range(). */
776 csr->ops->release_addr(csr_addr, csr->private);
777 return CSR1212_ENOMEM;
780 cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
782 csr->ops->release_addr(csr_addr, csr->private);
783 return CSR1212_ENOMEM;
786 cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);
787 if (!cache->ext_rom) {
788 csr->ops->release_addr(csr_addr, csr->private);
790 return CSR1212_ENOMEM;
793 if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) {
794 csr1212_release_keyval(cache->ext_rom);
795 csr->ops->release_addr(csr_addr, csr->private);
797 return CSR1212_ENOMEM;
799 cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
800 cache->ext_rom->value.leaf.len = -1;
801 cache->ext_rom->value.leaf.data = cache->data;
803 /* Add cache to tail of cache list */
804 cache->prev = csr->cache_tail;
805 csr->cache_tail->next = cache;
806 csr->cache_tail = cache;
807 return CSR1212_SUCCESS;
810 static inline void csr1212_remove_cache(struct csr1212_csr *csr,
811 struct csr1212_csr_rom_cache *cache)
813 if (csr->cache_head == cache)
814 csr->cache_head = cache->next;
815 if (csr->cache_tail == cache)
816 csr->cache_tail = cache->prev;
819 cache->prev->next = cache->next;
821 cache->next->prev = cache->prev;
823 if (cache->ext_rom) {
824 csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
825 csr1212_release_keyval(cache->ext_rom);
831 static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
832 struct csr1212_keyval **layout_tail)
834 struct csr1212_dentry *dentry;
835 struct csr1212_keyval *dkv;
836 struct csr1212_keyval *last_extkey_spec = NULL;
837 struct csr1212_keyval *last_extkey = NULL;
840 for (dentry = dir->value.directory.dentries_head; dentry;
841 dentry = dentry->next) {
842 for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
843 /* Special Case: Extended Key Specifier_ID */
844 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
845 if (last_extkey_spec == NULL) {
846 last_extkey_spec = dkv;
847 } else if (dkv->value.immediate != last_extkey_spec->value.immediate) {
848 last_extkey_spec = dkv;
852 /* Special Case: Extended Key */
853 } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
854 if (last_extkey == NULL) {
856 } else if (dkv->value.immediate != last_extkey->value.immediate) {
865 switch(dkv->key.type) {
867 case CSR1212_KV_TYPE_IMMEDIATE:
868 case CSR1212_KV_TYPE_CSR_OFFSET:
870 case CSR1212_KV_TYPE_LEAF:
871 case CSR1212_KV_TYPE_DIRECTORY:
872 /* Remove from list */
873 if (dkv->prev && (dkv->prev->next == dkv))
874 dkv->prev->next = dkv->next;
875 if (dkv->next && (dkv->next->prev == dkv))
876 dkv->next->prev = dkv->prev;
877 //if (dkv == *layout_tail)
878 // *layout_tail = dkv->prev;
880 /* Special case: Extended ROM leafs */
881 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
882 dkv->value.leaf.len = -1;
883 /* Don't add Extended ROM leafs in the layout list,
884 * they are handled differently. */
888 /* Add to tail of list */
890 dkv->prev = *layout_tail;
891 (*layout_tail)->next = dkv;
900 size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
902 struct csr1212_keyval *ltail = kv;
906 switch(kv->key.type) {
907 case CSR1212_KV_TYPE_LEAF:
908 /* Add 1 quadlet for crc/len field */
909 agg_size += kv->value.leaf.len + 1;
912 case CSR1212_KV_TYPE_DIRECTORY:
913 kv->value.directory.len = csr1212_generate_layout_subdir(kv, <ail);
914 /* Add 1 quadlet for crc/len field */
915 agg_size += kv->value.directory.len + 1;
920 return quads_to_bytes(agg_size);
923 struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
924 struct csr1212_keyval *start_kv,
927 struct csr1212_keyval *kv = start_kv;
928 struct csr1212_keyval *okv = start_kv;
930 int kv_len = 0, okv_len = 0;
932 cache->layout_head = kv;
934 while(kv && pos < cache->size) {
935 /* Special case: Extended ROM leafs */
936 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
937 kv->offset = cache->offset + pos;
940 switch(kv->key.type) {
941 case CSR1212_KV_TYPE_LEAF:
942 kv_len = kv->value.leaf.len;
945 case CSR1212_KV_TYPE_DIRECTORY:
946 kv_len = kv->value.directory.len;
950 /* Should never get here */
954 pos += quads_to_bytes(kv_len + 1);
956 if (pos <= cache->size) {
963 cache->layout_tail = okv;
964 cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
969 static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,
970 u_int32_t *data_buffer)
972 struct csr1212_dentry *dentry;
973 struct csr1212_keyval *last_extkey_spec = NULL;
974 struct csr1212_keyval *last_extkey = NULL;
977 for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
978 struct csr1212_keyval *a;
980 for (a = dentry->kv; a; a = a->associate) {
983 /* Special Case: Extended Key Specifier_ID */
984 if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
985 if (last_extkey_spec == NULL) {
986 last_extkey_spec = a;
987 } else if (a->value.immediate != last_extkey_spec->value.immediate) {
988 last_extkey_spec = a;
992 /* Special Case: Extended Key */
993 } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
994 if (last_extkey == NULL) {
996 } else if (a->value.immediate != last_extkey->value.immediate) {
1003 switch(a->key.type) {
1004 case CSR1212_KV_TYPE_IMMEDIATE:
1005 value = a->value.immediate;
1007 case CSR1212_KV_TYPE_CSR_OFFSET:
1008 value = a->value.csr_offset;
1010 case CSR1212_KV_TYPE_LEAF:
1012 value -= dir->offset + quads_to_bytes(1+index);
1013 value = bytes_to_quads(value);
1015 case CSR1212_KV_TYPE_DIRECTORY:
1017 value -= dir->offset + quads_to_bytes(1+index);
1018 value = bytes_to_quads(value);
1021 /* Should never get here */
1022 break; /* GDB breakpoint */
1025 value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;
1026 value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
1027 (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);
1028 data_buffer[index] = CSR1212_CPU_TO_BE32(value);
1034 void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
1036 struct csr1212_keyval *kv, *nkv;
1037 struct csr1212_keyval_img *kvi;
1039 for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {
1040 kvi = (struct csr1212_keyval_img *)
1041 (cache->data + bytes_to_quads(kv->offset - cache->offset));
1042 switch(kv->key.type) {
1044 case CSR1212_KV_TYPE_IMMEDIATE:
1045 case CSR1212_KV_TYPE_CSR_OFFSET:
1046 /* Should never get here */
1047 break; /* GDB breakpoint */
1049 case CSR1212_KV_TYPE_LEAF:
1050 /* Don't copy over Extended ROM areas, they are
1051 * already filled out! */
1052 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1053 memcpy(kvi->data, kv->value.leaf.data,
1054 quads_to_bytes(kv->value.leaf.len));
1056 kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);
1057 kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
1060 case CSR1212_KV_TYPE_DIRECTORY:
1061 csr1212_generate_tree_subdir(kv, kvi->data);
1063 kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);
1064 kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
1070 kv->prev->next = NULL;
1072 kv->next->prev = NULL;
1078 int csr1212_generate_csr_image(struct csr1212_csr *csr)
1080 struct csr1212_bus_info_block_img *bi;
1081 struct csr1212_csr_rom_cache *cache;
1082 struct csr1212_keyval *kv;
1088 return CSR1212_EINVAL;
1090 cache = csr->cache_head;
1092 bi = (struct csr1212_bus_info_block_img*)cache->data;
1094 bi->length = bytes_to_quads(csr->bus_info_len) - 1;
1095 bi->crc_length = bi->length;
1096 bi->crc = csr1212_crc16(bi->data, bi->crc_length);
1098 csr->root_kv->next = NULL;
1099 csr->root_kv->prev = NULL;
1101 agg_size = csr1212_generate_layout_order(csr->root_kv);
1103 init_offset = csr->bus_info_len;
1105 for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
1107 /* Estimate approximate number of additional cache
1108 * regions needed (it assumes that the cache holding
1109 * the first 1K Config ROM space always exists). */
1110 int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
1111 (2 * sizeof(u_int32_t))) + 1;
1113 /* Add additional cache regions, extras will be
1115 for (; est_c; est_c--) {
1116 ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
1117 if (ret != CSR1212_SUCCESS)
1120 /* Need to re-layout for additional cache regions */
1121 agg_size = csr1212_generate_layout_order(csr->root_kv);
1123 cache = csr->cache_head;
1124 init_offset = csr->bus_info_len;
1126 kv = csr1212_generate_positions(cache, kv, init_offset);
1127 agg_size -= cache->len;
1128 init_offset = sizeof(u_int32_t);
1131 /* Remove unused, excess cache regions */
1133 struct csr1212_csr_rom_cache *oc = cache;
1135 cache = cache->next;
1136 csr1212_remove_cache(csr, oc);
1139 /* Go through the list backward so that when done, the correct CRC
1140 * will be calculated for the Extended ROM areas. */
1141 for(cache = csr->cache_tail; cache; cache = cache->prev) {
1142 /* Only Extended ROM caches should have this set. */
1143 if (cache->ext_rom) {
1146 /* Make sure the Extended ROM leaf is a multiple of
1147 * max_rom in size. */
1148 leaf_size = (cache->len + (csr->max_rom - 1)) &
1149 ~(csr->max_rom - 1);
1151 /* Zero out the unused ROM region */
1152 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1153 leaf_size - cache->len);
1155 /* Subtract leaf header */
1156 leaf_size -= sizeof(u_int32_t);
1158 /* Update the Extended ROM leaf length */
1159 cache->ext_rom->value.leaf.len =
1160 bytes_to_quads(leaf_size);
1162 /* Zero out the unused ROM region */
1163 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1164 cache->size - cache->len);
1167 /* Copy the data into the cache buffer */
1168 csr1212_fill_cache(cache);
1170 if (cache != csr->cache_head) {
1171 /* Set the length and CRC of the extended ROM. */
1172 struct csr1212_keyval_img *kvi =
1173 (struct csr1212_keyval_img*)cache->data;
1175 kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1);
1176 kvi->crc = csr1212_crc16(kvi->data,
1177 bytes_to_quads(cache->len) - 1);
1182 return CSR1212_SUCCESS;
1185 int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len)
1187 struct csr1212_csr_rom_cache *cache;
1189 for (cache = csr->cache_head; cache; cache = cache->next) {
1190 if (offset >= cache->offset &&
1191 (offset + len) <= (cache->offset + cache->size)) {
1193 &cache->data[bytes_to_quads(offset - cache->offset)],
1195 return CSR1212_SUCCESS;
1198 return CSR1212_ENOENT;
1203 /* Parse a chunk of data as a Config ROM */
1205 static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
1207 struct csr1212_bus_info_block_img *bi;
1208 struct csr1212_cache_region *cr;
1212 /* IEEE 1212 says that the entire bus info block should be readable in
1213 * a single transaction regardless of the max_rom value.
1214 * Unfortunately, many IEEE 1394 devices do not abide by that, so the
1215 * bus info block will be read 1 quadlet at a time. The rest of the
1216 * ConfigROM will be read according to the max_rom field. */
1217 for (i = 0; i < csr->bus_info_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)],
1222 if (ret != CSR1212_SUCCESS)
1226 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1227 csr->crc_len = quads_to_bytes(bi->crc_length);
1229 /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
1230 * always the case, so read the rest of the crc area 1 quadlet at a time. */
1231 for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) {
1232 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1233 sizeof(csr1212_quad_t),
1234 &csr->cache_head->data[bytes_to_quads(i)],
1236 if (ret != CSR1212_SUCCESS)
1240 if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
1241 return CSR1212_EINVAL;
1244 /* Apparently there are too many differnt wrong implementations of the
1245 * CRC algorithm that verifying them is moot. */
1246 if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
1247 (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
1248 return CSR1212_EINVAL;
1251 cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1253 return CSR1212_ENOMEM;
1257 cr->offset_start = 0;
1258 cr->offset_end = csr->crc_len + 4;
1260 csr->cache_head->filled_head = cr;
1261 csr->cache_head->filled_tail = cr;
1263 return CSR1212_SUCCESS;
1266 static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
1270 int ret = CSR1212_SUCCESS;
1271 struct csr1212_keyval *k = NULL;
1274 switch(CSR1212_KV_KEY_TYPE(ki)) {
1275 case CSR1212_KV_TYPE_IMMEDIATE:
1276 k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
1277 CSR1212_KV_VAL(ki));
1279 ret = CSR1212_ENOMEM;
1283 k->refcnt = 0; /* Don't keep local reference when parsing. */
1286 case CSR1212_KV_TYPE_CSR_OFFSET:
1287 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1288 CSR1212_KV_VAL(ki));
1290 ret = CSR1212_ENOMEM;
1293 k->refcnt = 0; /* Don't keep local reference when parsing. */
1297 /* Compute the offset from 0xffff f000 0000. */
1298 offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
1299 if (offset == kv_pos) {
1300 /* Uh-oh. Can't have a relative offset of 0 for Leaves
1301 * or Directories. The Config ROM image is most likely
1302 * messed up, so we'll just abort here. */
1307 k = csr1212_find_keyval_offset(dir, offset);
1310 break; /* Found it. */
1312 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1313 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1315 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1318 ret = CSR1212_ENOMEM;
1321 k->refcnt = 0; /* Don't keep local reference when parsing. */
1322 k->valid = 0; /* Contents not read yet so it's not valid. */
1326 k->next = dir->next;
1327 dir->next->prev = k;
1330 ret = csr1212_attach_keyval_to_directory(dir, k);
1333 if (ret != CSR1212_SUCCESS) {
1341 int csr1212_parse_keyval(struct csr1212_keyval *kv,
1342 struct csr1212_csr_rom_cache *cache)
1344 struct csr1212_keyval_img *kvi;
1346 int ret = CSR1212_SUCCESS;
1349 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1351 kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
1354 /* Apparently there are too many differnt wrong implementations of the
1355 * CRC algorithm that verifying them is moot. */
1356 if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
1357 (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
1358 ret = CSR1212_EINVAL;
1363 switch(kv->key.type) {
1364 case CSR1212_KV_TYPE_DIRECTORY:
1365 for (i = 0; i < kvi_len; i++) {
1366 csr1212_quad_t ki = kvi->data[i];
1368 /* Some devices put null entries in their unit
1369 * directories. If we come across such an entry,
1373 ret = csr1212_parse_dir_entry(kv, ki,
1375 quads_to_bytes(i + 1)));
1377 kv->value.directory.len = kvi_len;
1380 case CSR1212_KV_TYPE_LEAF:
1381 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
1382 kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
1383 if (!kv->value.leaf.data)
1385 ret = CSR1212_ENOMEM;
1389 kv->value.leaf.len = kvi_len;
1390 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1402 int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1404 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1405 struct csr1212_keyval_img *kvi = NULL;
1406 struct csr1212_csr_rom_cache *cache;
1409 u_int32_t *cache_ptr;
1410 u_int16_t kv_len = 0;
1413 return CSR1212_EINVAL;
1415 /* First find which cache the data should be in (or go in if not read
1417 for (cache = csr->cache_head; cache; cache = cache->next) {
1418 if (kv->offset >= cache->offset &&
1419 kv->offset < (cache->offset + cache->size))
1425 u_int32_t cache_size;
1427 /* Only create a new cache for Extended ROM leaves. */
1428 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1429 return CSR1212_EINVAL;
1431 if (csr->ops->bus_read(csr,
1432 CSR1212_REGISTER_SPACE_BASE + kv->offset,
1433 sizeof(csr1212_quad_t), &q, csr->private)) {
1437 kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
1439 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1440 (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1442 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1444 return CSR1212_ENOMEM;
1446 kv->value.leaf.data = &cache->data[1];
1447 csr->cache_tail->next = cache;
1448 cache->prev = csr->cache_tail;
1450 csr->cache_tail = cache;
1451 cache->filled_head =
1452 CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1453 if (!cache->filled_head) {
1454 return CSR1212_ENOMEM;
1457 cache->filled_head->offset_start = 0;
1458 cache->filled_head->offset_end = sizeof(csr1212_quad_t);
1459 cache->filled_tail = cache->filled_head;
1460 cache->filled_head->next = NULL;
1461 cache->filled_head->prev = NULL;
1464 /* Don't read the entire extended ROM now. Pieces of it will
1465 * be read when entries inside it are read. */
1466 return csr1212_parse_keyval(kv, cache);
1469 cache_index = kv->offset - cache->offset;
1471 /* Now seach read portions of the cache to see if it is there. */
1472 for (cr = cache->filled_head; cr; cr = cr->next) {
1473 if (cache_index < cr->offset_start) {
1474 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1476 return CSR1212_ENOMEM;
1478 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1479 newcr->offset_end = newcr->offset_start;
1481 newcr->prev = cr->prev;
1485 } else if ((cache_index >= cr->offset_start) &&
1486 (cache_index < cr->offset_end)) {
1487 kvi = (struct csr1212_keyval_img*)
1488 (&cache->data[bytes_to_quads(cache_index)]);
1489 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1492 } else if (cache_index == cr->offset_end)
1497 cr = cache->filled_tail;
1498 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1500 return CSR1212_ENOMEM;
1502 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1503 newcr->offset_end = newcr->offset_start;
1505 newcr->next = cr->next;
1508 cache->filled_tail = newcr;
1511 while(!kvi || cr->offset_end < cache_index + kv_len) {
1512 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1513 ~(csr->max_rom - 1))];
1515 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1516 cr->offset_end) & ~(csr->max_rom - 1);
1518 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1520 if (csr->max_rom == 4)
1521 /* We've got problems! */
1524 /* Apperently the max_rom value was a lie, set it to
1525 * do quadlet reads and try again. */
1530 cr->offset_end += csr->max_rom - (cr->offset_end &
1531 (csr->max_rom - 1));
1533 if (!kvi && (cr->offset_end > cache_index)) {
1534 kvi = (struct csr1212_keyval_img*)
1535 (&cache->data[bytes_to_quads(cache_index)]);
1536 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1540 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1541 /* The Leaf or Directory claims its length extends
1542 * beyond the ConfigROM image region and thus beyond the
1543 * end of our cache region. Therefore, we abort now
1544 * rather than seg faulting later. */
1550 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1551 /* consolidate region entries */
1552 ncr->offset_start = cr->offset_start;
1555 cr->prev->next = cr->next;
1556 ncr->prev = cr->prev;
1557 if (cache->filled_head == cr)
1558 cache->filled_head = ncr;
1564 return csr1212_parse_keyval(kv, cache);
1569 int csr1212_parse_csr(struct csr1212_csr *csr)
1571 static const int mr_map[] = { 4, 64, 1024, 0 };
1572 struct csr1212_dentry *dentry;
1575 if (!csr || !csr->ops->bus_read)
1576 return CSR1212_EINVAL;
1578 ret = csr1212_parse_bus_info_block(csr);
1579 if (ret != CSR1212_SUCCESS)
1582 if (!csr->ops->get_max_rom)
1583 csr->max_rom = mr_map[0]; /* default value */
1585 csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data,
1588 csr->cache_head->layout_head = csr->root_kv;
1589 csr->cache_head->layout_tail = csr->root_kv;
1591 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1594 csr->root_kv->valid = 0;
1595 csr->root_kv->next = csr->root_kv;
1596 csr->root_kv->prev = csr->root_kv;
1597 csr1212_get_keyval(csr, csr->root_kv);
1599 /* Scan through the Root directory finding all extended ROM regions
1600 * and make cache regions for them */
1601 for (dentry = csr->root_kv->value.directory.dentries_head;
1602 dentry; dentry = dentry->next) {
1603 if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
1604 csr1212_get_keyval(csr, dentry->kv);
1606 if (ret != CSR1212_SUCCESS)
1611 return CSR1212_SUCCESS;