blob: c28f639823d238c187f31daca9552f88c6ec188b [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.
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] = {
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
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
Ben Collins1934b8b2005-07-09 20:01:23 -0400212#ifdef __KERNEL__
213 BUG_ON(max_rom & ~0x3);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 csr->max_rom = mr_map[max_rom];
Ben Collins1934b8b2005-07-09 20:01:23 -0400215#else
216 if (max_rom & ~0x3) /* caller supplied invalid argument */
217 csr->max_rom = 0;
218 else
219 csr->max_rom = mr_map[max_rom];
220#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
222}
223
224
225static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key)
226{
227 struct csr1212_keyval *kv;
228
229 if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
230 return NULL;
231
232 kv = CSR1212_MALLOC(sizeof(*kv));
233 if (!kv)
234 return NULL;
235
236 kv->key.type = type;
237 kv->key.id = key;
238
239 kv->associate = NULL;
240 kv->refcnt = 1;
241
242 kv->next = NULL;
243 kv->prev = NULL;
244 kv->offset = 0;
245 kv->valid = 0;
246 return kv;
247}
248
249struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value)
250{
251 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
252
253 if (!kv)
254 return NULL;
255
256 kv->value.immediate = value;
257 kv->valid = 1;
258 return kv;
259}
260
261struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len)
262{
263 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
264
265 if (!kv)
266 return NULL;
267
268 if (data_len > 0) {
269 kv->value.leaf.data = CSR1212_MALLOC(data_len);
270 if (!kv->value.leaf.data) {
271 CSR1212_FREE(kv);
272 return NULL;
273 }
274
275 if (data)
276 memcpy(kv->value.leaf.data, data, data_len);
277 } else {
278 kv->value.leaf.data = NULL;
279 }
280
281 kv->value.leaf.len = bytes_to_quads(data_len);
282 kv->offset = 0;
283 kv->valid = 1;
284
285 return kv;
286}
287
288struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset)
289{
290 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
291
292 if (!kv)
293 return NULL;
294
295 kv->value.csr_offset = csr_offset;
296
297 kv->offset = 0;
298 kv->valid = 1;
299 return kv;
300}
301
302struct csr1212_keyval *csr1212_new_directory(u_int8_t key)
303{
304 struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
305
306 if (!kv)
307 return NULL;
308
309 kv->value.directory.len = 0;
310 kv->offset = 0;
311 kv->value.directory.dentries_head = NULL;
312 kv->value.directory.dentries_tail = NULL;
313 kv->valid = 1;
314 return kv;
315}
316
317int csr1212_associate_keyval(struct csr1212_keyval *kv,
318 struct csr1212_keyval *associate)
319{
320 if (!kv || !associate)
321 return CSR1212_EINVAL;
322
323 if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
324 (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
325 associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
326 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
327 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
328 associate->key.id < 0x30))
329 return CSR1212_EINVAL;
330
331 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
332 associate->key.id != CSR1212_KV_ID_EXTENDED_KEY)
333 return CSR1212_EINVAL;
334
335 if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
336 associate->key.id != CSR1212_KV_ID_EXTENDED_DATA)
337 return CSR1212_EINVAL;
338
339 if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
340 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID)
341 return CSR1212_EINVAL;
342
343 if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
344 kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)
345 return CSR1212_EINVAL;
346
347 if (kv->associate)
348 csr1212_release_keyval(kv->associate);
349
350 associate->refcnt++;
351 kv->associate = associate;
352
353 return CSR1212_SUCCESS;
354}
355
356int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
357 struct csr1212_keyval *kv)
358{
359 struct csr1212_dentry *dentry;
360
361 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
362 return CSR1212_EINVAL;
363
364 dentry = CSR1212_MALLOC(sizeof(*dentry));
365 if (!dentry)
366 return CSR1212_ENOMEM;
367
368 dentry->kv = kv;
369
370 kv->refcnt++;
371
372 dentry->next = NULL;
373 dentry->prev = dir->value.directory.dentries_tail;
374
375 if (!dir->value.directory.dentries_head)
376 dir->value.directory.dentries_head = dentry;
377
378 if (dir->value.directory.dentries_tail)
379 dir->value.directory.dentries_tail->next = dentry;
380 dir->value.directory.dentries_tail = dentry;
381
382 return CSR1212_SUCCESS;
383}
384
385struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key,
386 u_int32_t value)
387{
388 struct csr1212_keyval *kvs, *kvk, *kvv;
389
390 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
391 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
392 kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value);
393
394 if (!kvs || !kvk || !kvv) {
395 if (kvs)
396 free_keyval(kvs);
397 if (kvk)
398 free_keyval(kvk);
399 if (kvv)
400 free_keyval(kvv);
401 return NULL;
402 }
403
404 /* Don't keep a local reference to the extended key or value. */
405 kvk->refcnt = 0;
406 kvv->refcnt = 0;
407
408 csr1212_associate_keyval(kvk, kvv);
409 csr1212_associate_keyval(kvs, kvk);
410
411 return kvs;
412}
413
414struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key,
415 const void *data, size_t data_len)
416{
417 struct csr1212_keyval *kvs, *kvk, *kvv;
418
419 kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec);
420 kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key);
421 kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len);
422
423 if (!kvs || !kvk || !kvv) {
424 if (kvs)
425 free_keyval(kvs);
426 if (kvk)
427 free_keyval(kvk);
428 if (kvv)
429 free_keyval(kvv);
430 return NULL;
431 }
432
433 /* Don't keep a local reference to the extended key or value. */
434 kvk->refcnt = 0;
435 kvv->refcnt = 0;
436
437 csr1212_associate_keyval(kvk, kvv);
438 csr1212_associate_keyval(kvs, kvk);
439
440 return kvs;
441}
442
443struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id,
444 const void *data, size_t data_len)
445{
446 struct csr1212_keyval *kv;
447
448 kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
449 data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
450 if (!kv)
451 return NULL;
452
453 CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
454 CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
455
456 if (data) {
457 memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
458 }
459
460 return kv;
461}
462
463
464struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth,
465 u_int16_t cset,
466 u_int16_t language,
467 const void *data,
468 size_t data_len)
469{
470 struct csr1212_keyval *kv;
471 char *lstr;
472
473 kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len +
474 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
475 if (!kv)
476 return NULL;
477
478 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth);
479 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset);
480 CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
481
482 lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
483
484 /* make sure last quadlet is zeroed out */
485 *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0;
486
487 /* don't copy the NUL terminator */
488 memcpy(lstr, data, data_len);
489
490 return kv;
491}
492
493static int csr1212_check_minimal_ascii(const char *s)
494{
495 static const char minimal_ascii_table[] = {
496 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
497 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00,
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
500 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27,
501 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
502 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
503 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
504 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
505 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
506 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
507 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
508 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
509 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
510 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
511 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00,
512 };
513 for (; *s; s++) {
514 if (minimal_ascii_table[*s & 0x7F] != *s)
515 return -1; /* failed */
516 }
517 /* String conforms to minimal-ascii, as specified by IEEE 1212,
518 * par. 7.4 */
519 return 0;
520}
521
522struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
523{
524 /* Check if string conform to minimal_ascii format */
525 if (csr1212_check_minimal_ascii(s))
526 return NULL;
527
528 /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */
529 return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s));
530}
531
532struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version,
533 u_int8_t palette_depth,
534 u_int8_t color_space,
535 u_int16_t language,
536 u_int16_t hscan,
537 u_int16_t vscan,
538 u_int32_t *palette,
539 u_int32_t *pixels)
540{
541 static const int pd[4] = { 0, 4, 16, 256 };
542 static const int cs[16] = { 4, 2 };
543 struct csr1212_keyval *kv;
Ben Collins1934b8b2005-07-09 20:01:23 -0400544 int palette_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 int pixel_size = (hscan * vscan + 3) & ~0x3;
546
Ben Collins1934b8b2005-07-09 20:01:23 -0400547 if (!pixels || (!palette && palette_depth) ||
548 (palette_depth & ~0x3) || (color_space & ~0xf))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 return NULL;
550
Ben Collins1934b8b2005-07-09 20:01:23 -0400551 palette_size = pd[palette_depth] * cs[color_space];
552
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 kv = csr1212_new_descriptor_leaf(1, 0, NULL,
554 palette_size + pixel_size +
555 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);
556 if (!kv)
557 return NULL;
558
559 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version);
560 CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth);
561 CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space);
562 CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);
563 CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan);
564 CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan);
565
566 if (palette_size)
567 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,
568 palette_size);
569
570 memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);
571
572 return kv;
573}
574
575struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,
576 u_int64_t address)
577{
578 struct csr1212_keyval *kv;
579
580 /* IEEE 1212, par. 7.5.4.3 Modifiable descriptors */
581 kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t));
582 if(!kv)
583 return NULL;
584
585 CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size);
586 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address);
587 CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address);
588
589 return kv;
590}
591
592static int csr1212_check_keyword(const char *s)
593{
594 for (; *s; s++) {
595
596 if (('A' <= *s) && (*s <= 'Z'))
597 continue;
598 if (('0' <= *s) && (*s <= '9'))
599 continue;
600 if (*s == '-')
601 continue;
602
603 return -1; /* failed */
604 }
605 /* String conforms to keyword, as specified by IEEE 1212,
606 * par. 7.6.5 */
607 return CSR1212_SUCCESS;
608}
609
610struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[])
611{
612 struct csr1212_keyval *kv;
613 char *buffer;
614 int i, data_len = 0;
615
616 /* Check all keywords to see if they conform to restrictions:
617 * Only the following characters is allowed ['A'..'Z','0'..'9','-']
618 * Each word is zero-terminated.
619 * Also calculate the total length of the keywords.
620 */
621 for (i = 0; i < strc; i++) {
622 if (!strv[i] || csr1212_check_keyword(strv[i])) {
623 return NULL;
624 }
625 data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */
626 }
627
628 /* IEEE 1212, par. 7.6.5 Keyword leaves */
629 kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);
630 if (!kv)
631 return NULL;
632
633 buffer = (char *)kv->value.leaf.data;
634
635 /* make sure last quadlet is zeroed out */
636 *((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;
637
638 /* Copy keyword(s) into leaf data buffer */
639 for (i = 0; i < strc; i++) {
640 int len = strlen(strv[i]) + 1;
641 memcpy(buffer, strv[i], len);
642 buffer += len;
643 }
644 return kv;
645}
646
647
648/* Destruction Routines */
649
650void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
651 struct csr1212_keyval *kv)
652{
653 struct csr1212_dentry *dentry;
654
655 if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
656 return;
657
658 dentry = csr1212_find_keyval(dir, kv);
659
660 if (!dentry)
661 return;
662
663 if (dentry->prev)
664 dentry->prev->next = dentry->next;
665 if (dentry->next)
666 dentry->next->prev = dentry->prev;
667 if (dir->value.directory.dentries_head == dentry)
668 dir->value.directory.dentries_head = dentry->next;
669 if (dir->value.directory.dentries_tail == dentry)
670 dir->value.directory.dentries_tail = dentry->prev;
671
672 CSR1212_FREE(dentry);
673
674 csr1212_release_keyval(kv);
675}
676
677
678void csr1212_disassociate_keyval(struct csr1212_keyval *kv)
679{
680 if (kv->associate) {
681 csr1212_release_keyval(kv->associate);
682 }
683
684 kv->associate = NULL;
685}
686
687
688/* This function is used to free the memory taken by a keyval. If the given
689 * keyval is a directory type, then any keyvals contained in that directory
690 * will be destroyed as well if their respective refcnts are 0. By means of
691 * list manipulation, this routine will descend a directory structure in a
692 * non-recursive manner. */
693void _csr1212_destroy_keyval(struct csr1212_keyval *kv)
694{
695 struct csr1212_keyval *k, *a;
696 struct csr1212_dentry dentry;
697 struct csr1212_dentry *head, *tail;
698
699 dentry.kv = kv;
700 dentry.next = NULL;
701 dentry.prev = NULL;
702
703 head = &dentry;
704 tail = head;
705
706 while (head) {
707 k = head->kv;
708
709 while (k) {
710 k->refcnt--;
711
712 if (k->refcnt > 0)
713 break;
714
715 a = k->associate;
716
717 if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
718 /* If the current entry is a directory, then move all
719 * the entries to the destruction list. */
720 if (k->value.directory.dentries_head) {
721 tail->next = k->value.directory.dentries_head;
722 k->value.directory.dentries_head->prev = tail;
723 tail = k->value.directory.dentries_tail;
724 }
725 }
726 free_keyval(k);
727 k = a;
728 }
729
730 head = head->next;
731 if (head) {
732 if (head->prev && head->prev != &dentry) {
733 CSR1212_FREE(head->prev);
734 }
735 head->prev = NULL;
736 } else if (tail != &dentry)
737 CSR1212_FREE(tail);
738 }
739}
740
741
742void csr1212_destroy_csr(struct csr1212_csr *csr)
743{
744 struct csr1212_csr_rom_cache *c, *oc;
745 struct csr1212_cache_region *cr, *ocr;
746
747 csr1212_release_keyval(csr->root_kv);
748
749 c = csr->cache_head;
750 while (c) {
751 oc = c;
752 cr = c->filled_head;
753 while (cr) {
754 ocr = cr;
755 cr = cr->next;
756 CSR1212_FREE(ocr);
757 }
758 c = c->next;
759 CSR1212_FREE(oc);
760 }
761
762 CSR1212_FREE(csr);
763}
764
765
766
767/* CSR Image Creation */
768
769static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
770{
771 struct csr1212_csr_rom_cache *cache;
772 u_int64_t csr_addr;
773
Ben Collins1934b8b2005-07-09 20:01:23 -0400774 if (!csr || !csr->ops || !csr->ops->allocate_addr_range ||
775 !csr->ops->release_addr || csr->max_rom < 1)
776 return CSR1212_EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
778 /* ROM size must be a multiple of csr->max_rom */
779 romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
780
781 csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);
Ben Collins67372312006-06-12 18:15:31 -0400782 if (csr_addr == CSR1212_INVALID_ADDR_SPACE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return CSR1212_ENOMEM;
784 }
785 if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
786 /* Invalid address returned from allocate_addr_range(). */
787 csr->ops->release_addr(csr_addr, csr->private);
788 return CSR1212_ENOMEM;
789 }
790
791 cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);
792 if (!cache) {
793 csr->ops->release_addr(csr_addr, csr->private);
794 return CSR1212_ENOMEM;
795 }
796
797 cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);
798 if (!cache->ext_rom) {
799 csr->ops->release_addr(csr_addr, csr->private);
800 CSR1212_FREE(cache);
801 return CSR1212_ENOMEM;
802 }
803
804 if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) {
805 csr1212_release_keyval(cache->ext_rom);
806 csr->ops->release_addr(csr_addr, csr->private);
807 CSR1212_FREE(cache);
808 return CSR1212_ENOMEM;
809 }
810 cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
811 cache->ext_rom->value.leaf.len = -1;
812 cache->ext_rom->value.leaf.data = cache->data;
813
814 /* Add cache to tail of cache list */
815 cache->prev = csr->cache_tail;
816 csr->cache_tail->next = cache;
817 csr->cache_tail = cache;
818 return CSR1212_SUCCESS;
819}
820
821static inline void csr1212_remove_cache(struct csr1212_csr *csr,
822 struct csr1212_csr_rom_cache *cache)
823{
824 if (csr->cache_head == cache)
825 csr->cache_head = cache->next;
826 if (csr->cache_tail == cache)
827 csr->cache_tail = cache->prev;
828
829 if (cache->prev)
830 cache->prev->next = cache->next;
831 if (cache->next)
832 cache->next->prev = cache->prev;
833
834 if (cache->ext_rom) {
835 csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);
836 csr1212_release_keyval(cache->ext_rom);
837 }
838
839 CSR1212_FREE(cache);
840}
841
842static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
843 struct csr1212_keyval **layout_tail)
844{
845 struct csr1212_dentry *dentry;
846 struct csr1212_keyval *dkv;
847 struct csr1212_keyval *last_extkey_spec = NULL;
848 struct csr1212_keyval *last_extkey = NULL;
849 int num_entries = 0;
850
851 for (dentry = dir->value.directory.dentries_head; dentry;
852 dentry = dentry->next) {
853 for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
854 /* Special Case: Extended Key Specifier_ID */
855 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
856 if (last_extkey_spec == NULL) {
857 last_extkey_spec = dkv;
858 } else if (dkv->value.immediate != last_extkey_spec->value.immediate) {
859 last_extkey_spec = dkv;
860 } else {
861 continue;
862 }
863 /* Special Case: Extended Key */
864 } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
865 if (last_extkey == NULL) {
866 last_extkey = dkv;
867 } else if (dkv->value.immediate != last_extkey->value.immediate) {
868 last_extkey = dkv;
869 } else {
870 continue;
871 }
872 }
873
874 num_entries += 1;
875
876 switch(dkv->key.type) {
877 default:
878 case CSR1212_KV_TYPE_IMMEDIATE:
879 case CSR1212_KV_TYPE_CSR_OFFSET:
880 break;
881 case CSR1212_KV_TYPE_LEAF:
882 case CSR1212_KV_TYPE_DIRECTORY:
883 /* Remove from list */
884 if (dkv->prev && (dkv->prev->next == dkv))
885 dkv->prev->next = dkv->next;
886 if (dkv->next && (dkv->next->prev == dkv))
887 dkv->next->prev = dkv->prev;
888 //if (dkv == *layout_tail)
889 // *layout_tail = dkv->prev;
890
891 /* Special case: Extended ROM leafs */
892 if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
893 dkv->value.leaf.len = -1;
894 /* Don't add Extended ROM leafs in the layout list,
895 * they are handled differently. */
896 break;
897 }
898
899 /* Add to tail of list */
900 dkv->next = NULL;
901 dkv->prev = *layout_tail;
902 (*layout_tail)->next = dkv;
903 *layout_tail = dkv;
904 break;
905 }
906 }
907 }
908 return num_entries;
909}
910
911size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
912{
913 struct csr1212_keyval *ltail = kv;
914 size_t agg_size = 0;
915
916 while(kv) {
917 switch(kv->key.type) {
918 case CSR1212_KV_TYPE_LEAF:
919 /* Add 1 quadlet for crc/len field */
920 agg_size += kv->value.leaf.len + 1;
921 break;
922
923 case CSR1212_KV_TYPE_DIRECTORY:
924 kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);
925 /* Add 1 quadlet for crc/len field */
926 agg_size += kv->value.directory.len + 1;
927 break;
928 }
929 kv = kv->next;
930 }
931 return quads_to_bytes(agg_size);
932}
933
934struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
935 struct csr1212_keyval *start_kv,
936 int start_pos)
937{
938 struct csr1212_keyval *kv = start_kv;
939 struct csr1212_keyval *okv = start_kv;
940 int pos = start_pos;
941 int kv_len = 0, okv_len = 0;
942
943 cache->layout_head = kv;
944
945 while(kv && pos < cache->size) {
946 /* Special case: Extended ROM leafs */
947 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
948 kv->offset = cache->offset + pos;
949 }
950
951 switch(kv->key.type) {
952 case CSR1212_KV_TYPE_LEAF:
953 kv_len = kv->value.leaf.len;
954 break;
955
956 case CSR1212_KV_TYPE_DIRECTORY:
957 kv_len = kv->value.directory.len;
958 break;
959
960 default:
961 /* Should never get here */
962 break;
963 }
964
965 pos += quads_to_bytes(kv_len + 1);
966
967 if (pos <= cache->size) {
968 okv = kv;
969 okv_len = kv_len;
970 kv = kv->next;
971 }
972 }
973
974 cache->layout_tail = okv;
975 cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);
976
977 return kv;
978}
979
980static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,
981 u_int32_t *data_buffer)
982{
983 struct csr1212_dentry *dentry;
984 struct csr1212_keyval *last_extkey_spec = NULL;
985 struct csr1212_keyval *last_extkey = NULL;
986 int index = 0;
987
988 for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {
989 struct csr1212_keyval *a;
990
991 for (a = dentry->kv; a; a = a->associate) {
992 u_int32_t value = 0;
993
994 /* Special Case: Extended Key Specifier_ID */
995 if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
996 if (last_extkey_spec == NULL) {
997 last_extkey_spec = a;
998 } else if (a->value.immediate != last_extkey_spec->value.immediate) {
999 last_extkey_spec = a;
1000 } else {
1001 continue;
1002 }
1003 /* Special Case: Extended Key */
1004 } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
1005 if (last_extkey == NULL) {
1006 last_extkey = a;
1007 } else if (a->value.immediate != last_extkey->value.immediate) {
1008 last_extkey = a;
1009 } else {
1010 continue;
1011 }
1012 }
1013
1014 switch(a->key.type) {
1015 case CSR1212_KV_TYPE_IMMEDIATE:
1016 value = a->value.immediate;
1017 break;
1018 case CSR1212_KV_TYPE_CSR_OFFSET:
1019 value = a->value.csr_offset;
1020 break;
1021 case CSR1212_KV_TYPE_LEAF:
1022 value = a->offset;
1023 value -= dir->offset + quads_to_bytes(1+index);
1024 value = bytes_to_quads(value);
1025 break;
1026 case CSR1212_KV_TYPE_DIRECTORY:
1027 value = a->offset;
1028 value -= dir->offset + quads_to_bytes(1+index);
1029 value = bytes_to_quads(value);
1030 break;
1031 default:
1032 /* Should never get here */
1033 break; /* GDB breakpoint */
1034 }
1035
1036 value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;
1037 value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
1038 (CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);
1039 data_buffer[index] = CSR1212_CPU_TO_BE32(value);
1040 index++;
1041 }
1042 }
1043}
1044
1045void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
1046{
1047 struct csr1212_keyval *kv, *nkv;
1048 struct csr1212_keyval_img *kvi;
1049
1050 for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {
1051 kvi = (struct csr1212_keyval_img *)
1052 (cache->data + bytes_to_quads(kv->offset - cache->offset));
1053 switch(kv->key.type) {
1054 default:
1055 case CSR1212_KV_TYPE_IMMEDIATE:
1056 case CSR1212_KV_TYPE_CSR_OFFSET:
1057 /* Should never get here */
1058 break; /* GDB breakpoint */
1059
1060 case CSR1212_KV_TYPE_LEAF:
1061 /* Don't copy over Extended ROM areas, they are
1062 * already filled out! */
1063 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1064 memcpy(kvi->data, kv->value.leaf.data,
1065 quads_to_bytes(kv->value.leaf.len));
1066
1067 kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);
1068 kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
1069 break;
1070
1071 case CSR1212_KV_TYPE_DIRECTORY:
1072 csr1212_generate_tree_subdir(kv, kvi->data);
1073
1074 kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);
1075 kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);
1076 break;
1077 }
1078
1079 nkv = kv->next;
1080 if (kv->prev)
1081 kv->prev->next = NULL;
1082 if (kv->next)
1083 kv->next->prev = NULL;
1084 kv->prev = NULL;
1085 kv->next = NULL;
1086 }
1087}
1088
1089int csr1212_generate_csr_image(struct csr1212_csr *csr)
1090{
1091 struct csr1212_bus_info_block_img *bi;
1092 struct csr1212_csr_rom_cache *cache;
1093 struct csr1212_keyval *kv;
1094 size_t agg_size;
1095 int ret;
1096 int init_offset;
1097
1098 if (!csr)
1099 return CSR1212_EINVAL;
1100
1101 cache = csr->cache_head;
1102
1103 bi = (struct csr1212_bus_info_block_img*)cache->data;
1104
1105 bi->length = bytes_to_quads(csr->bus_info_len) - 1;
1106 bi->crc_length = bi->length;
1107 bi->crc = csr1212_crc16(bi->data, bi->crc_length);
1108
1109 csr->root_kv->next = NULL;
1110 csr->root_kv->prev = NULL;
1111
1112 agg_size = csr1212_generate_layout_order(csr->root_kv);
1113
1114 init_offset = csr->bus_info_len;
1115
1116 for (kv = csr->root_kv, cache = csr->cache_head; kv; cache = cache->next) {
1117 if (!cache) {
1118 /* Estimate approximate number of additional cache
1119 * regions needed (it assumes that the cache holding
1120 * the first 1K Config ROM space always exists). */
1121 int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
1122 (2 * sizeof(u_int32_t))) + 1;
1123
1124 /* Add additional cache regions, extras will be
1125 * removed later */
1126 for (; est_c; est_c--) {
1127 ret = csr1212_append_new_cache(csr, CSR1212_EXTENDED_ROM_SIZE);
1128 if (ret != CSR1212_SUCCESS)
1129 return ret;
1130 }
1131 /* Need to re-layout for additional cache regions */
1132 agg_size = csr1212_generate_layout_order(csr->root_kv);
1133 kv = csr->root_kv;
1134 cache = csr->cache_head;
1135 init_offset = csr->bus_info_len;
1136 }
1137 kv = csr1212_generate_positions(cache, kv, init_offset);
1138 agg_size -= cache->len;
1139 init_offset = sizeof(u_int32_t);
1140 }
1141
1142 /* Remove unused, excess cache regions */
1143 while (cache) {
1144 struct csr1212_csr_rom_cache *oc = cache;
1145
1146 cache = cache->next;
1147 csr1212_remove_cache(csr, oc);
1148 }
1149
1150 /* Go through the list backward so that when done, the correct CRC
1151 * will be calculated for the Extended ROM areas. */
1152 for(cache = csr->cache_tail; cache; cache = cache->prev) {
1153 /* Only Extended ROM caches should have this set. */
1154 if (cache->ext_rom) {
1155 int leaf_size;
1156
1157 /* Make sure the Extended ROM leaf is a multiple of
1158 * max_rom in size. */
Ben Collins1934b8b2005-07-09 20:01:23 -04001159 if (csr->max_rom < 1)
1160 return CSR1212_EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 leaf_size = (cache->len + (csr->max_rom - 1)) &
1162 ~(csr->max_rom - 1);
1163
1164 /* Zero out the unused ROM region */
1165 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1166 leaf_size - cache->len);
1167
1168 /* Subtract leaf header */
1169 leaf_size -= sizeof(u_int32_t);
1170
1171 /* Update the Extended ROM leaf length */
1172 cache->ext_rom->value.leaf.len =
1173 bytes_to_quads(leaf_size);
1174 } else {
1175 /* Zero out the unused ROM region */
1176 memset(cache->data + bytes_to_quads(cache->len), 0x00,
1177 cache->size - cache->len);
1178 }
1179
1180 /* Copy the data into the cache buffer */
1181 csr1212_fill_cache(cache);
1182
1183 if (cache != csr->cache_head) {
1184 /* Set the length and CRC of the extended ROM. */
1185 struct csr1212_keyval_img *kvi =
1186 (struct csr1212_keyval_img*)cache->data;
1187
1188 kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1);
1189 kvi->crc = csr1212_crc16(kvi->data,
1190 bytes_to_quads(cache->len) - 1);
1191
1192 }
1193 }
1194
1195 return CSR1212_SUCCESS;
1196}
1197
1198int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int32_t len)
1199{
1200 struct csr1212_csr_rom_cache *cache;
1201
1202 for (cache = csr->cache_head; cache; cache = cache->next) {
1203 if (offset >= cache->offset &&
1204 (offset + len) <= (cache->offset + cache->size)) {
1205 memcpy(buffer,
1206 &cache->data[bytes_to_quads(offset - cache->offset)],
1207 len);
1208 return CSR1212_SUCCESS;
1209 }
1210 }
1211 return CSR1212_ENOENT;
1212}
1213
1214
1215
1216/* Parse a chunk of data as a Config ROM */
1217
1218static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
1219{
1220 struct csr1212_bus_info_block_img *bi;
1221 struct csr1212_cache_region *cr;
1222 int i;
1223 int ret;
1224
1225 /* IEEE 1212 says that the entire bus info block should be readable in
1226 * a single transaction regardless of the max_rom value.
1227 * Unfortunately, many IEEE 1394 devices do not abide by that, so the
1228 * bus info block will be read 1 quadlet at a time. The rest of the
1229 * ConfigROM will be read according to the max_rom field. */
1230 for (i = 0; i < csr->bus_info_len; i += sizeof(csr1212_quad_t)) {
1231 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1232 sizeof(csr1212_quad_t),
1233 &csr->cache_head->data[bytes_to_quads(i)],
1234 csr->private);
1235 if (ret != CSR1212_SUCCESS)
1236 return ret;
Stefan Richterb2051f82007-01-03 19:32:13 +01001237
1238 /* check ROM header's info_length */
1239 if (i == 0 &&
1240 CSR1212_BE32_TO_CPU(csr->cache_head->data[0]) >> 24 !=
1241 bytes_to_quads(csr->bus_info_len) - 1)
1242 return CSR1212_EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
1244
1245 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1246 csr->crc_len = quads_to_bytes(bi->crc_length);
1247
1248 /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
1249 * always the case, so read the rest of the crc area 1 quadlet at a time. */
1250 for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) {
1251 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1252 sizeof(csr1212_quad_t),
1253 &csr->cache_head->data[bytes_to_quads(i)],
1254 csr->private);
1255 if (ret != CSR1212_SUCCESS)
1256 return ret;
1257 }
1258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259#if 0
1260 /* Apparently there are too many differnt wrong implementations of the
1261 * CRC algorithm that verifying them is moot. */
1262 if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
1263 (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
1264 return CSR1212_EINVAL;
1265#endif
1266
Stefan Richter85511582005-11-07 06:31:45 -05001267 cr = CSR1212_MALLOC(sizeof(*cr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 if (!cr)
1269 return CSR1212_ENOMEM;
1270
1271 cr->next = NULL;
1272 cr->prev = NULL;
1273 cr->offset_start = 0;
1274 cr->offset_end = csr->crc_len + 4;
1275
1276 csr->cache_head->filled_head = cr;
1277 csr->cache_head->filled_tail = cr;
1278
1279 return CSR1212_SUCCESS;
1280}
1281
1282static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
1283 csr1212_quad_t ki,
1284 u_int32_t kv_pos)
1285{
1286 int ret = CSR1212_SUCCESS;
1287 struct csr1212_keyval *k = NULL;
1288 u_int32_t offset;
1289
1290 switch(CSR1212_KV_KEY_TYPE(ki)) {
1291 case CSR1212_KV_TYPE_IMMEDIATE:
1292 k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
1293 CSR1212_KV_VAL(ki));
1294 if (!k) {
1295 ret = CSR1212_ENOMEM;
1296 goto fail;
1297 }
1298
1299 k->refcnt = 0; /* Don't keep local reference when parsing. */
1300 break;
1301
1302 case CSR1212_KV_TYPE_CSR_OFFSET:
1303 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1304 CSR1212_KV_VAL(ki));
1305 if (!k) {
1306 ret = CSR1212_ENOMEM;
1307 goto fail;
1308 }
1309 k->refcnt = 0; /* Don't keep local reference when parsing. */
1310 break;
1311
1312 default:
1313 /* Compute the offset from 0xffff f000 0000. */
1314 offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
1315 if (offset == kv_pos) {
1316 /* Uh-oh. Can't have a relative offset of 0 for Leaves
1317 * or Directories. The Config ROM image is most likely
1318 * messed up, so we'll just abort here. */
1319 ret = CSR1212_EIO;
1320 goto fail;
1321 }
1322
1323 k = csr1212_find_keyval_offset(dir, offset);
1324
1325 if (k)
1326 break; /* Found it. */
1327
1328 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1329 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1330 } else {
1331 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1332 }
1333 if (!k) {
1334 ret = CSR1212_ENOMEM;
1335 goto fail;
1336 }
1337 k->refcnt = 0; /* Don't keep local reference when parsing. */
1338 k->valid = 0; /* Contents not read yet so it's not valid. */
1339 k->offset = offset;
1340
1341 k->prev = dir;
1342 k->next = dir->next;
1343 dir->next->prev = k;
1344 dir->next = k;
1345 }
1346 ret = csr1212_attach_keyval_to_directory(dir, k);
1347
1348fail:
1349 if (ret != CSR1212_SUCCESS) {
1350 if (k)
1351 free_keyval(k);
1352 }
1353 return ret;
1354}
1355
1356
1357int csr1212_parse_keyval(struct csr1212_keyval *kv,
1358 struct csr1212_csr_rom_cache *cache)
1359{
1360 struct csr1212_keyval_img *kvi;
1361 int i;
1362 int ret = CSR1212_SUCCESS;
1363 int kvi_len;
1364
1365 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1366 cache->offset)];
1367 kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
1368
1369#if 0
1370 /* Apparently there are too many differnt wrong implementations of the
1371 * CRC algorithm that verifying them is moot. */
1372 if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
1373 (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
1374 ret = CSR1212_EINVAL;
1375 goto fail;
1376 }
1377#endif
1378
1379 switch(kv->key.type) {
1380 case CSR1212_KV_TYPE_DIRECTORY:
1381 for (i = 0; i < kvi_len; i++) {
1382 csr1212_quad_t ki = kvi->data[i];
1383
1384 /* Some devices put null entries in their unit
1385 * directories. If we come across such an entry,
1386 * then skip it. */
1387 if (ki == 0x0)
1388 continue;
1389 ret = csr1212_parse_dir_entry(kv, ki,
1390 (kv->offset +
1391 quads_to_bytes(i + 1)));
1392 }
1393 kv->value.directory.len = kvi_len;
1394 break;
1395
1396 case CSR1212_KV_TYPE_LEAF:
1397 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
1398 kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
Stefan Richter85511582005-11-07 06:31:45 -05001399 if (!kv->value.leaf.data) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400 ret = CSR1212_ENOMEM;
1401 goto fail;
1402 }
1403
1404 kv->value.leaf.len = kvi_len;
1405 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1406 }
1407 break;
1408 }
1409
1410 kv->valid = 1;
1411
1412fail:
1413 return ret;
1414}
1415
1416
1417int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1418{
1419 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1420 struct csr1212_keyval_img *kvi = NULL;
1421 struct csr1212_csr_rom_cache *cache;
1422 int cache_index;
1423 u_int64_t addr;
1424 u_int32_t *cache_ptr;
1425 u_int16_t kv_len = 0;
1426
Ben Collins1934b8b2005-07-09 20:01:23 -04001427 if (!csr || !kv || csr->max_rom < 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 return CSR1212_EINVAL;
1429
1430 /* First find which cache the data should be in (or go in if not read
1431 * yet). */
1432 for (cache = csr->cache_head; cache; cache = cache->next) {
1433 if (kv->offset >= cache->offset &&
1434 kv->offset < (cache->offset + cache->size))
1435 break;
1436 }
1437
1438 if (!cache) {
1439 csr1212_quad_t q;
1440 u_int32_t cache_size;
1441
1442 /* Only create a new cache for Extended ROM leaves. */
1443 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1444 return CSR1212_EINVAL;
1445
1446 if (csr->ops->bus_read(csr,
1447 CSR1212_REGISTER_SPACE_BASE + kv->offset,
1448 sizeof(csr1212_quad_t), &q, csr->private)) {
1449 return CSR1212_EIO;
1450 }
1451
1452 kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
1453
1454 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1455 (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1456
1457 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1458 if (!cache)
1459 return CSR1212_ENOMEM;
1460
1461 kv->value.leaf.data = &cache->data[1];
1462 csr->cache_tail->next = cache;
1463 cache->prev = csr->cache_tail;
1464 cache->next = NULL;
1465 csr->cache_tail = cache;
1466 cache->filled_head =
Stefan Richter85511582005-11-07 06:31:45 -05001467 CSR1212_MALLOC(sizeof(*cache->filled_head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if (!cache->filled_head) {
1469 return CSR1212_ENOMEM;
1470 }
1471
1472 cache->filled_head->offset_start = 0;
1473 cache->filled_head->offset_end = sizeof(csr1212_quad_t);
1474 cache->filled_tail = cache->filled_head;
1475 cache->filled_head->next = NULL;
1476 cache->filled_head->prev = NULL;
1477 cache->data[0] = q;
1478
1479 /* Don't read the entire extended ROM now. Pieces of it will
1480 * be read when entries inside it are read. */
1481 return csr1212_parse_keyval(kv, cache);
1482 }
1483
1484 cache_index = kv->offset - cache->offset;
1485
1486 /* Now seach read portions of the cache to see if it is there. */
1487 for (cr = cache->filled_head; cr; cr = cr->next) {
1488 if (cache_index < cr->offset_start) {
Stefan Richter85511582005-11-07 06:31:45 -05001489 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 if (!newcr)
1491 return CSR1212_ENOMEM;
1492
1493 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1494 newcr->offset_end = newcr->offset_start;
1495 newcr->next = cr;
1496 newcr->prev = cr->prev;
1497 cr->prev = newcr;
1498 cr = newcr;
1499 break;
1500 } else if ((cache_index >= cr->offset_start) &&
1501 (cache_index < cr->offset_end)) {
1502 kvi = (struct csr1212_keyval_img*)
1503 (&cache->data[bytes_to_quads(cache_index)]);
1504 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1505 1);
1506 break;
1507 } else if (cache_index == cr->offset_end)
1508 break;
1509 }
1510
1511 if (!cr) {
1512 cr = cache->filled_tail;
Stefan Richter85511582005-11-07 06:31:45 -05001513 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (!newcr)
1515 return CSR1212_ENOMEM;
1516
1517 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1518 newcr->offset_end = newcr->offset_start;
1519 newcr->prev = cr;
1520 newcr->next = cr->next;
1521 cr->next = newcr;
1522 cr = newcr;
1523 cache->filled_tail = newcr;
1524 }
1525
1526 while(!kvi || cr->offset_end < cache_index + kv_len) {
1527 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1528 ~(csr->max_rom - 1))];
1529
1530 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1531 cr->offset_end) & ~(csr->max_rom - 1);
1532
1533 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1534 csr->private)) {
1535 if (csr->max_rom == 4)
1536 /* We've got problems! */
1537 return CSR1212_EIO;
1538
1539 /* Apperently the max_rom value was a lie, set it to
1540 * do quadlet reads and try again. */
1541 csr->max_rom = 4;
1542 continue;
1543 }
1544
1545 cr->offset_end += csr->max_rom - (cr->offset_end &
1546 (csr->max_rom - 1));
1547
1548 if (!kvi && (cr->offset_end > cache_index)) {
1549 kvi = (struct csr1212_keyval_img*)
1550 (&cache->data[bytes_to_quads(cache_index)]);
1551 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1552 1);
1553 }
1554
1555 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1556 /* The Leaf or Directory claims its length extends
1557 * beyond the ConfigROM image region and thus beyond the
1558 * end of our cache region. Therefore, we abort now
1559 * rather than seg faulting later. */
1560 return CSR1212_EIO;
1561 }
1562
1563 ncr = cr->next;
1564
1565 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1566 /* consolidate region entries */
1567 ncr->offset_start = cr->offset_start;
1568
1569 if (cr->prev)
1570 cr->prev->next = cr->next;
1571 ncr->prev = cr->prev;
1572 if (cache->filled_head == cr)
1573 cache->filled_head = ncr;
1574 CSR1212_FREE(cr);
1575 cr = ncr;
1576 }
1577 }
1578
1579 return csr1212_parse_keyval(kv, cache);
1580}
1581
1582
1583
1584int csr1212_parse_csr(struct csr1212_csr *csr)
1585{
1586 static const int mr_map[] = { 4, 64, 1024, 0 };
1587 struct csr1212_dentry *dentry;
1588 int ret;
1589
Ben Collins1934b8b2005-07-09 20:01:23 -04001590 if (!csr || !csr->ops || !csr->ops->bus_read)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 return CSR1212_EINVAL;
1592
1593 ret = csr1212_parse_bus_info_block(csr);
1594 if (ret != CSR1212_SUCCESS)
1595 return ret;
1596
1597 if (!csr->ops->get_max_rom)
1598 csr->max_rom = mr_map[0]; /* default value */
Ben Collins1934b8b2005-07-09 20:01:23 -04001599 else {
1600 int i = csr->ops->get_max_rom(csr->bus_info_data,
1601 csr->private);
1602 if (i & ~0x3)
1603 return CSR1212_EINVAL;
1604 csr->max_rom = mr_map[i];
1605 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606
1607 csr->cache_head->layout_head = csr->root_kv;
1608 csr->cache_head->layout_tail = csr->root_kv;
1609
1610 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1611 csr->bus_info_len;
1612
1613 csr->root_kv->valid = 0;
1614 csr->root_kv->next = csr->root_kv;
1615 csr->root_kv->prev = csr->root_kv;
Jody McIntyre5303a982005-11-22 12:17:11 -05001616 ret = _csr1212_read_keyval(csr, csr->root_kv);
1617 if (ret != CSR1212_SUCCESS)
1618 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
1620 /* Scan through the Root directory finding all extended ROM regions
1621 * and make cache regions for them */
1622 for (dentry = csr->root_kv->value.directory.dentries_head;
1623 dentry; dentry = dentry->next) {
Jody McIntyrea96074e2005-11-22 12:17:14 -05001624 if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
1625 !dentry->kv->valid) {
Jody McIntyre5303a982005-11-22 12:17:11 -05001626 ret = _csr1212_read_keyval(csr, dentry->kv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 if (ret != CSR1212_SUCCESS)
1628 return ret;
1629 }
1630 }
1631
1632 return CSR1212_SUCCESS;
1633}