root/trunk/libfreebob/src/csr1212.c

Revision 125, 42.2 kB (checked in by wagi, 18 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
3  *
4  * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
5  *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  *    1. Redistributions of source code must retain the above copyright notice,
11  *       this list of conditions and the following disclaimer.
12  *    2. Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in the
14  *       documentation and/or other materials provided with the distribution.
15  *    3. The name of the author may not be used to endorse or promote products
16  *       derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30
31 /* TODO List:
32  * - Verify interface consistency: i.e., public functions that take a size
33  *   parameter expect size to be in bytes.
34  * - Convenience functions for reading a block of data from a given offset.
35  */
36
37 #ifndef __KERNEL__
38 #include <string.h>
39 #endif
40
41 #include "csr1212.h"
42
43
44 /* Permitted key type for each key id */
45 #define __I (1 << CSR1212_KV_TYPE_IMMEDIATE)
46 #define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET)
47 #define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
48 #define __L (1 << CSR1212_KV_TYPE_LEAF)
49 static 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
88 static 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
97 static 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. */
120 static 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
140 static 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
154 static 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 */
168 struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
169                                        size_t bus_info_size, void *private_data)
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_data = private_data;
200         csr->cache_tail = csr->cache_head;
201
202         return csr;
203 }
204
205
206
207 void csr1212_init_local_csr(struct csr1212_csr *csr,
208                             const u_int32_t *bus_info_data, int max_rom)
209 {
210         static const int mr_map[] = { 4, 64, 1024, 0 };
211
212 #ifdef __KERNEL__
213         BUG_ON(max_rom & ~0x3);
214         csr->max_rom = mr_map[max_rom];
215 #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
221         memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
222 }
223
224
225 static 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
249 struct 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
261 struct 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
288 struct 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
302 struct 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
317 int 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
356 int 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
385 struct 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
414 struct 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
443 struct 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
464 struct 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
493 static 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
522 struct 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
532 struct 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;
544         int palette_size;
545         int pixel_size = (hscan * vscan + 3) & ~0x3;
546
547         if (!pixels || (!palette && palette_depth) ||
548             (palette_depth & ~0x3) || (color_space & ~0xf))
549                 return NULL;
550
551         palette_size = pd[palette_depth] * cs[color_space];
552
553         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
575 struct 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
592 static 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
610 struct 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
650 void 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
678 void 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. */
693 void _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
742 void 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
769 static 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
774         if (!csr || !csr->ops || !csr->ops->allocate_addr_range ||
775             !csr->ops->release_addr || csr->max_rom < 1)
776                 return CSR1212_EINVAL;
777
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_data);
782         if (csr_addr == ~0ULL) {
783                 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_data);
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_data);
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_data);
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_data);
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
821 static 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
842 static 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
911 size_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
934 struct 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
980 static 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
1045 void 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
1089 int 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. */
1159                         if (csr->max_rom < 1)
1160                                 return CSR1212_EINVAL;
1161                         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
1198 int 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
1218 static 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_data);
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_data);
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
1264         cr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1265         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
1279 static 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
1345 fail:
1346         if (ret != CSR1212_SUCCESS) {
1347                 if (k)
1348                         free_keyval(k);
1349         }
1350         return ret;
1351 }
1352
1353
1354 int 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));
1396                         if (!kv->value.leaf.data)
1397                         {
1398                                 ret = CSR1212_ENOMEM;
1399                                 goto fail;
1400                         }
1401
1402                         kv->value.leaf.len = kvi_len;
1403                         memcpy(kv->value.leaf.data, kvi->data, quads_to_bytes(kvi_len));
1404                 }
1405                 break;
1406         }
1407
1408         kv->valid = 1;
1409
1410 fail:
1411         return ret;
1412 }
1413
1414
1415 int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
1416 {
1417         struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
1418         struct csr1212_keyval_img *kvi = NULL;
1419         struct csr1212_csr_rom_cache *cache;
1420         int cache_index;
1421         u_int64_t addr;
1422         u_int32_t *cache_ptr;
1423         u_int16_t kv_len = 0;
1424
1425         if (!csr || !kv || csr->max_rom < 1)
1426                 return CSR1212_EINVAL;
1427
1428         /* First find which cache the data should be in (or go in if not read
1429          * yet). */
1430         for (cache = csr->cache_head; cache; cache = cache->next) {
1431                 if (kv->offset >= cache->offset &&
1432                     kv->offset < (cache->offset + cache->size))
1433                         break;
1434         }
1435
1436         if (!cache) {
1437                 csr1212_quad_t q;
1438                 u_int32_t cache_size;
1439
1440                 /* Only create a new cache for Extended ROM leaves. */
1441                 if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
1442                         return CSR1212_EINVAL;
1443
1444                 if (csr->ops->bus_read(csr,
1445                                        CSR1212_REGISTER_SPACE_BASE + kv->offset,
1446                                        sizeof(csr1212_quad_t), &q, csr->private_data)) {
1447                         return CSR1212_EIO;
1448                 }
1449
1450                 kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
1451
1452                 cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
1453                               (csr->max_rom - 1)) & ~(csr->max_rom - 1);
1454
1455                 cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
1456                 if (!cache)
1457                         return CSR1212_ENOMEM;
1458
1459                 kv->value.leaf.data = &cache->data[1];
1460                 csr->cache_tail->next = cache;
1461                 cache->prev = csr->cache_tail;
1462                 cache->next = NULL;
1463                 csr->cache_tail = cache;
1464                 cache->filled_head =
1465                         CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1466                 if (!cache->filled_head) {
1467                         return CSR1212_ENOMEM;
1468                 }
1469
1470                 cache->filled_head->offset_start = 0;
1471                 cache->filled_head->offset_end = sizeof(csr1212_quad_t);
1472                 cache->filled_tail = cache->filled_head;
1473                 cache->filled_head->next = NULL;
1474                 cache->filled_head->prev = NULL;
1475                 cache->data[0] = q;
1476
1477                 /* Don't read the entire extended ROM now.  Pieces of it will
1478                  * be read when entries inside it are read. */
1479                 return csr1212_parse_keyval(kv, cache);
1480         }
1481
1482         cache_index = kv->offset - cache->offset;
1483
1484         /* Now seach read portions of the cache to see if it is there. */
1485         for (cr = cache->filled_head; cr; cr = cr->next) {
1486                 if (cache_index < cr->offset_start) {
1487                         newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1488                         if (!newcr)
1489                                 return CSR1212_ENOMEM;
1490
1491                         newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1492                         newcr->offset_end = newcr->offset_start;
1493                         newcr->next = cr;
1494                         newcr->prev = cr->prev;
1495                         cr->prev = newcr;
1496                         cr = newcr;
1497                         break;
1498                 } else if ((cache_index >= cr->offset_start) &&
1499                            (cache_index < cr->offset_end)) {
1500                         kvi = (struct csr1212_keyval_img*)
1501                                 (&cache->data[bytes_to_quads(cache_index)]);
1502                         kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1503                                                 1);
1504                         break;
1505                 } else if (cache_index == cr->offset_end)
1506                         break;
1507         }
1508
1509         if (!cr) {
1510                 cr = cache->filled_tail;
1511                 newcr = CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
1512                 if (!newcr)
1513                         return CSR1212_ENOMEM;
1514
1515                 newcr->offset_start = cache_index & ~(csr->max_rom - 1);
1516                 newcr->offset_end = newcr->offset_start;
1517                 newcr->prev = cr;
1518                 newcr->next = cr->next;
1519                 cr->next = newcr;
1520                 cr = newcr;
1521                 cache->filled_tail = newcr;
1522         }
1523
1524         while(!kvi || cr->offset_end < cache_index + kv_len) {
1525                 cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
1526                                                         ~(csr->max_rom - 1))];
1527
1528                 addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
1529                         cr->offset_end) & ~(csr->max_rom - 1);
1530
1531                 if (csr->ops->bus_read(csr, addr, csr->max_rom, cache_ptr,
1532                                        csr->private_data)) {
1533                         if (csr->max_rom == 4)
1534                                 /* We've got problems! */
1535                                 return CSR1212_EIO;
1536
1537                         /* Apperently the max_rom value was a lie, set it to
1538                          * do quadlet reads and try again. */
1539                         csr->max_rom = 4;
1540                         continue;
1541                 }
1542
1543                 cr->offset_end += csr->max_rom - (cr->offset_end &
1544                                                   (csr->max_rom - 1));
1545
1546                 if (!kvi && (cr->offset_end > cache_index)) {
1547                         kvi = (struct csr1212_keyval_img*)
1548                                 (&cache->data[bytes_to_quads(cache_index)]);
1549                         kv_len = quads_to_bytes(CSR1212_BE16_TO_CPU(kvi->length) +
1550                                                 1);
1551                 }
1552
1553                 if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
1554                         /* The Leaf or Directory claims its length extends
1555                          * beyond the ConfigROM image region and thus beyond the
1556                          * end of our cache region.  Therefore, we abort now
1557                          * rather than seg faulting later. */
1558                         return CSR1212_EIO;
1559                 }
1560
1561                 ncr = cr->next;
1562
1563                 if (ncr && (cr->offset_end >= ncr->offset_start)) {
1564                         /* consolidate region entries */
1565                         ncr->offset_start = cr->offset_start;
1566
1567                         if (cr->prev)
1568                                 cr->prev->next = cr->next;
1569                         ncr->prev = cr->prev;
1570                         if (cache->filled_head == cr)
1571                                 cache->filled_head = ncr;
1572                         CSR1212_FREE(cr);
1573                         cr = ncr;
1574                 }
1575         }
1576
1577         return csr1212_parse_keyval(kv, cache);
1578 }
1579
1580
1581
1582 int csr1212_parse_csr(struct csr1212_csr *csr)
1583 {
1584         static const int mr_map[] = { 4, 64, 1024, 0 };
1585         struct csr1212_dentry *dentry;
1586         int ret;
1587
1588         if (!csr || !csr->ops || !csr->ops->bus_read)
1589                 return CSR1212_EINVAL;
1590
1591         ret = csr1212_parse_bus_info_block(csr);
1592         if (ret != CSR1212_SUCCESS)
1593                 return ret;
1594
1595         if (!csr->ops->get_max_rom)
1596                 csr->max_rom = mr_map[0];       /* default value */
1597         else {
1598                 int i = csr->ops->get_max_rom(csr->bus_info_data,
1599                                               csr->private_data);
1600                 if (i & ~0x3)
1601                         return CSR1212_EINVAL;
1602                 csr->max_rom = mr_map[i];
1603         }
1604
1605         csr->cache_head->layout_head = csr->root_kv;
1606         csr->cache_head->layout_tail = csr->root_kv;
1607
1608         csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
1609                 csr->bus_info_len;
1610
1611         csr->root_kv->valid = 0;
1612         csr->root_kv->next = csr->root_kv;
1613         csr->root_kv->prev = csr->root_kv;
1614         csr1212_get_keyval(csr, csr->root_kv);
1615
1616         /* Scan through the Root directory finding all extended ROM regions
1617          * and make cache regions for them */
1618         for (dentry = csr->root_kv->value.directory.dentries_head;
1619              dentry; dentry = dentry->next) {
1620                 if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
1621                         csr1212_get_keyval(csr, dentry->kv);
1622
1623                         if (ret != CSR1212_SUCCESS)
1624                                 return ret;
1625                 }
1626         }
1627
1628         return CSR1212_SUCCESS;
1629 }
Note: See TracBrowser for help on using the browser.