aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ieee1394/csr1212.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ieee1394/csr1212.c')
-rw-r--r--drivers/ieee1394/csr1212.c1612
1 files changed, 1612 insertions, 0 deletions
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
new file mode 100644
index 000000000000..7c4330e2e875
--- /dev/null
+++ b/drivers/ieee1394/csr1212.c
@@ -0,0 +1,1612 @@
1/*
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.
34 * - Convenience functions for reading a block of data from a given offset.
35 */
36
37#ifndef __KERNEL__
38#include <string.h>
39#endif
40
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)
49static const u_int8_t csr1212_key_id_type_map[0x30] = {
50 0, /* Reserved */
51 __D | __L, /* Descriptor */
52 __I | __D | __L, /* Bus_Dependent_Info */
53 __I | __D | __L, /* Vendor */
54 __I, /* Hardware_Version */
55 0, 0, /* Reserved */
56 __D | __L, /* Module */
57 0, 0, 0, 0, /* Reserved */
58 __I, /* Node_Capabilities */
59 __L, /* EUI_64 */
60 0, 0, 0, /* Reserved */
61 __D, /* Unit */
62 __I, /* Specifier_ID */
63 __I, /* Version */
64 __I | __C | __D | __L, /* Dependent_Info */
65 __L, /* Unit_Location */
66 0, /* Reserved */
67 __I, /* Model */
68 __D, /* Instance */
69 __L, /* Keyword */
70 __D, /* Feature */
71 __L, /* Extended_ROM */
72 __I, /* Extended_Key_Specifier_ID */
73 __I, /* Extended_Key */
74 __I | __C | __D | __L, /* Extended_Data */
75 __L, /* Modifiable_Descriptor */
76 __I, /* Directory_ID */
77 __I, /* Revision */
78};
79#undef __I
80#undef __C
81#undef __D
82#undef __L
83
84
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))
87
88static inline void free_keyval(struct csr1212_keyval *kv)
89{
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
97static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length)
98{
99 int shift;
100 u_int32_t data;
101 u_int16_t sum, crc = 0;
102
103 for (; length; length--) {
104 data = CSR1212_BE32_TO_CPU(*buffer);
105 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
113 return CSR1212_CPU_TO_BE16(crc);
114}
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. */
120static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length)
121{
122 int shift;
123 u_int32_t data;
124 u_int16_t sum, crc = 0;
125
126 for (; length; length--) {
127 data = CSR1212_LE32_TO_CPU(*buffer);
128 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
136 return CSR1212_CPU_TO_BE16(crc);
137}
138#endif
139
140static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir,
141 struct csr1212_keyval *kv)
142{
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
153
154static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list,
155 u_int32_t offset)
156{
157 struct csr1212_keyval *kv;
158
159 for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) {
160 if (kv->offset == offset)
161 return kv;
162 }
163 return NULL;
164}
165
166
167/* Creation Routines */
168struct 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
205
206
207void csr1212_init_local_csr(struct csr1212_csr *csr,
208 const u_int32_t *bus_info_data, int max_rom)
209{
210 static const int mr_map[] = { 4, 64, 1024, 0 };
211
212 csr->max_rom = mr_map[max_rom];
213 memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
214}
215
216
217static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key)
218{
219 struct csr1212_keyval *kv;
220
221 if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
222 return NULL;
223
224 kv = CSR1212_MALLOC(sizeof(*kv));
225 if (!kv)
226 return NULL;
227
228 kv->key.type = type;
229 kv->key.id = key;
230
231 kv->associate = NULL;
232 kv->refcnt = 1;
233
234 kv->next = NULL;
235 kv->prev = NULL;
236 kv->offset = 0;
237 kv->valid = 0;
238 return kv;
239}
240
241struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value)
242{
243 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
244
245 if (!kv)
246 return NULL;
247
248 kv->value.immediate = value;
249 kv->valid = 1;
250 return kv;
251}
252
253struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len)
254{
255 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
256
257 if (!kv)
258 return NULL;
259
260 if (data_len > 0) {
261 kv->value.leaf.data = CSR1212_MALLOC(data_len);
262 if (!kv->value.leaf.data) {
263 CSR1212_FREE(kv);
264 return NULL;
265 }
266
267 if (data)
268 memcpy(kv->value.leaf.data, data, data_len);
269 } else {
270 kv->value.leaf.data = NULL;
271 }
272
273 kv->value.leaf.len = bytes_to_quads(data_len);
274 kv->offset = 0;
275 kv->valid = 1;
276
277 return kv;
278}
279
280struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset)
281{
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
294struct csr1212_keyval *csr1212_new_directory(u_int8_t key)
295{
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
309int csr1212_associate_keyval(struct csr1212_keyval *kv,
310 struct csr1212_keyval *associate)
311{
312 if (!kv || !associate)
313 return CSR1212_EINVAL;
314
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;
322
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;
326
327 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
328 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA)
329 return CSR1212_EINVAL;
330
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;
334
335 if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
336 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)
337 return CSR1212_EINVAL;
338
339 if (kv->associate)
340 csr1212_release_keyval(kv->associate);
341
342 associate->refcnt++;
343 kv->associate = associate;
344
345 return CSR1212_SUCCESS;
346}
347
348int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
349 struct csr1212_keyval *kv)
350{
351 struct csr1212_dentry *dentry;
352
353 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
354 return CSR1212_EINVAL;
355
356 dentry = CSR1212_MALLOC(sizeof(*dentry));
357 if (!dentry)
358 return CSR1212_ENOMEM;
359
360 dentry->kv = kv;
361
362 kv->refcnt++;
363
364 dentry->next = NULL;
365 dentry->prev = dir->value.directory.dentries_tail;
366
367 if (!dir->value.directory.dentries_head)
368 dir->value.directory.dentries_head = dentry;
369
370 if (dir->value.directory.dentries_tail)
371 dir->value.directory.dentries_tail->next = dentry;
372 dir->value.directory.dentries_tail = dentry;
373
374 return CSR1212_SUCCESS;
375}
376
377struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key,
378 u_int32_t value)
379{
380 struct csr1212_keyval *kvs, *kvk, *kvv;
381
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);
385
386 if (!kvs || !kvk || !kvv) {
387 if (kvs)
388 free_keyval(kvs);
389 if (kvk)
390 free_keyval(kvk);
391 if (kvv)
392 free_keyval(kvv);
393 return NULL;
394 }
395
396 /* Don't keep a local reference to the extended key or value. */
397 kvk->refcnt = 0;
398 kvv->refcnt = 0;
399
400 csr1212_associate_keyval(kvk, kvv);
401 csr1212_associate_keyval(kvs, kvk);
402
403 return kvs;
404}
405
406struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key,
407 const void *data, size_t data_len)
408{
409 struct csr1212_keyval *kvs, *kvk, *kvv;
410
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);
414
415 if (!kvs || !kvk || !kvv) {
416 if (kvs)
417 free_keyval(kvs);
418 if (kvk)
419 free_keyval(kvk);
420 if (kvv)
421 free_keyval(kvv);
422 return NULL;
423 }
424
425 /* Don't keep a local reference to the extended key or value. */
426 kvk->refcnt = 0;
427 kvv->refcnt = 0;
428
429 csr1212_associate_keyval(kvk, kvv);
430 csr1212_associate_keyval(kvs, kvk);
431
432 return kvs;
433}
434
435struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id,
436 const void *data, size_t data_len)
437{
438 struct csr1212_keyval *kv;
439
440 kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
441 data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
442 if (!kv)
443 return NULL;
444
445 CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
446 CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
447
448 if (data) {
449 memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
450 }
451
452 return kv;
453}
454
455
456struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
457 u_int16_t cset,
458 u_int16_t language,
459 const void *data,
460 size_t data_len)
461{
462 struct csr1212_keyval *kv;
463 char *lstr;
464
465 kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
466 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
467 if (!kv)
468 return NULL;
469
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);
473
474 lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
475
476 /* make sure last quadlet is zeroed out */
477 *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0;
478
479 /* don't copy the NUL terminator */
480 memcpy(lstr, data, data_len);
481
482 return kv;
483}
484
485static int csr1212_check_minimal_ascii(const char *s)
486{
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,
504 };
505 for (; *s; s++) {
506 if (minimal_ascii_table[*s & 0x7F] != *s)
507 return -1; /* failed */
508 }
509 /* String conforms to minimal-ascii, as specified by IEEE 1212,
510 * par. 7.4 */
511 return 0;
512}
513
514struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
515{
516 /* Check if string conform to minimal_ascii format */
517 if (csr1212_check_minimal_ascii(s))
518 return NULL;
519
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));
522}
523
524struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
525 u_int8_t palette_depth,
526 u_int8_t color_space,
527 u_int16_t language,
528 u_int16_t hscan,
529 u_int16_t vscan,
530 u_int32_t *palette,
531 u_int32_t *pixels)
532{
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;
538
539 if ((palette_depth && !palette) || !pixels)
540 return NULL;
541
542 kv = csr1212_new_descriptor_leaf(1, 0, NULL,
543 palette_size + pixel_size +
544 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
545 if (!kv)
546 return NULL;
547
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);
554
555 if (palette_size)
556 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,
557 palette_size);
558
559 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);
560
561 return kv;
562}
563
564struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
565 u_int64_t address)
566{
567 struct csr1212_keyval *kv;
568
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));
571 if(!kv)
572 return NULL;
573
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);
577
578 return kv;
579}
580
581static int csr1212_check_keyword(const char *s)
582{
583 for (; *s; s++) {
584
585 if (('A' <= *s) && (*s <= 'Z'))
586 continue;
587 if (('0' <= *s) && (*s <= '9'))
588 continue;
589 if (*s == '-')
590 continue;
591
592 return -1; /* failed */
593 }
594 /* String conforms to keyword, as specified by IEEE 1212,
595 * par. 7.6.5 */
596 return CSR1212_SUCCESS;
597}
598
599struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[])
600{
601 struct csr1212_keyval *kv;
602 char *buffer;
603 int i, data_len = 0;
604
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.
609 */
610 for (i = 0; i < strc; i++) {
611 if (!strv[i] || csr1212_check_keyword(strv[i])) {
612 return NULL;
613 }
614 data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */
615 }
616
617 /* IEEE 1212, par. 7.6.5 Keyword leaves */
618 kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);
619 if (!kv)
620 return NULL;
621
622 buffer = (char *)kv->value.leaf.data;
623
624 /* make sure last quadlet is zeroed out */
625 *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;
626
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);
631 buffer += len;
632 }
633 return kv;
634}
635
636
637/* Destruction Routines */
638
639void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
640 struct csr1212_keyval *kv)
641{
642 struct csr1212_dentry *dentry;
643
644 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
645 return;
646
647 dentry = csr1212_find_keyval(dir, kv);
648
649 if (!dentry)
650 return;
651
652 if (dentry->prev)
653 dentry->prev->next = dentry->next;
654 if (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;
660
661 CSR1212_FREE(dentry);
662
663 csr1212_release_keyval(kv);
664}
665
666
667void csr1212_disassociate_keyval(struct csr1212_keyval *kv)
668{
669 if (kv->associate) {
670 csr1212_release_keyval(kv->associate);
671 }
672
673 kv->associate = NULL;
674}
675
676
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. */
682void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
683{
684 struct csr1212_keyval *k, *a;
685 struct csr1212_dentry dentry;
686 struct csr1212_dentry *head, *tail;
687
688 dentry.kv = kv;
689 dentry.next = NULL;
690 dentry.prev = NULL;
691
692 head = &dentry;
693 tail = head;
694
695 while (head) {
696 k = head->kv;
697
698 while (k) {
699 k->refcnt--;
700
701 if (k->refcnt > 0)
702 break;
703
704 a = k->associate;
705
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;
713 }
714 }
715 free_keyval(k);
716 k = a;
717 }
718
719 head = head->next;
720 if (head) {
721 if (head->prev && head->prev != &dentry) {
722 CSR1212_FREE(head->prev);
723 }
724 head->prev = NULL;
725 } else if (tail != &dentry)
726 CSR1212_FREE(tail);
727 }
728}
729
730
731void csr1212_destroy_csr(struct csr1212_csr *csr)
732{
733 struct csr1212_csr_rom_cache *c, *oc;
734 struct csr1212_cache_region *cr, *ocr;
735
736 csr1212_release_keyval(csr->root_kv);
737
738 c = csr->cache_head;
739 while (c) {
740 oc = c;
741 cr = c->filled_head;
742 while (cr) {
743 ocr = cr;
744 cr = cr->next;
745 CSR1212_FREE(ocr);
746 }
747 c = c->next;
748 CSR1212_FREE(oc);
749 }
750
751 CSR1212_FREE(csr);
752}
753
754
755
756/* CSR Image Creation */
757
758static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
759{
760 struct csr1212_csr_rom_cache *cache;
761 u_int64_t csr_addr;
762
763 if (!csr || !csr->ops->allocate_addr_range ||
764 !csr->ops->release_addr)
765 return CSR1212_ENOMEM;
766
767 /* ROM size must be a multiple of csr->max_rom */
768 romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
769
770 csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
771 if (csr_addr == ~0ULL) {
772 return CSR1212_ENOMEM;
773 }
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;
778 }
779
780 cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
781 if (!cache) {
782 csr->ops->release_addr(csr_addr, csr->private);
783 return CSR1212_ENOMEM;
784 }
785
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);
789 CSR1212_FREE(cache);
790 return CSR1212_ENOMEM;
791 }
792
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);
796 CSR1212_FREE(cache);
797 return CSR1212_ENOMEM;
798 }
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;
802
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;
808}
809
810static inline void csr1212_remove_cache(struct csr1212_csr *csr,
811 struct csr1212_csr_rom_cache *cache)
812{
813 if (csr->cache_head == cache)
814 csr->cache_head = cache->next;
815 if (csr->cache_tail == cache)
816 csr->cache_tail = cache->prev;
817
818 if (cache->prev)
819 cache->prev->next = cache->next;
820 if (cache->next)
821 cache->next->prev = cache->prev;
822
823 if (cache->ext_rom) {
824 csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
825 csr1212_release_keyval(cache->ext_rom);
826 }
827
828 CSR1212_FREE(cache);
829}
830
831static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
832 struct csr1212_keyval **layout_tail)
833{
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;
838 int num_entries = 0;
839
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;
849 } else {
850 continue;
851 }
852 /* Special Case: Extended Key */
853 } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
854 if (last_extkey == NULL) {
855 last_extkey = dkv;
856 } else if (dkv->value.immediate != last_extkey->value.immediate) {
857 last_extkey = dkv;
858 } else {
859 continue;
860 }
861 }
862
863 num_entries += 1;
864
865 switch(dkv->key.type) {
866 default:
867 case CSR1212_KV_TYPE_IMMEDIATE:
868 case CSR1212_KV_TYPE_CSR_OFFSET:
869 break;
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;
879
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. */
885 break;
886 }
887
888 /* Add to tail of list */
889 dkv->next = NULL;
890 dkv->prev = *layout_tail;
891 (*layout_tail)->next = dkv;
892 *layout_tail = dkv;
893 break;
894 }
895 }
896 }
897 return num_entries;
898}
899
900size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
901{
902 struct csr1212_keyval *ltail = kv;
903 size_t agg_size = 0;
904
905 while(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;
910 break;
911
912 case CSR1212_KV_TYPE_DIRECTORY:
913 kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);
914 /* Add 1 quadlet for crc/len field */
915 agg_size += kv->value.directory.len + 1;
916 break;
917 }
918 kv = kv->next;
919 }
920 return quads_to_bytes(agg_size);
921}
922
923struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
924 struct csr1212_keyval *start_kv,
925 int start_pos)
926{
927 struct csr1212_keyval *kv = start_kv;
928 struct csr1212_keyval *okv = start_kv;
929 int pos = start_pos;
930 int kv_len = 0, okv_len = 0;
931
932 cache->layout_head = kv;
933
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;
938 }
939
940 switch(kv->key.type) {
941 case CSR1212_KV_TYPE_LEAF:
942 kv_len = kv->value.leaf.len;
943 break;
944
945 case CSR1212_KV_TYPE_DIRECTORY:
946 kv_len = kv->value.directory.len;
947 break;
948
949 default:
950 /* Should never get here */
951 break;
952 }
953
954 pos += quads_to_bytes(kv_len + 1);
955
956 if (pos <= cache->size) {
957 okv = kv;
958 okv_len = kv_len;
959 kv = kv->next;
960 }
961 }
962
963 cache->layout_tail = okv;
964 cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
965
966 return kv;
967}
968
969static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,
970 u_int32_t *data_buffer)
971{
972 struct csr1212_dentry *dentry;
973 struct csr1212_keyval *last_extkey_spec = NULL;
974 struct csr1212_keyval *last_extkey = NULL;
975 int index = 0;
976
977 for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
978 struct csr1212_keyval *a;
979
980 for (a = dentry->kv; a; a = a->associate) {
981 u_int32_t value = 0;
982
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;
989 } else {
990 continue;
991 }
992 /* Special Case: Extended Key */
993 } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
994 if (last_extkey == NULL) {
995 last_extkey = a;
996 } else if (a->value.immediate != last_extkey->value.immediate) {
997 last_extkey = a;
998 } else {
999 continue;
1000 }
1001 }
1002
1003 switch(a->key.type) {
1004 case CSR1212_KV_TYPE_IMMEDIATE:
1005 value = a->value.immediate;
1006 break;
1007 case CSR1212_KV_TYPE_CSR_OFFSET:
1008 value = a->value.csr_offset;
1009 break;
1010 case CSR1212_KV_TYPE_LEAF:
1011 value = a->offset;
1012 value -= dir->offset + quads_to_bytes(1+index);
1013 value = bytes_to_quads(value);
1014 break;
1015 case CSR1212_KV_TYPE_DIRECTORY:
1016 value = a->offset;
1017 value -= dir->offset + quads_to_bytes(1+index);
1018 value = bytes_to_quads(value);
1019 break;
1020 default:
1021 /* Should never get here */
1022 break; /* GDB breakpoint */
1023 }
1024
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);
1029 index++;
1030 }
1031 }
1032}
1033
1034void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
1035{
1036 struct csr1212_keyval *kv, *nkv;
1037 struct csr1212_keyval_img *kvi;
1038
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) {
1043 default:
1044 case CSR1212_KV_TYPE_IMMEDIATE:
1045 case CSR1212_KV_TYPE_CSR_OFFSET:
1046 /* Should never get here */
1047 break; /* GDB breakpoint */
1048
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));
1055
1056 kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);
1057 kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
1058 break;
1059
1060 case CSR1212_KV_TYPE_DIRECTORY:
1061 csr1212_generate_tree_subdir(kv, kvi->data);
1062
1063 kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);
1064 kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
1065 break;
1066 }
1067
1068 nkv = kv->next;
1069 if (kv->prev)
1070 kv->prev->next = NULL;
1071 if (kv->next)
1072 kv->next->prev = NULL;
1073 kv->prev = NULL;
1074 kv->next = NULL;
1075 }
1076}
1077
1078int csr1212_generate_csr_image(struct csr1212_csr *csr)
1079{
1080 struct csr1212_bus_info_block_img *bi;
1081 struct csr1212_csr_rom_cache *cache;
1082 struct csr1212_keyval *kv;
1083 size_t agg_size;
1084 int ret;
1085 int init_offset;
1086
1087 if (!csr)
1088 return CSR1212_EINVAL;
1089
1090 cache = csr->cache_head;
1091
1092 bi = (struct csr1212_bus_info_block_img*)cache->data;
1093
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);
1097
1098 csr->root_kv->next = NULL;
1099 csr->root_kv->prev = NULL;
1100
1101 agg_size = csr1212_generate_layout_order(csr->root_kv);
1102
1103 init_offset = csr->bus_info_len;
1104
1105 for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
1106 if (!cache) {
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;
1112
1113 /* Add additional cache regions, extras will be
1114 * removed later */
1115 for (; est_c; est_c--) {
1116 ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
1117 if (ret != CSR1212_SUCCESS)
1118 return ret;
1119 }
1120 /* Need to re-layout for additional cache regions */
1121 agg_size = csr1212_generate_layout_order(csr->root_kv);
1122 kv = csr->root_kv;
1123 cache = csr->cache_head;
1124 init_offset = csr->bus_info_len;
1125 }
1126 kv = csr1212_generate_positions(cache, kv, init_offset);
1127 agg_size -= cache->len;
1128 init_offset = sizeof(u_int32_t);
1129 }
1130
1131 /* Remove unused, excess cache regions */
1132 while (cache) {
1133 struct csr1212_csr_rom_cache *oc = cache;
1134
1135 cache = cache->next;
1136 csr1212_remove_cache(csr, oc);
1137 }
1138
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) {
1144 int leaf_size;
1145
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);
1150
1151 /* Zero out the unused ROM region */
1152 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1153 leaf_size - cache->len);
1154
1155 /* Subtract leaf header */
1156 leaf_size -= sizeof(u_int32_t);
1157
1158 /* Update the Extended ROM leaf length */
1159 cache->ext_rom->value.leaf.len =
1160 bytes_to_quads(leaf_size);
1161 } else {
1162 /* Zero out the unused ROM region */
1163 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1164 cache->size - cache->len);
1165 }
1166
1167 /* Copy the data into the cache buffer */
1168 csr1212_fill_cache(cache);
1169
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;
1174
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);
1178
1179 }
1180 }
1181
1182 return CSR1212_SUCCESS;
1183}
1184
1185int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len)
1186{
1187 struct csr1212_csr_rom_cache *cache;
1188
1189 for (cache = csr->cache_head; cache; cache = cache->next) {
1190 if (offset >= cache->offset &&
1191 (offset + len) <= (cache->offset + cache->size)) {
1192 memcpy(buffer,
1193 &cache->data[bytes_to_quads(offset - cache->offset)],
1194 len);
1195 return CSR1212_SUCCESS;
1196 }
1197 }
1198 return CSR1212_ENOENT;
1199}
1200
1201
1202
1203/* Parse a chunk of data as a Config ROM */
1204
1205static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
1206{
1207 struct csr1212_bus_info_block_img *bi;
1208 struct csr1212_cache_region *cr;
1209 int i;
1210 int ret;
1211
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)],
1221 csr->private);
1222 if (ret != CSR1212_SUCCESS)
1223 return ret;
1224 }
1225
1226 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1227 csr->crc_len = quads_to_bytes(bi->crc_length);
1228
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)],
1235 csr->private);
1236 if (ret != CSR1212_SUCCESS)
1237 return ret;
1238 }
1239
1240 if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
1241 return CSR1212_EINVAL;
1242
1243#if 0
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;
1249#endif
1250
1251 cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1252 if (!cr)
1253 return CSR1212_ENOMEM;
1254
1255 cr->next = NULL;
1256 cr->prev = NULL;
1257 cr->offset_start = 0;
1258 cr->offset_end = csr->crc_len + 4;
1259
1260 csr->cache_head->filled_head = cr;
1261 csr->cache_head->filled_tail = cr;
1262
1263 return CSR1212_SUCCESS;
1264}
1265
1266static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
1267 csr1212_quad_t ki,
1268 u_int32_t kv_pos)
1269{
1270 int ret = CSR1212_SUCCESS;
1271 struct csr1212_keyval *k = NULL;
1272 u_int32_t offset;
1273
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));
1278 if (!k) {
1279 ret = CSR1212_ENOMEM;
1280 goto fail;
1281 }
1282
1283 k->refcnt = 0; /* Don't keep local reference when parsing. */
1284 break;
1285
1286 case CSR1212_KV_TYPE_CSR_OFFSET:
1287 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1288 CSR1212_KV_VAL(ki));
1289 if (!k) {
1290 ret = CSR1212_ENOMEM;
1291 goto fail;
1292 }
1293 k->refcnt = 0; /* Don't keep local reference when parsing. */
1294 break;
1295
1296 default:
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. */
1303 ret = CSR1212_EIO;
1304 goto fail;
1305 }
1306
1307 k = csr1212_find_keyval_offset(dir, offset);
1308
1309 if (k)
1310 break; /* Found it. */
1311
1312 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1313 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1314 } else {
1315 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1316 }
1317 if (!k) {
1318 ret = CSR1212_ENOMEM;
1319 goto fail;
1320 }
1321 k->refcnt = 0; /* Don't keep local reference when parsing. */
1322 k->valid = 0; /* Contents not read yet so it's not valid. */
1323 k->offset = offset;
1324
1325 k->prev = dir;
1326 k->next = dir->next;
1327 dir->next->prev = k;
1328 dir->next = k;
1329 }
1330 ret = csr1212_attach_keyval_to_directory(dir, k);
1331
1332fail:
1333 if (ret != CSR1212_SUCCESS) {
1334 if (k)
1335 free_keyval(k);
1336 }
1337 return ret;
1338}
1339
1340
1341int csr1212_parse_keyval(struct csr1212_keyval *kv,
1342 struct csr1212_csr_rom_cache *cache)
1343{
1344 struct csr1212_keyval_img *kvi;
1345 int i;
1346 int ret = CSR1212_SUCCESS;
1347 int kvi_len;
1348
1349 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1350 cache->offset)];
1351 kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
1352
1353#if 0
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;
1359 goto fail;
1360 }
1361#endif
1362
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];
1367
1368 /* Some devices put null entries in their unit
1369 * directories. If we come across such an entry,
1370 * then skip it. */
1371 if (ki == 0x0)
1372 continue;
1373 ret = csr1212_parse_dir_entry(kv, ki,
1374 (kv->offset +
1375 quads_to_bytes(i + 1)));
1376 }
1377 kv->value.directory.len = kvi_len;
1378 break;
1379
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)
1384 {
1385 ret = CSR1212_ENOMEM;
1386 goto fail;
1387 }
1388
1389 kv->value.leaf.len = kvi_len;
1390 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1391 }
1392 break;
1393 }
1394
1395 kv->valid = 1;
1396
1397fail:
1398 return ret;
1399}
1400
1401
1402int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1403{
1404 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1405 struct csr1212_keyval_img *kvi = NULL;
1406 struct csr1212_csr_rom_cache *cache;
1407 int cache_index;
1408 u_int64_t addr;
1409 u_int32_t *cache_ptr;
1410 u_int16_t kv_len = 0;
1411
1412 if (!csr || !kv)
1413 return CSR1212_EINVAL;
1414
1415 /* First find which cache the data should be in (or go in if not read
1416 * yet). */
1417 for (cache = csr->cache_head; cache; cache = cache->next) {
1418 if (kv->offset >= cache->offset &&
1419 kv->offset < (cache->offset + cache->size))
1420 break;
1421 }
1422
1423 if (!cache) {
1424 csr1212_quad_t q;
1425 u_int32_t cache_size;
1426
1427 /* Only create a new cache for Extended ROM leaves. */
1428 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1429 return CSR1212_EINVAL;
1430
1431 if (csr->ops->bus_read(csr,
1432 CSR1212_REGISTER_SPACE_BASE + kv->offset,
1433 sizeof(csr1212_quad_t), &q, csr->private)) {
1434 return CSR1212_EIO;
1435 }
1436
1437 kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
1438
1439 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1440 (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1441
1442 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1443 if (!cache)
1444 return CSR1212_ENOMEM;
1445
1446 kv->value.leaf.data = &cache->data[1];
1447 csr->cache_tail->next = cache;
1448 cache->prev = csr->cache_tail;
1449 cache->next = NULL;
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;
1455 }
1456
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;
1462 cache->data[0] = q;
1463
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);
1467 }
1468
1469 cache_index = kv->offset - cache->offset;
1470
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));
1475 if (!newcr)
1476 return CSR1212_ENOMEM;
1477
1478 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1479 newcr->offset_end = newcr->offset_start;
1480 newcr->next = cr;
1481 newcr->prev = cr->prev;
1482 cr->prev = newcr;
1483 cr = newcr;
1484 break;
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) +
1490 1);
1491 break;
1492 } else if (cache_index == cr->offset_end)
1493 break;
1494 }
1495
1496 if (!cr) {
1497 cr = cache->filled_tail;
1498 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1499 if (!newcr)
1500 return CSR1212_ENOMEM;
1501
1502 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1503 newcr->offset_end = newcr->offset_start;
1504 newcr->prev = cr;
1505 newcr->next = cr->next;
1506 cr->next = newcr;
1507 cr = newcr;
1508 cache->filled_tail = newcr;
1509 }
1510
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))];
1514
1515 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1516 cr->offset_end) & ~(csr->max_rom - 1);
1517
1518 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1519 csr->private)) {
1520 if (csr->max_rom == 4)
1521 /* We've got problems! */
1522 return CSR1212_EIO;
1523
1524 /* Apperently the max_rom value was a lie, set it to
1525 * do quadlet reads and try again. */
1526 csr->max_rom = 4;
1527 continue;
1528 }
1529
1530 cr->offset_end += csr->max_rom - (cr->offset_end &
1531 (csr->max_rom - 1));
1532
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) +
1537 1);
1538 }
1539
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. */
1545 return CSR1212_EIO;
1546 }
1547
1548 ncr = cr->next;
1549
1550 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1551 /* consolidate region entries */
1552 ncr->offset_start = cr->offset_start;
1553
1554 if (cr->prev)
1555 cr->prev->next = cr->next;
1556 ncr->prev = cr->prev;
1557 if (cache->filled_head == cr)
1558 cache->filled_head = ncr;
1559 CSR1212_FREE(cr);
1560 cr = ncr;
1561 }
1562 }
1563
1564 return csr1212_parse_keyval(kv, cache);
1565}
1566
1567
1568
1569int csr1212_parse_csr(struct csr1212_csr *csr)
1570{
1571 static const int mr_map[] = { 4, 64, 1024, 0 };
1572 struct csr1212_dentry *dentry;
1573 int ret;
1574
1575 if (!csr || !csr->ops->bus_read)
1576 return CSR1212_EINVAL;
1577
1578 ret = csr1212_parse_bus_info_block(csr);
1579 if (ret != CSR1212_SUCCESS)
1580 return ret;
1581
1582 if (!csr->ops->get_max_rom)
1583 csr->max_rom = mr_map[0]; /* default value */
1584 else
1585 csr->max_rom = mr_map[csr->ops->get_max_rom(csr->bus_info_data,
1586 csr->private)];
1587
1588 csr->cache_head->layout_head = csr->root_kv;
1589 csr->cache_head->layout_tail = csr->root_kv;
1590
1591 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1592 csr->bus_info_len;
1593
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);
1598
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);
1605
1606 if (ret != CSR1212_SUCCESS)
1607 return ret;
1608 }
1609 }
1610
1611 return CSR1212_SUCCESS;
1612}