blob: 586f71e7346a5e7d8fcfbbcb06a4bac543cf7124 [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] = {
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
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;
1237 }
1238
1239 bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
1240 csr->crc_len = quads_to_bytes(bi->crc_length);
1241
1242 /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that is not
1243 * always the case, so read the rest of the crc area 1 quadlet at a time. */
1244 for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(csr1212_quad_t)) {
1245 ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
1246 sizeof(csr1212_quad_t),
1247 &csr->cache_head->data[bytes_to_quads(i)],
1248 csr->private);
1249 if (ret != CSR1212_SUCCESS)
1250 return ret;
1251 }
1252
1253 if (bytes_to_quads(csr->bus_info_len - sizeof(csr1212_quad_t)) != bi->length)
1254 return CSR1212_EINVAL;
1255
1256#if 0
1257 /* Apparently there are too many differnt wrong implementations of the
1258 * CRC algorithm that verifying them is moot. */
1259 if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
1260 (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
1261 return CSR1212_EINVAL;
1262#endif
1263
Stefan Richter85511582005-11-07 06:31:45 -05001264 cr = CSR1212_MALLOC(sizeof(*cr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 if (!cr)
1266 return CSR1212_ENOMEM;
1267
1268 cr->next = NULL;
1269 cr->prev = NULL;
1270 cr->offset_start = 0;
1271 cr->offset_end = csr->crc_len + 4;
1272
1273 csr->cache_head->filled_head = cr;
1274 csr->cache_head->filled_tail = cr;
1275
1276 return CSR1212_SUCCESS;
1277}
1278
1279static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
1280 csr1212_quad_t ki,
1281 u_int32_t kv_pos)
1282{
1283 int ret = CSR1212_SUCCESS;
1284 struct csr1212_keyval *k = NULL;
1285 u_int32_t offset;
1286
1287 switch(CSR1212_KV_KEY_TYPE(ki)) {
1288 case CSR1212_KV_TYPE_IMMEDIATE:
1289 k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
1290 CSR1212_KV_VAL(ki));
1291 if (!k) {
1292 ret = CSR1212_ENOMEM;
1293 goto fail;
1294 }
1295
1296 k->refcnt = 0; /* Don't keep local reference when parsing. */
1297 break;
1298
1299 case CSR1212_KV_TYPE_CSR_OFFSET:
1300 k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
1301 CSR1212_KV_VAL(ki));
1302 if (!k) {
1303 ret = CSR1212_ENOMEM;
1304 goto fail;
1305 }
1306 k->refcnt = 0; /* Don't keep local reference when parsing. */
1307 break;
1308
1309 default:
1310 /* Compute the offset from 0xffff f000 0000. */
1311 offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
1312 if (offset == kv_pos) {
1313 /* Uh-oh. Can't have a relative offset of 0 for Leaves
1314 * or Directories. The Config ROM image is most likely
1315 * messed up, so we'll just abort here. */
1316 ret = CSR1212_EIO;
1317 goto fail;
1318 }
1319
1320 k = csr1212_find_keyval_offset(dir, offset);
1321
1322 if (k)
1323 break; /* Found it. */
1324
1325 if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY) {
1326 k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
1327 } else {
1328 k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
1329 }
1330 if (!k) {
1331 ret = CSR1212_ENOMEM;
1332 goto fail;
1333 }
1334 k->refcnt = 0; /* Don't keep local reference when parsing. */
1335 k->valid = 0; /* Contents not read yet so it's not valid. */
1336 k->offset = offset;
1337
1338 k->prev = dir;
1339 k->next = dir->next;
1340 dir->next->prev = k;
1341 dir->next = k;
1342 }
1343 ret = csr1212_attach_keyval_to_directory(dir, k);
1344
1345fail:
1346 if (ret != CSR1212_SUCCESS) {
1347 if (k)
1348 free_keyval(k);
1349 }
1350 return ret;
1351}
1352
1353
1354int csr1212_parse_keyval(struct csr1212_keyval *kv,
1355 struct csr1212_csr_rom_cache *cache)
1356{
1357 struct csr1212_keyval_img *kvi;
1358 int i;
1359 int ret = CSR1212_SUCCESS;
1360 int kvi_len;
1361
1362 kvi = (struct csr1212_keyval_img*)&cache->data[bytes_to_quads(kv->offset -
1363 cache->offset)];
1364 kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
1365
1366#if 0
1367 /* Apparently there are too many differnt wrong implementations of the
1368 * CRC algorithm that verifying them is moot. */
1369 if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
1370 (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
1371 ret = CSR1212_EINVAL;
1372 goto fail;
1373 }
1374#endif
1375
1376 switch(kv->key.type) {
1377 case CSR1212_KV_TYPE_DIRECTORY:
1378 for (i = 0; i < kvi_len; i++) {
1379 csr1212_quad_t ki = kvi->data[i];
1380
1381 /* Some devices put null entries in their unit
1382 * directories. If we come across such an entry,
1383 * then skip it. */
1384 if (ki == 0x0)
1385 continue;
1386 ret = csr1212_parse_dir_entry(kv, ki,
1387 (kv->offset +
1388 quads_to_bytes(i + 1)));
1389 }
1390 kv->value.directory.len = kvi_len;
1391 break;
1392
1393 case CSR1212_KV_TYPE_LEAF:
1394 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
1395 kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
Stefan Richter85511582005-11-07 06:31:45 -05001396 if (!kv->value.leaf.data) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 ret = CSR1212_ENOMEM;
1398 goto fail;
1399 }
1400
1401 kv->value.leaf.len = kvi_len;
1402 memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1403 }
1404 break;
1405 }
1406
1407 kv->valid = 1;
1408
1409fail:
1410 return ret;
1411}
1412
1413
1414int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1415{
1416 struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1417 struct csr1212_keyval_img *kvi = NULL;
1418 struct csr1212_csr_rom_cache *cache;
1419 int cache_index;
1420 u_int64_t addr;
1421 u_int32_t *cache_ptr;
1422 u_int16_t kv_len = 0;
1423
Ben Collins1934b8b2005-07-09 20:01:23 -04001424 if (!csr || !kv || csr->max_rom < 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 return CSR1212_EINVAL;
1426
1427 /* First find which cache the data should be in (or go in if not read
1428 * yet). */
1429 for (cache = csr->cache_head; cache; cache = cache->next) {
1430 if (kv->offset >= cache->offset &&
1431 kv->offset < (cache->offset + cache->size))
1432 break;
1433 }
1434
1435 if (!cache) {
1436 csr1212_quad_t q;
1437 u_int32_t cache_size;
1438
1439 /* Only create a new cache for Extended ROM leaves. */
1440 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1441 return CSR1212_EINVAL;
1442
1443 if (csr->ops->bus_read(csr,
1444 CSR1212_REGISTER_SPACE_BASE + kv->offset,
1445 sizeof(csr1212_quad_t), &q, csr->private)) {
1446 return CSR1212_EIO;
1447 }
1448
1449 kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
1450
1451 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1452 (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1453
1454 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1455 if (!cache)
1456 return CSR1212_ENOMEM;
1457
1458 kv->value.leaf.data = &cache->data[1];
1459 csr->cache_tail->next = cache;
1460 cache->prev = csr->cache_tail;
1461 cache->next = NULL;
1462 csr->cache_tail = cache;
1463 cache->filled_head =
Stefan Richter85511582005-11-07 06:31:45 -05001464 CSR1212_MALLOC(sizeof(*cache->filled_head));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (!cache->filled_head) {
1466 return CSR1212_ENOMEM;
1467 }
1468
1469 cache->filled_head->offset_start = 0;
1470 cache->filled_head->offset_end = sizeof(csr1212_quad_t);
1471 cache->filled_tail = cache->filled_head;
1472 cache->filled_head->next = NULL;
1473 cache->filled_head->prev = NULL;
1474 cache->data[0] = q;
1475
1476 /* Don't read the entire extended ROM now. Pieces of it will
1477 * be read when entries inside it are read. */
1478 return csr1212_parse_keyval(kv, cache);
1479 }
1480
1481 cache_index = kv->offset - cache->offset;
1482
1483 /* Now seach read portions of the cache to see if it is there. */
1484 for (cr = cache->filled_head; cr; cr = cr->next) {
1485 if (cache_index < cr->offset_start) {
Stefan Richter85511582005-11-07 06:31:45 -05001486 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 if (!newcr)
1488 return CSR1212_ENOMEM;
1489
1490 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1491 newcr->offset_end = newcr->offset_start;
1492 newcr->next = cr;
1493 newcr->prev = cr->prev;
1494 cr->prev = newcr;
1495 cr = newcr;
1496 break;
1497 } else if ((cache_index >= cr->offset_start) &&
1498 (cache_index < cr->offset_end)) {
1499 kvi = (struct csr1212_keyval_img*)
1500 (&cache->data[bytes_to_quads(cache_index)]);
1501 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1502 1);
1503 break;
1504 } else if (cache_index == cr->offset_end)
1505 break;
1506 }
1507
1508 if (!cr) {
1509 cr = cache->filled_tail;
Stefan Richter85511582005-11-07 06:31:45 -05001510 newcr = CSR1212_MALLOC(sizeof(*newcr));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 if (!newcr)
1512 return CSR1212_ENOMEM;
1513
1514 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1515 newcr->offset_end = newcr->offset_start;
1516 newcr->prev = cr;
1517 newcr->next = cr->next;
1518 cr->next = newcr;
1519 cr = newcr;
1520 cache->filled_tail = newcr;
1521 }
1522
1523 while(!kvi || cr->offset_end < cache_index + kv_len) {
1524 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1525 ~(csr->max_rom - 1))];
1526
1527 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1528 cr->offset_end) & ~(csr->max_rom - 1);
1529
1530 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1531 csr->private)) {
1532 if (csr->max_rom == 4)
1533 /* We've got problems! */
1534 return CSR1212_EIO;
1535
1536 /* Apperently the max_rom value was a lie, set it to
1537 * do quadlet reads and try again. */
1538 csr->max_rom = 4;
1539 continue;
1540 }
1541
1542 cr->offset_end += csr->max_rom - (cr->offset_end &
1543 (csr->max_rom - 1));
1544
1545 if (!kvi && (cr->offset_end > cache_index)) {
1546 kvi = (struct csr1212_keyval_img*)
1547 (&cache->data[bytes_to_quads(cache_index)]);
1548 kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1549 1);
1550 }
1551
1552 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1553 /* The Leaf or Directory claims its length extends
1554 * beyond the ConfigROM image region and thus beyond the
1555 * end of our cache region. Therefore, we abort now
1556 * rather than seg faulting later. */
1557 return CSR1212_EIO;
1558 }
1559
1560 ncr = cr->next;
1561
1562 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1563 /* consolidate region entries */
1564 ncr->offset_start = cr->offset_start;
1565
1566 if (cr->prev)
1567 cr->prev->next = cr->next;
1568 ncr->prev = cr->prev;
1569 if (cache->filled_head == cr)
1570 cache->filled_head = ncr;
1571 CSR1212_FREE(cr);
1572 cr = ncr;
1573 }
1574 }
1575
1576 return csr1212_parse_keyval(kv, cache);
1577}
1578
1579
1580
1581int csr1212_parse_csr(struct csr1212_csr *csr)
1582{
1583 static const int mr_map[] = { 4, 64, 1024, 0 };
1584 struct csr1212_dentry *dentry;
1585 int ret;
1586
Ben Collins1934b8b2005-07-09 20:01:23 -04001587 if (!csr || !csr->ops || !csr->ops->bus_read)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 return CSR1212_EINVAL;
1589
1590 ret = csr1212_parse_bus_info_block(csr);
1591 if (ret != CSR1212_SUCCESS)
1592 return ret;
1593
1594 if (!csr->ops->get_max_rom)
1595 csr->max_rom = mr_map[0]; /* default value */
Ben Collins1934b8b2005-07-09 20:01:23 -04001596 else {
1597 int i = csr->ops->get_max_rom(csr->bus_info_data,
1598 csr->private);
1599 if (i & ~0x3)
1600 return CSR1212_EINVAL;
1601 csr->max_rom = mr_map[i];
1602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
1604 csr->cache_head->layout_head = csr->root_kv;
1605 csr->cache_head->layout_tail = csr->root_kv;
1606
1607 csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1608 csr->bus_info_len;
1609
1610 csr->root_kv->valid = 0;
1611 csr->root_kv->next = csr->root_kv;
1612 csr->root_kv->prev = csr->root_kv;
Jody McIntyre5303a982005-11-22 12:17:11 -05001613 ret = _csr1212_read_keyval(csr, csr->root_kv);
1614 if (ret != CSR1212_SUCCESS)
1615 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
1617 /* Scan through the Root directory finding all extended ROM regions
1618 * and make cache regions for them */
1619 for (dentry = csr->root_kv->value.directory.dentries_head;
1620 dentry; dentry = dentry->next) {
Jody McIntyrea96074e2005-11-22 12:17:14 -05001621 if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
1622 !dentry->kv->valid) {
Jody McIntyre5303a982005-11-22 12:17:11 -05001623 ret = _csr1212_read_keyval(csr, dentry->kv);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 if (ret != CSR1212_SUCCESS)
1625 return ret;
1626 }
1627 }
1628
1629 return CSR1212_SUCCESS;
1630}