blob: 2fd465ec94ec110419a4ba1f0532ec7bceb15100 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
3 *
4 * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
5 * Steve Kinneberg <kinnebergsteve@acmsystems.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
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.
17 *
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.
28 */
29
30
31/* TODO List:
32 * - Verify interface consistency: i.e., public functions that take a size
33 * parameter expect size to be in bytes.
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 */
35
Stefan Richter7fb9add2007-03-11 22:49:05 +010036#include <linux/errno.h>
37#include <linux/string.h>
Stefan Richter64ff7122007-03-11 22:50:13 +010038#include <asm/bug.h>
Stefan Richter7fb9add2007-03-11 22:49:05 +010039#include <asm/byteorder.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
41#include "csr1212.h"
42
43
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)
Stefan Richter982610b2007-03-11 22:49:34 +010049static const u8 csr1212_key_id_type_map[0x30] = {
Andrea Guzzo0749aaa2006-12-08 00:53:24 +010050 __C, /* used by Apple iSight */
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 __D | __L, /* Descriptor */
52 __I | __D | __L, /* Bus_Dependent_Info */
53 __I | __D | __L, /* Vendor */
54 __I, /* Hardware_Version */
55 0, 0, /* Reserved */
Andrea Guzzo0749aaa2006-12-08 00:53:24 +010056 __D | __L | __I, /* Module */
57 __I, 0, 0, 0, /* used by Apple iSight, Reserved */
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 __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 */
78};
79#undef __I
80#undef __C
81#undef __D
82#undef __L
83
84
Stefan Richter982610b2007-03-11 22:49:34 +010085#define quads_to_bytes(_q) ((_q) * sizeof(u32))
86#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32))
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
Stefan Richter6c88e472007-03-11 22:47:34 +010088static void free_keyval(struct csr1212_keyval *kv)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
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);
93
94 CSR1212_FREE(kv);
95}
96
Stefan Richter982610b2007-03-11 22:49:34 +010097static u16 csr1212_crc16(const u32 *buffer, size_t length)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
99 int shift;
Stefan Richter982610b2007-03-11 22:49:34 +0100100 u32 data;
101 u16 sum, crc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102
103 for (; length; length--) {
Stefan Richter7fb9add2007-03-11 22:49:05 +0100104 data = be32_to_cpu(*buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 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);
109 }
110 crc &= 0xffff;
111 }
112
Stefan Richter7fb9add2007-03-11 22:49:05 +0100113 return cpu_to_be16(crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114}
115
116#if 0
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
119 * software. */
Stefan Richter982610b2007-03-11 22:49:34 +0100120static u16 csr1212_msft_crc16(const u32 *buffer, size_t length)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121{
122 int shift;
Stefan Richter982610b2007-03-11 22:49:34 +0100123 u32 data;
124 u16 sum, crc = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 for (; length; length--) {
Stefan Richter7fb9add2007-03-11 22:49:05 +0100127 data = le32_to_cpu(*buffer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 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);
132 }
133 crc &= 0xffff;
134 }
135
Stefan Richter7fb9add2007-03-11 22:49:05 +0100136 return cpu_to_be16(crc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138#endif
139
Stefan Richter6c88e472007-03-11 22:47:34 +0100140static struct csr1212_dentry *
141csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
143 struct csr1212_dentry *pos;
144
145 for (pos = dir->value.directory.dentries_head;
146 pos != NULL; pos = pos->next) {
147 if (pos->kv == kv)
148 return pos;
149 }
150 return NULL;
151}
152
Stefan Richter6c88e472007-03-11 22:47:34 +0100153static struct csr1212_keyval *
Stefan Richter982610b2007-03-11 22:49:34 +0100154csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u32 offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
156 struct csr1212_keyval *kv;
157
158 for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) {
159 if (kv->offset == offset)
160 return kv;
161 }
162 return NULL;
163}
164
165
166/* Creation Routines */
Stefan Richter6c88e472007-03-11 22:47:34 +0100167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
169 size_t bus_info_size, void *private)
170{
171 struct csr1212_csr *csr;
172
173 csr = CSR1212_MALLOC(sizeof(*csr));
174 if (!csr)
175 return NULL;
176
177 csr->cache_head =
178 csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
179 CSR1212_CONFIG_ROM_SPACE_SIZE);
180 if (!csr->cache_head) {
181 CSR1212_FREE(csr);
182 return NULL;
183 }
184
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);
189 if (!csr->root_kv) {
190 CSR1212_FREE(csr->cache_head);
191 CSR1212_FREE(csr);
192 return NULL;
193 }
194
195 csr->bus_info_data = csr->cache_head->data;
196 csr->bus_info_len = bus_info_size;
197 csr->crc_len = bus_info_size;
198 csr->ops = ops;
199 csr->private = private;
200 csr->cache_tail = csr->cache_head;
201
202 return csr;
203}
204
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205void csr1212_init_local_csr(struct csr1212_csr *csr,
Stefan Richter982610b2007-03-11 22:49:34 +0100206 const u32 *bus_info_data, int max_rom)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207{
208 static const int mr_map[] = { 4, 64, 1024, 0 };
209
Ben Collins1934b8b2005-07-09 20:01:23 -0400210 BUG_ON(max_rom & ~0x3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 csr->max_rom = mr_map[max_rom];
212 memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
213}
214
Stefan Richter982610b2007-03-11 22:49:34 +0100215static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216{
217 struct csr1212_keyval *kv;
218
219 if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
220 return NULL;
221
222 kv = CSR1212_MALLOC(sizeof(*kv));
223 if (!kv)
224 return NULL;
225
226 kv->key.type = type;
227 kv->key.id = key;
228
229 kv->associate = NULL;
230 kv->refcnt = 1;
231
232 kv->next = NULL;
233 kv->prev = NULL;
234 kv->offset = 0;
235 kv->valid = 0;
236 return kv;
237}
238
Stefan Richter982610b2007-03-11 22:49:34 +0100239struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240{
241 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
242
243 if (!kv)
244 return NULL;
245
246 kv->value.immediate = value;
247 kv->valid = 1;
248 return kv;
249}
250
Stefan Richter6c88e472007-03-11 22:47:34 +0100251static struct csr1212_keyval *
Stefan Richter982610b2007-03-11 22:49:34 +0100252csr1212_new_leaf(u8 key, const void *data, size_t data_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253{
254 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
255
256 if (!kv)
257 return NULL;
258
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;
264 }
265
266 if (data)
267 memcpy(kv->value.leaf.data, data, data_len);
268 } else {
269 kv->value.leaf.data = NULL;
270 }
271
272 kv->value.leaf.len = bytes_to_quads(data_len);
273 kv->offset = 0;
274 kv->valid = 1;
275
276 return kv;
277}
278
Stefan Richter6c88e472007-03-11 22:47:34 +0100279static struct csr1212_keyval *
Stefan Richter982610b2007-03-11 22:49:34 +0100280csr1212_new_csr_offset(u8 key, u32 csr_offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
283
284 if (!kv)
285 return NULL;
286
287 kv->value.csr_offset = csr_offset;
288
289 kv->offset = 0;
290 kv->valid = 1;
291 return kv;
292}
293
Stefan Richter982610b2007-03-11 22:49:34 +0100294struct csr1212_keyval *csr1212_new_directory(u8 key)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295{
296 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
297
298 if (!kv)
299 return NULL;
300
301 kv->value.directory.len = 0;
302 kv->offset = 0;
303 kv->value.directory.dentries_head = NULL;
304 kv->value.directory.dentries_tail = NULL;
305 kv->valid = 1;
306 return kv;
307}
308
Stefan Richter64ff7122007-03-11 22:50:13 +0100309void csr1212_associate_keyval(struct csr1212_keyval *kv,
310 struct csr1212_keyval *associate)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311{
Stefan Richter64ff7122007-03-11 22:50:13 +0100312 BUG_ON(!kv || !associate || kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
313 (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
314 associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
315 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
316 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
317 associate->key.id < 0x30) ||
318 (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
319 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) ||
320 (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
321 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) ||
322 (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
323 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) ||
324 (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
325 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
327 if (kv->associate)
328 csr1212_release_keyval(kv->associate);
329
330 associate->refcnt++;
331 kv->associate = associate;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332}
333
334int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
335 struct csr1212_keyval *kv)
336{
337 struct csr1212_dentry *dentry;
338
Stefan Richter64ff7122007-03-11 22:50:13 +0100339 BUG_ON(!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340
341 dentry = CSR1212_MALLOC(sizeof(*dentry));
342 if (!dentry)
Stefan Richter7fb9add2007-03-11 22:49:05 +0100343 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345 dentry->kv = kv;
346
347 kv->refcnt++;
348
349 dentry->next = NULL;
350 dentry->prev = dir->value.directory.dentries_tail;
351
352 if (!dir->value.directory.dentries_head)
353 dir->value.directory.dentries_head = dentry;
354
355 if (dir->value.directory.dentries_tail)
356 dir->value.directory.dentries_tail->next = dentry;
357 dir->value.directory.dentries_tail = dentry;
358
359 return CSR1212_SUCCESS;
360}
361
Stefan Richter6c88e472007-03-11 22:47:34 +0100362#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
363 (&((kv)->value.leaf.data[1]))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
Stefan Richter6c88e472007-03-11 22:47:34 +0100365#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \
366 ((kv)->value.leaf.data[0] = \
Stefan Richter7fb9add2007-03-11 22:49:05 +0100367 cpu_to_be32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \
368 ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)))
Stefan Richter6c88e472007-03-11 22:47:34 +0100369#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \
370 ((kv)->value.leaf.data[0] = \
Stefan Richter7fb9add2007-03-11 22:49:05 +0100371 cpu_to_be32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \
372 CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \
373 ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Stefan Richter6c88e472007-03-11 22:47:34 +0100375static struct csr1212_keyval *
Stefan Richter982610b2007-03-11 22:49:34 +0100376csr1212_new_descriptor_leaf(u8 dtype, u32 specifier_id,
Stefan Richter6c88e472007-03-11 22:47:34 +0100377 const void *data, size_t data_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
379 struct csr1212_keyval *kv;
380
381 kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
382 data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
383 if (!kv)
384 return NULL;
385
386 CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
387 CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
388
389 if (data) {
390 memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
391 }
392
393 return kv;
394}
395
Stefan Richter6c88e472007-03-11 22:47:34 +0100396#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \
397 ((kv)->value.leaf.data[1] = \
398 ((kv)->value.leaf.data[1] & \
Stefan Richter7fb9add2007-03-11 22:49:05 +0100399 cpu_to_be32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \
400 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \
401 cpu_to_be32(((width) & CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \
402 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Stefan Richter6c88e472007-03-11 22:47:34 +0100404#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \
405 ((kv)->value.leaf.data[1] = \
406 ((kv)->value.leaf.data[1] & \
Stefan Richter7fb9add2007-03-11 22:49:05 +0100407 cpu_to_be32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \
408 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \
409 cpu_to_be32(((char_set) & \
410 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \
411 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))
Stefan Richter6c88e472007-03-11 22:47:34 +0100412
413#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \
414 ((kv)->value.leaf.data[1] = \
415 ((kv)->value.leaf.data[1] & \
Stefan Richter7fb9add2007-03-11 22:49:05 +0100416 cpu_to_be32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \
417 cpu_to_be32(((language) & \
418 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)))
Stefan Richter6c88e472007-03-11 22:47:34 +0100419
420static struct csr1212_keyval *
Stefan Richter982610b2007-03-11 22:49:34 +0100421csr1212_new_textual_descriptor_leaf(u8 cwidth, u16 cset, u16 language,
422 const void *data, size_t data_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 struct csr1212_keyval *kv;
425 char *lstr;
426
427 kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
428 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
429 if (!kv)
430 return NULL;
431
432 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth);
433 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset);
434 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
435
436 lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
437
438 /* make sure last quadlet is zeroed out */
Stefan Richter982610b2007-03-11 22:49:34 +0100439 *((u32*)&(lstr[(data_len - 1) & ~0x3])) = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441 /* don't copy the NUL terminator */
442 memcpy(lstr, data, data_len);
443
444 return kv;
445}
446
447static int csr1212_check_minimal_ascii(const char *s)
448{
449 static const char minimal_ascii_table[] = {
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
451 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00,
452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27,
455 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
456 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
457 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
458 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
459 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
460 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
461 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
462 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
463 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
464 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
465 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
466 };
467 for (; *s; s++) {
468 if (minimal_ascii_table[*s & 0x7F] != *s)
469 return -1; /* failed */
470 }
471 /* String conforms to minimal-ascii, as specified by IEEE 1212,
472 * par. 7.4 */
473 return 0;
474}
475
476struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
477{
478 /* Check if string conform to minimal_ascii format */
479 if (csr1212_check_minimal_ascii(s))
480 return NULL;
481
482 /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */
483 return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s));
484}
485
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
487/* Destruction Routines */
488
489void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
490 struct csr1212_keyval *kv)
491{
492 struct csr1212_dentry *dentry;
493
494 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
495 return;
496
497 dentry = csr1212_find_keyval(dir, kv);
498
499 if (!dentry)
500 return;
501
502 if (dentry->prev)
503 dentry->prev->next = dentry->next;
504 if (dentry->next)
505 dentry->next->prev = dentry->prev;
506 if (dir->value.directory.dentries_head == dentry)
507 dir->value.directory.dentries_head = dentry->next;
508 if (dir->value.directory.dentries_tail == dentry)
509 dir->value.directory.dentries_tail = dentry->prev;
510
511 CSR1212_FREE(dentry);
512
513 csr1212_release_keyval(kv);
514}
515
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516/* This function is used to free the memory taken by a keyval. If the given
517 * keyval is a directory type, then any keyvals contained in that directory
518 * will be destroyed as well if their respective refcnts are 0. By means of
519 * list manipulation, this routine will descend a directory structure in a
520 * non-recursive manner. */
Stefan Richterc1a37f22007-03-14 00:20:53 +0100521static void csr1212_destroy_keyval(struct csr1212_keyval *kv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522{
523 struct csr1212_keyval *k, *a;
524 struct csr1212_dentry dentry;
525 struct csr1212_dentry *head, *tail;
526
527 dentry.kv = kv;
528 dentry.next = NULL;
529 dentry.prev = NULL;
530
531 head = &dentry;
532 tail = head;
533
534 while (head) {
535 k = head->kv;
536
537 while (k) {
538 k->refcnt--;
539
540 if (k->refcnt > 0)
541 break;
542
543 a = k->associate;
544
545 if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
546 /* If the current entry is a directory, then move all
547 * the entries to the destruction list. */
548 if (k->value.directory.dentries_head) {
549 tail->next = k->value.directory.dentries_head;
550 k->value.directory.dentries_head->prev = tail;
551 tail = k->value.directory.dentries_tail;
552 }
553 }
554 free_keyval(k);
555 k = a;
556 }
557
558 head = head->next;
559 if (head) {
560 if (head->prev && head->prev != &dentry) {
561 CSR1212_FREE(head->prev);
562 }
563 head->prev = NULL;
564 } else if (tail != &dentry)
565 CSR1212_FREE(tail);
566 }
567}
568
Stefan Richterc1a37f22007-03-14 00:20:53 +0100569void csr1212_release_keyval(struct csr1212_keyval *kv)
570{
571 if (kv->refcnt > 1)
572 kv->refcnt--;
573 else
574 csr1212_destroy_keyval(kv);
575}
576
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577void csr1212_destroy_csr(struct csr1212_csr *csr)
578{
579 struct csr1212_csr_rom_cache *c, *oc;
580 struct csr1212_cache_region *cr, *ocr;
581
582 csr1212_release_keyval(csr->root_kv);
583
584 c = csr->cache_head;
585 while (c) {
586 oc = c;
587 cr = c->filled_head;
588 while (cr) {
589 ocr = cr;
590 cr = cr->next;
591 CSR1212_FREE(ocr);
592 }
593 c = c->next;
594 CSR1212_FREE(oc);
595 }
596
597 CSR1212_FREE(csr);
598}
599
600
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601/* CSR Image Creation */
602
603static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
604{
605 struct csr1212_csr_rom_cache *cache;
Stefan Richter982610b2007-03-11 22:49:34 +0100606 u64 csr_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Stefan Richter64ff7122007-03-11 22:50:13 +0100608 BUG_ON(!csr || !csr->ops || !csr->ops->allocate_addr_range ||
609 !csr->ops->release_addr || csr->max_rom < 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
611 /* ROM size must be a multiple of csr->max_rom */
612 romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
613
614 csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
Ben Collins67372312006-06-12 18:15:31 -0400615 if (csr_addr == CSR1212_INVALID_ADDR_SPACE) {
Stefan Richter7fb9add2007-03-11 22:49:05 +0100616 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 }
618 if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
619 /* Invalid address returned from allocate_addr_range(). */
620 csr->ops->release_addr(csr_addr, csr->private);
Stefan Richter7fb9add2007-03-11 22:49:05 +0100621 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 }
623
624 cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
625 if (!cache) {
626 csr->ops->release_addr(csr_addr, csr->private);
Stefan Richter7fb9add2007-03-11 22:49:05 +0100627 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 }
629
630 cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);
631 if (!cache->ext_rom) {
632 csr->ops->release_addr(csr_addr, csr->private);
633 CSR1212_FREE(cache);
Stefan Richter7fb9add2007-03-11 22:49:05 +0100634 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 }
636
637 if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) {
638 csr1212_release_keyval(cache->ext_rom);
639 csr->ops->release_addr(csr_addr, csr->private);
640 CSR1212_FREE(cache);
Stefan Richter7fb9add2007-03-11 22:49:05 +0100641 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 }
643 cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
644 cache->ext_rom->value.leaf.len = -1;
645 cache->ext_rom->value.leaf.data = cache->data;
646
647 /* Add cache to tail of cache list */
648 cache->prev = csr->cache_tail;
649 csr->cache_tail->next = cache;
650 csr->cache_tail = cache;
651 return CSR1212_SUCCESS;
652}
653
Stefan Richter6c88e472007-03-11 22:47:34 +0100654static void csr1212_remove_cache(struct csr1212_csr *csr,
655 struct csr1212_csr_rom_cache *cache)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656{
657 if (csr->cache_head == cache)
658 csr->cache_head = cache->next;
659 if (csr->cache_tail == cache)
660 csr->cache_tail = cache->prev;
661
662 if (cache->prev)
663 cache->prev->next = cache->next;
664 if (cache->next)
665 cache->next->prev = cache->prev;
666
667 if (cache->ext_rom) {
668 csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
669 csr1212_release_keyval(cache->ext_rom);
670 }
671
672 CSR1212_FREE(cache);
673}
674
675static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
676 struct csr1212_keyval **layout_tail)
677{
678 struct csr1212_dentry *dentry;
679 struct csr1212_keyval *dkv;
680 struct csr1212_keyval *last_extkey_spec = NULL;
681 struct csr1212_keyval *last_extkey = NULL;
682 int num_entries = 0;
683
684 for (dentry = dir->value.directory.dentries_head; dentry;
685 dentry = dentry->next) {
686 for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
687 /* Special Case: Extended Key Specifier_ID */
688 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
689 if (last_extkey_spec == NULL) {
690 last_extkey_spec = dkv;
691 } else if (dkv->value.immediate != last_extkey_spec->value.immediate) {
692 last_extkey_spec = dkv;
693 } else {
694 continue;
695 }
696 /* Special Case: Extended Key */
697 } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
698 if (last_extkey == NULL) {
699 last_extkey = dkv;
700 } else if (dkv->value.immediate != last_extkey->value.immediate) {
701 last_extkey = dkv;
702 } else {
703 continue;
704 }
705 }
706
707 num_entries += 1;
708
709 switch(dkv->key.type) {
710 default:
711 case CSR1212_KV_TYPE_IMMEDIATE:
712 case CSR1212_KV_TYPE_CSR_OFFSET:
713 break;
714 case CSR1212_KV_TYPE_LEAF:
715 case CSR1212_KV_TYPE_DIRECTORY:
716 /* Remove from list */
717 if (dkv->prev && (dkv->prev->next == dkv))
718 dkv->prev->next = dkv->next;
719 if (dkv->next && (dkv->next->prev == dkv))
720 dkv->next->prev = dkv->prev;
721 //if (dkv == *layout_tail)
722 // *layout_tail = dkv->prev;
723
724 /* Special case: Extended ROM leafs */
725 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
726 dkv->value.leaf.len = -1;
727 /* Don't add Extended ROM leafs in the layout list,
728 * they are handled differently. */
729 break;
730 }
731
732 /* Add to tail of list */
733 dkv->next = NULL;
734 dkv->prev = *layout_tail;
735 (*layout_tail)->next = dkv;
736 *layout_tail = dkv;
737 break;
738 }
739 }
740 }
741 return num_entries;
742}
743
Stefan Richter6c88e472007-03-11 22:47:34 +0100744static size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745{
746 struct csr1212_keyval *ltail = kv;
747 size_t agg_size = 0;
748
749 while(kv) {
750 switch(kv->key.type) {
751 case CSR1212_KV_TYPE_LEAF:
752 /* Add 1 quadlet for crc/len field */
753 agg_size += kv->value.leaf.len + 1;
754 break;
755
756 case CSR1212_KV_TYPE_DIRECTORY:
757 kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);
758 /* Add 1 quadlet for crc/len field */
759 agg_size += kv->value.directory.len + 1;
760 break;
761 }
762 kv = kv->next;
763 }
764 return quads_to_bytes(agg_size);
765}
766
Stefan Richter6c88e472007-03-11 22:47:34 +0100767static struct csr1212_keyval *
768csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
769 struct csr1212_keyval *start_kv, int start_pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
771 struct csr1212_keyval *kv = start_kv;
772 struct csr1212_keyval *okv = start_kv;
773 int pos = start_pos;
774 int kv_len = 0, okv_len = 0;
775
776 cache->layout_head = kv;
777
778 while(kv && pos < cache->size) {
779 /* Special case: Extended ROM leafs */
780 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
781 kv->offset = cache->offset + pos;
782 }
783
784 switch(kv->key.type) {
785 case CSR1212_KV_TYPE_LEAF:
786 kv_len = kv->value.leaf.len;
787 break;
788
789 case CSR1212_KV_TYPE_DIRECTORY:
790 kv_len = kv->value.directory.len;
791 break;
792
793 default:
794 /* Should never get here */
795 break;
796 }
797
798 pos += quads_to_bytes(kv_len + 1);
799
800 if (pos <= cache->size) {
801 okv = kv;
802 okv_len = kv_len;
803 kv = kv->next;
804 }
805 }
806
807 cache->layout_tail = okv;
808 cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
809
810 return kv;
811}
812
Stefan Richter6c88e472007-03-11 22:47:34 +0100813#define CSR1212_KV_KEY_SHIFT 24
814#define CSR1212_KV_KEY_TYPE_SHIFT 6
815#define CSR1212_KV_KEY_ID_MASK 0x3f
816#define CSR1212_KV_KEY_TYPE_MASK 0x3 /* after shift */
817
818static void
Stefan Richter982610b2007-03-11 22:49:34 +0100819csr1212_generate_tree_subdir(struct csr1212_keyval *dir, u32 *data_buffer)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
821 struct csr1212_dentry *dentry;
822 struct csr1212_keyval *last_extkey_spec = NULL;
823 struct csr1212_keyval *last_extkey = NULL;
824 int index = 0;
825
826 for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
827 struct csr1212_keyval *a;
828
829 for (a = dentry->kv; a; a = a->associate) {
Stefan Richter982610b2007-03-11 22:49:34 +0100830 u32 value = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
832 /* Special Case: Extended Key Specifier_ID */
833 if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
834 if (last_extkey_spec == NULL) {
835 last_extkey_spec = a;
836 } else if (a->value.immediate != last_extkey_spec->value.immediate) {
837 last_extkey_spec = a;
838 } else {
839 continue;
840 }
841 /* Special Case: Extended Key */
842 } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
843 if (last_extkey == NULL) {
844 last_extkey = a;
845 } else if (a->value.immediate != last_extkey->value.immediate) {
846 last_extkey = a;
847 } else {
848 continue;
849 }
850 }
851
852 switch(a->key.type) {
853 case CSR1212_KV_TYPE_IMMEDIATE:
854 value = a->value.immediate;
855 break;
856 case CSR1212_KV_TYPE_CSR_OFFSET:
857 value = a->value.csr_offset;
858 break;
859 case CSR1212_KV_TYPE_LEAF:
860 value = a->offset;
861 value -= dir->offset + quads_to_bytes(1+index);
862 value = bytes_to_quads(value);
863 break;
864 case CSR1212_KV_TYPE_DIRECTORY:
865 value = a->offset;
866 value -= dir->offset + quads_to_bytes(1+index);
867 value = bytes_to_quads(value);
868 break;
869 default:
870 /* Should never get here */
871 break; /* GDB breakpoint */
872 }
873
874 value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;
875 value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
876 (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);
Stefan Richter7fb9add2007-03-11 22:49:05 +0100877 data_buffer[index] = cpu_to_be32(value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 index++;
879 }
880 }
881}
882
Stefan Richter6c88e472007-03-11 22:47:34 +0100883struct csr1212_keyval_img {
Stefan Richter982610b2007-03-11 22:49:34 +0100884 u16 length;
885 u16 crc;
Stefan Richter6c88e472007-03-11 22:47:34 +0100886
887 /* Must be last */
Stefan Richter982610b2007-03-11 22:49:34 +0100888 u32 data[0]; /* older gcc can't handle [] which is standard */
Stefan Richter6c88e472007-03-11 22:47:34 +0100889};
890
891static void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892{
893 struct csr1212_keyval *kv, *nkv;
894 struct csr1212_keyval_img *kvi;
895
896 for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {
897 kvi = (struct csr1212_keyval_img *)
898 (cache->data + bytes_to_quads(kv->offset - cache->offset));
899 switch(kv->key.type) {
900 default:
901 case CSR1212_KV_TYPE_IMMEDIATE:
902 case CSR1212_KV_TYPE_CSR_OFFSET:
903 /* Should never get here */
904 break; /* GDB breakpoint */
905
906 case CSR1212_KV_TYPE_LEAF:
907 /* Don't copy over Extended ROM areas, they are
908 * already filled out! */
909 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
910 memcpy(kvi->data, kv->value.leaf.data,
911 quads_to_bytes(kv->value.leaf.len));
912
Stefan Richter7fb9add2007-03-11 22:49:05 +0100913 kvi->length = cpu_to_be16(kv->value.leaf.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
915 break;
916
917 case CSR1212_KV_TYPE_DIRECTORY:
918 csr1212_generate_tree_subdir(kv, kvi->data);
919
Stefan Richter7fb9add2007-03-11 22:49:05 +0100920 kvi->length = cpu_to_be16(kv->value.directory.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
922 break;
923 }
924
925 nkv = kv->next;
926 if (kv->prev)
927 kv->prev->next = NULL;
928 if (kv->next)
929 kv->next->prev = NULL;
930 kv->prev = NULL;
931 kv->next = NULL;
932 }
933}
934
Stefan Richterfd2f3bd2007-03-11 22:51:24 +0100935/* This size is arbitrarily chosen.
936 * The struct overhead is subtracted for more economic allocations. */
937#define CSR1212_EXTENDED_ROM_SIZE (2048 - sizeof(struct csr1212_csr_rom_cache))
Stefan Richter6c88e472007-03-11 22:47:34 +0100938
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939int csr1212_generate_csr_image(struct csr1212_csr *csr)
940{
941 struct csr1212_bus_info_block_img *bi;
942 struct csr1212_csr_rom_cache *cache;
943 struct csr1212_keyval *kv;
944 size_t agg_size;
945 int ret;
946 int init_offset;
947
Stefan Richter64ff7122007-03-11 22:50:13 +0100948 BUG_ON(!csr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
950 cache = csr->cache_head;
951
952 bi = (struct csr1212_bus_info_block_img*)cache->data;
953
954 bi->length = bytes_to_quads(csr->bus_info_len) - 1;
955 bi->crc_length = bi->length;
956 bi->crc = csr1212_crc16(bi->data, bi->crc_length);
957
958 csr->root_kv->next = NULL;
959 csr->root_kv->prev = NULL;
960
961 agg_size = csr1212_generate_layout_order(csr->root_kv);
962
963 init_offset = csr->bus_info_len;
964
965 for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
966 if (!cache) {
967 /* Estimate approximate number of additional cache
968 * regions needed (it assumes that the cache holding
969 * the first 1K Config ROM space always exists). */
970 int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
Stefan Richter982610b2007-03-11 22:49:34 +0100971 (2 * sizeof(u32))) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 /* Add additional cache regions, extras will be
974 * removed later */
975 for (; est_c; est_c--) {
976 ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
977 if (ret != CSR1212_SUCCESS)
978 return ret;
979 }
980 /* Need to re-layout for additional cache regions */
981 agg_size = csr1212_generate_layout_order(csr->root_kv);
982 kv = csr->root_kv;
983 cache = csr->cache_head;
984 init_offset = csr->bus_info_len;
985 }
986 kv = csr1212_generate_positions(cache, kv, init_offset);
987 agg_size -= cache->len;
Stefan Richter982610b2007-03-11 22:49:34 +0100988 init_offset = sizeof(u32);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990
991 /* Remove unused, excess cache regions */
992 while (cache) {
993 struct csr1212_csr_rom_cache *oc = cache;
994
995 cache = cache->next;
996 csr1212_remove_cache(csr, oc);
997 }
998
999 /* Go through the list backward so that when done, the correct CRC
1000 * will be calculated for the Extended ROM areas. */
1001 for(cache = csr->cache_tail; cache; cache = cache->prev) {
1002 /* Only Extended ROM caches should have this set. */
1003 if (cache->ext_rom) {
1004 int leaf_size;
1005
1006 /* Make sure the Extended ROM leaf is a multiple of
1007 * max_rom in size. */
Stefan Richter64ff7122007-03-11 22:50:13 +01001008 BUG_ON(csr->max_rom < 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 leaf_size = (cache->len + (csr->max_rom - 1)) &
1010 ~(csr->max_rom - 1);
1011
1012 /* Zero out the unused ROM region */
1013 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1014 leaf_size - cache->len);
1015
1016 /* Subtract leaf header */
Stefan Richter982610b2007-03-11 22:49:34 +01001017 leaf_size -= sizeof(u32);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018
1019 /* Update the Extended ROM leaf length */
1020 cache->ext_rom->value.leaf.len =
1021 bytes_to_quads(leaf_size);
1022 } else {
1023 /* Zero out the unused ROM region */
1024 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1025 cache->size - cache->len);
1026 }
1027
1028 /* Copy the data into the cache buffer */
1029 csr1212_fill_cache(cache);
1030
1031 if (cache != csr->cache_head) {
1032 /* Set the length and CRC of the extended ROM. */
1033 struct csr1212_keyval_img *kvi =
1034 (struct csr1212_keyval_img*)cache->data;
Stefan Richter982610b2007-03-11 22:49:34 +01001035 u16 len = bytes_to_quads(cache->len) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
Stefan Richter7fb9add2007-03-11 22:49:05 +01001037 kvi->length = cpu_to_be16(len);
1038 kvi->crc = csr1212_crc16(kvi->data, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 }
1041
1042 return CSR1212_SUCCESS;
1043}
1044
Stefan Richter982610b2007-03-11 22:49:34 +01001045int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer, u32 len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046{
1047 struct csr1212_csr_rom_cache *cache;
1048
1049 for (cache = csr->cache_head; cache; cache = cache->next) {
1050 if (offset >= cache->offset &&
1051 (offset + len) <= (cache->offset + cache->size)) {
1052 memcpy(buffer,
1053 &cache->data[bytes_to_quads(offset - cache->offset)],
1054 len);
1055 return CSR1212_SUCCESS;
1056 }
1057 }
Stefan Richter7fb9add2007-03-11 22:49:05 +01001058 return -ENOENT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059}
1060
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062/* Parse a chunk of data as a Config ROM */
1063
1064static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
1065{
1066 struct csr1212_bus_info_block_img *bi;
1067 struct csr1212_cache_region *cr;
1068 int i;
1069 int ret;
1070
1071 /* IEEE 1212 says that the entire bus info block should be readable in
1072 * a single transaction regardless of the max_rom value.
1073 * Unfortunately, many IEEE 1394 devices do not abide by that, so the
1074 * bus info block will be read 1 quadlet at a time. The rest of the
1075 * ConfigROM will be read according to the max_rom field. */
Stefan Richter982610b2007-03-11 22:49:34 +01001076 for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
Stefan Richter982610b2007-03-11 22:49:34 +01001078 sizeof(u32),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 &csr->cache_head->data[bytes_to_quads(i)],
1080 csr->private);
1081 if (ret != CSR1212_SUCCESS)
1082 return ret;
Stefan Richterb2051f82007-01-03 19:32:13 +01001083
1084 /* check ROM header's info_length */
1085 if (i == 0 &&
Stefan Richter7fb9add2007-03-11 22:49:05 +01001086 be32_to_cpu(csr->cache_head->data[0]) >> 24 !=
Stefan Richterb2051f82007-01-03 19:32:13 +01001087 bytes_to_quads(csr->bus_info_len) - 1)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001088 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 }
1090
1091 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1092 csr->crc_len = quads_to_bytes(bi->crc_length);
1093
1094 /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
1095 * always the case, so read the rest of the crc area 1 quadlet at a time. */
Stefan Richter982610b2007-03-11 22:49:34 +01001096 for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
Stefan Richter982610b2007-03-11 22:49:34 +01001098 sizeof(u32),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 &csr->cache_head->data[bytes_to_quads(i)],
1100 csr->private);
1101 if (ret != CSR1212_SUCCESS)
1102 return ret;
1103 }
1104
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105#if 0
1106 /* Apparently there are too many differnt wrong implementations of the
1107 * CRC algorithm that verifying them is moot. */
1108 if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
1109 (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
Stefan Richter7fb9add2007-03-11 22:49:05 +01001110 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111#endif
1112
Stefan Richter85511582005-11-07 06:31:45 -05001113 cr = CSR1212_MALLOC(sizeof(*cr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 if (!cr)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001115 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116
1117 cr->next = NULL;
1118 cr->prev = NULL;
1119 cr->offset_start = 0;
1120 cr->offset_end = csr->crc_len + 4;
1121
1122 csr->cache_head->filled_head = cr;
1123 csr->cache_head->filled_tail = cr;
1124
1125 return CSR1212_SUCCESS;
1126}
1127
Stefan Richter7fb9add2007-03-11 22:49:05 +01001128#define CSR1212_KV_KEY(q) (be32_to_cpu(q) >> CSR1212_KV_KEY_SHIFT)
Stefan Richter6c88e472007-03-11 22:47:34 +01001129#define CSR1212_KV_KEY_TYPE(q) (CSR1212_KV_KEY(q) >> CSR1212_KV_KEY_TYPE_SHIFT)
1130#define CSR1212_KV_KEY_ID(q) (CSR1212_KV_KEY(q) & CSR1212_KV_KEY_ID_MASK)
1131#define CSR1212_KV_VAL_MASK 0xffffff
Stefan Richter7fb9add2007-03-11 22:49:05 +01001132#define CSR1212_KV_VAL(q) (be32_to_cpu(q) & CSR1212_KV_VAL_MASK)
Stefan Richter6c88e472007-03-11 22:47:34 +01001133
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
Stefan Richter982610b2007-03-11 22:49:34 +01001135 u32 ki, u32 kv_pos)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
1137 int ret = CSR1212_SUCCESS;
1138 struct csr1212_keyval *k = NULL;
Stefan Richter982610b2007-03-11 22:49:34 +01001139 u32 offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140
1141 switch(CSR1212_KV_KEY_TYPE(ki)) {
1142 case CSR1212_KV_TYPE_IMMEDIATE:
1143 k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
1144 CSR1212_KV_VAL(ki));
1145 if (!k) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001146 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 goto fail;
1148 }
1149
1150 k->refcnt = 0; /* Don't keep local reference when parsing. */
1151 break;
1152
1153 case CSR1212_KV_TYPE_CSR_OFFSET:
1154 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1155 CSR1212_KV_VAL(ki));
1156 if (!k) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001157 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 goto fail;
1159 }
1160 k->refcnt = 0; /* Don't keep local reference when parsing. */
1161 break;
1162
1163 default:
1164 /* Compute the offset from 0xffff f000 0000. */
1165 offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
1166 if (offset == kv_pos) {
1167 /* Uh-oh. Can't have a relative offset of 0 for Leaves
1168 * or Directories. The Config ROM image is most likely
1169 * messed up, so we'll just abort here. */
Stefan Richter7fb9add2007-03-11 22:49:05 +01001170 ret = -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 goto fail;
1172 }
1173
1174 k = csr1212_find_keyval_offset(dir, offset);
1175
1176 if (k)
1177 break; /* Found it. */
1178
1179 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1180 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1181 } else {
1182 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1183 }
1184 if (!k) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001185 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 goto fail;
1187 }
1188 k->refcnt = 0; /* Don't keep local reference when parsing. */
1189 k->valid = 0; /* Contents not read yet so it's not valid. */
1190 k->offset = offset;
1191
1192 k->prev = dir;
1193 k->next = dir->next;
1194 dir->next->prev = k;
1195 dir->next = k;
1196 }
1197 ret = csr1212_attach_keyval_to_directory(dir, k);
1198
1199fail:
Stefan Richter6c88e472007-03-11 22:47:34 +01001200 if (ret != CSR1212_SUCCESS && k != NULL)
1201 free_keyval(k);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 return ret;
1203}
1204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205int csr1212_parse_keyval(struct csr1212_keyval *kv,
1206 struct csr1212_csr_rom_cache *cache)
1207{
1208 struct csr1212_keyval_img *kvi;
1209 int i;
1210 int ret = CSR1212_SUCCESS;
1211 int kvi_len;
1212
1213 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1214 cache->offset)];
Stefan Richter7fb9add2007-03-11 22:49:05 +01001215 kvi_len = be16_to_cpu(kvi->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
1217#if 0
1218 /* Apparently there are too many differnt wrong implementations of the
1219 * CRC algorithm that verifying them is moot. */
1220 if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
1221 (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001222 ret = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 goto fail;
1224 }
1225#endif
1226
1227 switch(kv->key.type) {
1228 case CSR1212_KV_TYPE_DIRECTORY:
1229 for (i = 0; i < kvi_len; i++) {
Stefan Richter982610b2007-03-11 22:49:34 +01001230 u32 ki = kvi->data[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
1232 /* Some devices put null entries in their unit
1233 * directories. If we come across such an entry,
1234 * then skip it. */
1235 if (ki == 0x0)
1236 continue;
1237 ret = csr1212_parse_dir_entry(kv, ki,
1238 (kv->offset +
1239 quads_to_bytes(i + 1)));
1240 }
1241 kv->value.directory.len = kvi_len;
1242 break;
1243
1244 case CSR1212_KV_TYPE_LEAF:
1245 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
1246 kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
Stefan Richter85511582005-11-07 06:31:45 -05001247 if (!kv->value.leaf.data) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001248 ret = -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 goto fail;
1250 }
1251
1252 kv->value.leaf.len = kvi_len;
1253 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1254 }
1255 break;
1256 }
1257
1258 kv->valid = 1;
1259
1260fail:
1261 return ret;
1262}
1263
Stefan Richterc1a37f22007-03-14 00:20:53 +01001264static int
1265csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266{
1267 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1268 struct csr1212_keyval_img *kvi = NULL;
1269 struct csr1212_csr_rom_cache *cache;
1270 int cache_index;
Stefan Richter982610b2007-03-11 22:49:34 +01001271 u64 addr;
1272 u32 *cache_ptr;
1273 u16 kv_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Stefan Richter64ff7122007-03-11 22:50:13 +01001275 BUG_ON(!csr || !kv || csr->max_rom < 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276
1277 /* First find which cache the data should be in (or go in if not read
1278 * yet). */
1279 for (cache = csr->cache_head; cache; cache = cache->next) {
1280 if (kv->offset >= cache->offset &&
1281 kv->offset < (cache->offset + cache->size))
1282 break;
1283 }
1284
1285 if (!cache) {
Stefan Richter982610b2007-03-11 22:49:34 +01001286 u32 q, cache_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
1288 /* Only create a new cache for Extended ROM leaves. */
1289 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001290 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
1292 if (csr->ops->bus_read(csr,
1293 CSR1212_REGISTER_SPACE_BASE + kv->offset,
Stefan Richter982610b2007-03-11 22:49:34 +01001294 sizeof(u32), &q, csr->private)) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001295 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 }
1297
Stefan Richter7fb9add2007-03-11 22:49:05 +01001298 kv->value.leaf.len = be32_to_cpu(q) >> 16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
1300 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1301 (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1302
1303 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1304 if (!cache)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001305 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 kv->value.leaf.data = &cache->data[1];
1308 csr->cache_tail->next = cache;
1309 cache->prev = csr->cache_tail;
1310 cache->next = NULL;
1311 csr->cache_tail = cache;
1312 cache->filled_head =
Stefan Richter85511582005-11-07 06:31:45 -05001313 CSR1212_MALLOC(sizeof(*cache->filled_head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 if (!cache->filled_head) {
Stefan Richter7fb9add2007-03-11 22:49:05 +01001315 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 }
1317
1318 cache->filled_head->offset_start = 0;
Stefan Richter982610b2007-03-11 22:49:34 +01001319 cache->filled_head->offset_end = sizeof(u32);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 cache->filled_tail = cache->filled_head;
1321 cache->filled_head->next = NULL;
1322 cache->filled_head->prev = NULL;
1323 cache->data[0] = q;
1324
1325 /* Don't read the entire extended ROM now. Pieces of it will
1326 * be read when entries inside it are read. */
1327 return csr1212_parse_keyval(kv, cache);
1328 }
1329
1330 cache_index = kv->offset - cache->offset;
1331
1332 /* Now seach read portions of the cache to see if it is there. */
1333 for (cr = cache->filled_head; cr; cr = cr->next) {
1334 if (cache_index < cr->offset_start) {
Stefan Richter85511582005-11-07 06:31:45 -05001335 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (!newcr)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001337 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
1339 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1340 newcr->offset_end = newcr->offset_start;
1341 newcr->next = cr;
1342 newcr->prev = cr->prev;
1343 cr->prev = newcr;
1344 cr = newcr;
1345 break;
1346 } else if ((cache_index >= cr->offset_start) &&
1347 (cache_index < cr->offset_end)) {
1348 kvi = (struct csr1212_keyval_img*)
1349 (&cache->data[bytes_to_quads(cache_index)]);
Stefan Richter7fb9add2007-03-11 22:49:05 +01001350 kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 break;
1352 } else if (cache_index == cr->offset_end)
1353 break;
1354 }
1355
1356 if (!cr) {
1357 cr = cache->filled_tail;
Stefan Richter85511582005-11-07 06:31:45 -05001358 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 if (!newcr)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001360 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
1362 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1363 newcr->offset_end = newcr->offset_start;
1364 newcr->prev = cr;
1365 newcr->next = cr->next;
1366 cr->next = newcr;
1367 cr = newcr;
1368 cache->filled_tail = newcr;
1369 }
1370
1371 while(!kvi || cr->offset_end < cache_index + kv_len) {
1372 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1373 ~(csr->max_rom - 1))];
1374
1375 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1376 cr->offset_end) & ~(csr->max_rom - 1);
1377
1378 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1379 csr->private)) {
1380 if (csr->max_rom == 4)
1381 /* We've got problems! */
Stefan Richter7fb9add2007-03-11 22:49:05 +01001382 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
1384 /* Apperently the max_rom value was a lie, set it to
1385 * do quadlet reads and try again. */
1386 csr->max_rom = 4;
1387 continue;
1388 }
1389
1390 cr->offset_end += csr->max_rom - (cr->offset_end &
1391 (csr->max_rom - 1));
1392
1393 if (!kvi && (cr->offset_end > cache_index)) {
1394 kvi = (struct csr1212_keyval_img*)
1395 (&cache->data[bytes_to_quads(cache_index)]);
Stefan Richter7fb9add2007-03-11 22:49:05 +01001396 kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 }
1398
1399 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1400 /* The Leaf or Directory claims its length extends
1401 * beyond the ConfigROM image region and thus beyond the
1402 * end of our cache region. Therefore, we abort now
1403 * rather than seg faulting later. */
Stefan Richter7fb9add2007-03-11 22:49:05 +01001404 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 }
1406
1407 ncr = cr->next;
1408
1409 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1410 /* consolidate region entries */
1411 ncr->offset_start = cr->offset_start;
1412
1413 if (cr->prev)
1414 cr->prev->next = cr->next;
1415 ncr->prev = cr->prev;
1416 if (cache->filled_head == cr)
1417 cache->filled_head = ncr;
1418 CSR1212_FREE(cr);
1419 cr = ncr;
1420 }
1421 }
1422
1423 return csr1212_parse_keyval(kv, cache);
1424}
1425
Stefan Richterc1a37f22007-03-14 00:20:53 +01001426struct csr1212_keyval *
1427csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1428{
1429 if (!kv)
1430 return NULL;
1431 if (!kv->valid)
1432 if (csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS)
1433 return NULL;
1434 return kv;
1435}
1436
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437int csr1212_parse_csr(struct csr1212_csr *csr)
1438{
1439 static const int mr_map[] = { 4, 64, 1024, 0 };
1440 struct csr1212_dentry *dentry;
1441 int ret;
1442
Stefan Richter64ff7122007-03-11 22:50:13 +01001443 BUG_ON(!csr || !csr->ops || !csr->ops->bus_read);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 ret = csr1212_parse_bus_info_block(csr);
1446 if (ret != CSR1212_SUCCESS)
1447 return ret;
1448
1449 if (!csr->ops->get_max_rom)
1450 csr->max_rom = mr_map[0]; /* default value */
Ben Collins1934b8b2005-07-09 20:01:23 -04001451 else {
1452 int i = csr->ops->get_max_rom(csr->bus_info_data,
1453 csr->private);
1454 if (i & ~0x3)
Stefan Richter7fb9add2007-03-11 22:49:05 +01001455 return -EINVAL;
Ben Collins1934b8b2005-07-09 20:01:23 -04001456 csr->max_rom = mr_map[i];
1457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459 csr->cache_head->layout_head = csr->root_kv;
1460 csr->cache_head->layout_tail = csr->root_kv;
1461
1462 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1463 csr->bus_info_len;
1464
1465 csr->root_kv->valid = 0;
1466 csr->root_kv->next = csr->root_kv;
1467 csr->root_kv->prev = csr->root_kv;
Stefan Richterc1a37f22007-03-14 00:20:53 +01001468 ret = csr1212_read_keyval(csr, csr->root_kv);
Jody McIntyre5303a982005-11-22 12:17:11 -05001469 if (ret != CSR1212_SUCCESS)
1470 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 /* Scan through the Root directory finding all extended ROM regions
1473 * and make cache regions for them */
1474 for (dentry = csr->root_kv->value.directory.dentries_head;
1475 dentry; dentry = dentry->next) {
Jody McIntyrea96074e2005-11-22 12:17:14 -05001476 if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
1477 !dentry->kv->valid) {
Stefan Richterc1a37f22007-03-14 00:20:53 +01001478 ret = csr1212_read_keyval(csr, dentry->kv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 if (ret != CSR1212_SUCCESS)
1480 return ret;
1481 }
1482 }
1483
1484 return CSR1212_SUCCESS;
1485}