diff options
Diffstat (limited to 'drivers/ieee1394/csr1212.c')
-rw-r--r-- | drivers/ieee1394/csr1212.c | 311 |
1 files changed, 87 insertions, 224 deletions
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index c28f639823d2..ff5a01ecfcaa 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c | |||
@@ -31,7 +31,6 @@ | |||
31 | /* TODO List: | 31 | /* TODO List: |
32 | * - Verify interface consistency: i.e., public functions that take a size | 32 | * - Verify interface consistency: i.e., public functions that take a size |
33 | * parameter expect size to be in bytes. | 33 | * parameter expect size to be in bytes. |
34 | * - Convenience functions for reading a block of data from a given offset. | ||
35 | */ | 34 | */ |
36 | 35 | ||
37 | #ifndef __KERNEL__ | 36 | #ifndef __KERNEL__ |
@@ -85,7 +84,7 @@ static const u_int8_t csr1212_key_id_type_map[0x30] = { | |||
85 | #define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t)) | 84 | #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)) | 85 | #define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t)) |
87 | 86 | ||
88 | static inline void free_keyval(struct csr1212_keyval *kv) | 87 | static void free_keyval(struct csr1212_keyval *kv) |
89 | { | 88 | { |
90 | if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && | 89 | if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && |
91 | (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) | 90 | (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) |
@@ -137,8 +136,8 @@ static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length) | |||
137 | } | 136 | } |
138 | #endif | 137 | #endif |
139 | 138 | ||
140 | static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir, | 139 | static struct csr1212_dentry * |
141 | struct csr1212_keyval *kv) | 140 | csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv) |
142 | { | 141 | { |
143 | struct csr1212_dentry *pos; | 142 | struct csr1212_dentry *pos; |
144 | 143 | ||
@@ -150,9 +149,8 @@ static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval * | |||
150 | return NULL; | 149 | return NULL; |
151 | } | 150 | } |
152 | 151 | ||
153 | 152 | static struct csr1212_keyval * | |
154 | static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, | 153 | csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u_int32_t offset) |
155 | u_int32_t offset) | ||
156 | { | 154 | { |
157 | struct csr1212_keyval *kv; | 155 | struct csr1212_keyval *kv; |
158 | 156 | ||
@@ -165,6 +163,7 @@ static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_k | |||
165 | 163 | ||
166 | 164 | ||
167 | /* Creation Routines */ | 165 | /* Creation Routines */ |
166 | |||
168 | struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, | 167 | struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, |
169 | size_t bus_info_size, void *private) | 168 | size_t bus_info_size, void *private) |
170 | { | 169 | { |
@@ -202,8 +201,6 @@ struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, | |||
202 | return csr; | 201 | return csr; |
203 | } | 202 | } |
204 | 203 | ||
205 | |||
206 | |||
207 | void csr1212_init_local_csr(struct csr1212_csr *csr, | 204 | void csr1212_init_local_csr(struct csr1212_csr *csr, |
208 | const u_int32_t *bus_info_data, int max_rom) | 205 | const u_int32_t *bus_info_data, int max_rom) |
209 | { | 206 | { |
@@ -221,7 +218,6 @@ void csr1212_init_local_csr(struct csr1212_csr *csr, | |||
221 | memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); | 218 | memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); |
222 | } | 219 | } |
223 | 220 | ||
224 | |||
225 | static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) | 221 | static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) |
226 | { | 222 | { |
227 | struct csr1212_keyval *kv; | 223 | struct csr1212_keyval *kv; |
@@ -258,7 +254,8 @@ struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value) | |||
258 | return kv; | 254 | return kv; |
259 | } | 255 | } |
260 | 256 | ||
261 | struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len) | 257 | static struct csr1212_keyval * |
258 | csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len) | ||
262 | { | 259 | { |
263 | struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); | 260 | struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); |
264 | 261 | ||
@@ -285,7 +282,8 @@ struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t d | |||
285 | return kv; | 282 | return kv; |
286 | } | 283 | } |
287 | 284 | ||
288 | struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset) | 285 | static struct csr1212_keyval * |
286 | csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset) | ||
289 | { | 287 | { |
290 | struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); | 288 | struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); |
291 | 289 | ||
@@ -382,66 +380,22 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, | |||
382 | return CSR1212_SUCCESS; | 380 | return CSR1212_SUCCESS; |
383 | } | 381 | } |
384 | 382 | ||
385 | struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key, | 383 | #define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ |
386 | u_int32_t value) | 384 | (&((kv)->value.leaf.data[1])) |
387 | { | 385 | |
388 | struct csr1212_keyval *kvs, *kvk, *kvv; | 386 | #define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \ |
389 | 387 | ((kv)->value.leaf.data[0] = \ | |
390 | kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); | 388 | CSR1212_CPU_TO_BE32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \ |
391 | kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); | 389 | ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT))) |
392 | kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value); | 390 | #define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \ |
393 | 391 | ((kv)->value.leaf.data[0] = \ | |
394 | if (!kvs || !kvk || !kvv) { | 392 | CSR1212_CPU_TO_BE32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \ |
395 | if (kvs) | 393 | CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \ |
396 | free_keyval(kvs); | 394 | ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK))) |
397 | if (kvk) | 395 | |
398 | free_keyval(kvk); | 396 | static struct csr1212_keyval * |
399 | if (kvv) | 397 | csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id, |
400 | free_keyval(kvv); | 398 | const void *data, size_t data_len) |
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 | { | 399 | { |
446 | struct csr1212_keyval *kv; | 400 | struct csr1212_keyval *kv; |
447 | 401 | ||
@@ -460,12 +414,35 @@ struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t spe | |||
460 | return kv; | 414 | return kv; |
461 | } | 415 | } |
462 | 416 | ||
463 | 417 | #define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, width) \ | |
464 | struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, | 418 | ((kv)->value.leaf.data[1] = \ |
465 | u_int16_t cset, | 419 | ((kv)->value.leaf.data[1] & \ |
466 | u_int16_t language, | 420 | CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK << \ |
467 | const void *data, | 421 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT))) | \ |
468 | size_t data_len) | 422 | CSR1212_CPU_TO_BE32(((width) & \ |
423 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK) << \ | ||
424 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)) | ||
425 | |||
426 | #define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, char_set) \ | ||
427 | ((kv)->value.leaf.data[1] = \ | ||
428 | ((kv)->value.leaf.data[1] & \ | ||
429 | CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK << \ | ||
430 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT))) | \ | ||
431 | CSR1212_CPU_TO_BE32(((char_set) & \ | ||
432 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK) << \ | ||
433 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT)) | ||
434 | |||
435 | #define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language) \ | ||
436 | ((kv)->value.leaf.data[1] = \ | ||
437 | ((kv)->value.leaf.data[1] & \ | ||
438 | CSR1212_CPU_TO_BE32(~(CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | \ | ||
439 | CSR1212_CPU_TO_BE32(((language) & \ | ||
440 | CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK))) | ||
441 | |||
442 | static struct csr1212_keyval * | ||
443 | csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, u_int16_t cset, | ||
444 | u_int16_t language, const void *data, | ||
445 | size_t data_len) | ||
469 | { | 446 | { |
470 | struct csr1212_keyval *kv; | 447 | struct csr1212_keyval *kv; |
471 | char *lstr; | 448 | char *lstr; |
@@ -529,121 +506,6 @@ struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s) | |||
529 | return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s)); | 506 | return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s)); |
530 | } | 507 | } |
531 | 508 | ||
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 | 509 | ||
648 | /* Destruction Routines */ | 510 | /* Destruction Routines */ |
649 | 511 | ||
@@ -674,17 +536,6 @@ void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir, | |||
674 | csr1212_release_keyval(kv); | 536 | csr1212_release_keyval(kv); |
675 | } | 537 | } |
676 | 538 | ||
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 | 539 | /* 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 | 540 | * 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 | 541 | * will be destroyed as well if their respective refcnts are 0. By means of |
@@ -738,7 +589,6 @@ void _csr1212_destroy_keyval(struct csr1212_keyval *kv) | |||
738 | } | 589 | } |
739 | } | 590 | } |
740 | 591 | ||
741 | |||
742 | void csr1212_destroy_csr(struct csr1212_csr *csr) | 592 | void csr1212_destroy_csr(struct csr1212_csr *csr) |
743 | { | 593 | { |
744 | struct csr1212_csr_rom_cache *c, *oc; | 594 | struct csr1212_csr_rom_cache *c, *oc; |
@@ -763,7 +613,6 @@ void csr1212_destroy_csr(struct csr1212_csr *csr) | |||
763 | } | 613 | } |
764 | 614 | ||
765 | 615 | ||
766 | |||
767 | /* CSR Image Creation */ | 616 | /* CSR Image Creation */ |
768 | 617 | ||
769 | static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) | 618 | static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) |
@@ -818,8 +667,8 @@ static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize) | |||
818 | return CSR1212_SUCCESS; | 667 | return CSR1212_SUCCESS; |
819 | } | 668 | } |
820 | 669 | ||
821 | static inline void csr1212_remove_cache(struct csr1212_csr *csr, | 670 | static void csr1212_remove_cache(struct csr1212_csr *csr, |
822 | struct csr1212_csr_rom_cache *cache) | 671 | struct csr1212_csr_rom_cache *cache) |
823 | { | 672 | { |
824 | if (csr->cache_head == cache) | 673 | if (csr->cache_head == cache) |
825 | csr->cache_head = cache->next; | 674 | csr->cache_head = cache->next; |
@@ -908,7 +757,7 @@ static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir, | |||
908 | return num_entries; | 757 | return num_entries; |
909 | } | 758 | } |
910 | 759 | ||
911 | size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) | 760 | static size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) |
912 | { | 761 | { |
913 | struct csr1212_keyval *ltail = kv; | 762 | struct csr1212_keyval *ltail = kv; |
914 | size_t agg_size = 0; | 763 | size_t agg_size = 0; |
@@ -931,9 +780,9 @@ size_t csr1212_generate_layout_order(struct csr1212_keyval *kv) | |||
931 | return quads_to_bytes(agg_size); | 780 | return quads_to_bytes(agg_size); |
932 | } | 781 | } |
933 | 782 | ||
934 | struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, | 783 | static struct csr1212_keyval * |
935 | struct csr1212_keyval *start_kv, | 784 | csr1212_generate_positions(struct csr1212_csr_rom_cache *cache, |
936 | int start_pos) | 785 | struct csr1212_keyval *start_kv, int start_pos) |
937 | { | 786 | { |
938 | struct csr1212_keyval *kv = start_kv; | 787 | struct csr1212_keyval *kv = start_kv; |
939 | struct csr1212_keyval *okv = start_kv; | 788 | struct csr1212_keyval *okv = start_kv; |
@@ -977,8 +826,13 @@ struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache * | |||
977 | return kv; | 826 | return kv; |
978 | } | 827 | } |
979 | 828 | ||
980 | static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir, | 829 | #define CSR1212_KV_KEY_SHIFT 24 |
981 | u_int32_t *data_buffer) | 830 | #define CSR1212_KV_KEY_TYPE_SHIFT 6 |
831 | #define CSR1212_KV_KEY_ID_MASK 0x3f | ||
832 | #define CSR1212_KV_KEY_TYPE_MASK 0x3 /* after shift */ | ||
833 | |||
834 | static void | ||
835 | csr1212_generate_tree_subdir(struct csr1212_keyval *dir, u_int32_t *data_buffer) | ||
982 | { | 836 | { |
983 | struct csr1212_dentry *dentry; | 837 | struct csr1212_dentry *dentry; |
984 | struct csr1212_keyval *last_extkey_spec = NULL; | 838 | struct csr1212_keyval *last_extkey_spec = NULL; |
@@ -1042,7 +896,15 @@ static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir, | |||
1042 | } | 896 | } |
1043 | } | 897 | } |
1044 | 898 | ||
1045 | void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) | 899 | struct csr1212_keyval_img { |
900 | u_int16_t length; | ||
901 | u_int16_t crc; | ||
902 | |||
903 | /* Must be last */ | ||
904 | csr1212_quad_t data[0]; /* older gcc can't handle [] which is standard */ | ||
905 | }; | ||
906 | |||
907 | static void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) | ||
1046 | { | 908 | { |
1047 | struct csr1212_keyval *kv, *nkv; | 909 | struct csr1212_keyval *kv, *nkv; |
1048 | struct csr1212_keyval_img *kvi; | 910 | struct csr1212_keyval_img *kvi; |
@@ -1086,6 +948,8 @@ void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache) | |||
1086 | } | 948 | } |
1087 | } | 949 | } |
1088 | 950 | ||
951 | #define CSR1212_EXTENDED_ROM_SIZE (0x10000 * sizeof(u_int32_t)) | ||
952 | |||
1089 | int csr1212_generate_csr_image(struct csr1212_csr *csr) | 953 | int csr1212_generate_csr_image(struct csr1212_csr *csr) |
1090 | { | 954 | { |
1091 | struct csr1212_bus_info_block_img *bi; | 955 | struct csr1212_bus_info_block_img *bi; |
@@ -1212,7 +1076,6 @@ int csr1212_read(struct csr1212_csr *csr, u_int32_t offset, void *buffer, u_int3 | |||
1212 | } | 1076 | } |
1213 | 1077 | ||
1214 | 1078 | ||
1215 | |||
1216 | /* Parse a chunk of data as a Config ROM */ | 1079 | /* Parse a chunk of data as a Config ROM */ |
1217 | 1080 | ||
1218 | static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | 1081 | static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) |
@@ -1279,6 +1142,12 @@ static int csr1212_parse_bus_info_block(struct csr1212_csr *csr) | |||
1279 | return CSR1212_SUCCESS; | 1142 | return CSR1212_SUCCESS; |
1280 | } | 1143 | } |
1281 | 1144 | ||
1145 | #define CSR1212_KV_KEY(q) (CSR1212_BE32_TO_CPU(q) >> CSR1212_KV_KEY_SHIFT) | ||
1146 | #define CSR1212_KV_KEY_TYPE(q) (CSR1212_KV_KEY(q) >> CSR1212_KV_KEY_TYPE_SHIFT) | ||
1147 | #define CSR1212_KV_KEY_ID(q) (CSR1212_KV_KEY(q) & CSR1212_KV_KEY_ID_MASK) | ||
1148 | #define CSR1212_KV_VAL_MASK 0xffffff | ||
1149 | #define CSR1212_KV_VAL(q) (CSR1212_BE32_TO_CPU(q) & CSR1212_KV_VAL_MASK) | ||
1150 | |||
1282 | static int csr1212_parse_dir_entry(struct csr1212_keyval *dir, | 1151 | static int csr1212_parse_dir_entry(struct csr1212_keyval *dir, |
1283 | csr1212_quad_t ki, | 1152 | csr1212_quad_t ki, |
1284 | u_int32_t kv_pos) | 1153 | u_int32_t kv_pos) |
@@ -1346,14 +1215,11 @@ static int csr1212_parse_dir_entry(struct csr1212_keyval *dir, | |||
1346 | ret = csr1212_attach_keyval_to_directory(dir, k); | 1215 | ret = csr1212_attach_keyval_to_directory(dir, k); |
1347 | 1216 | ||
1348 | fail: | 1217 | fail: |
1349 | if (ret != CSR1212_SUCCESS) { | 1218 | if (ret != CSR1212_SUCCESS && k != NULL) |
1350 | if (k) | 1219 | free_keyval(k); |
1351 | free_keyval(k); | ||
1352 | } | ||
1353 | return ret; | 1220 | return ret; |
1354 | } | 1221 | } |
1355 | 1222 | ||
1356 | |||
1357 | int csr1212_parse_keyval(struct csr1212_keyval *kv, | 1223 | int csr1212_parse_keyval(struct csr1212_keyval *kv, |
1358 | struct csr1212_csr_rom_cache *cache) | 1224 | struct csr1212_csr_rom_cache *cache) |
1359 | { | 1225 | { |
@@ -1413,7 +1279,6 @@ fail: | |||
1413 | return ret; | 1279 | return ret; |
1414 | } | 1280 | } |
1415 | 1281 | ||
1416 | |||
1417 | int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | 1282 | int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) |
1418 | { | 1283 | { |
1419 | struct csr1212_cache_region *cr, *ncr, *newcr = NULL; | 1284 | struct csr1212_cache_region *cr, *ncr, *newcr = NULL; |
@@ -1579,8 +1444,6 @@ int _csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv) | |||
1579 | return csr1212_parse_keyval(kv, cache); | 1444 | return csr1212_parse_keyval(kv, cache); |
1580 | } | 1445 | } |
1581 | 1446 | ||
1582 | |||
1583 | |||
1584 | int csr1212_parse_csr(struct csr1212_csr *csr) | 1447 | int csr1212_parse_csr(struct csr1212_csr *csr) |
1585 | { | 1448 | { |
1586 | static const int mr_map[] = { 4, 64, 1024, 0 }; | 1449 | static const int mr_map[] = { 4, 64, 1024, 0 }; |