diff options
Diffstat (limited to 'scripts/mod')
-rw-r--r-- | scripts/mod/file2alias.c | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index e8c7eb16c0ea..296f17ff751b 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -889,6 +889,74 @@ static int do_isapnp_entry(const char *filename, | |||
889 | return 1; | 889 | return 1; |
890 | } | 890 | } |
891 | 891 | ||
892 | /* | ||
893 | * Append a match expression for a single masked hex digit. | ||
894 | * outp points to a pointer to the character at which to append. | ||
895 | * *outp is updated on return to point just after the appended text, | ||
896 | * to facilitate further appending. | ||
897 | */ | ||
898 | static void append_nibble_mask(char **outp, | ||
899 | unsigned int nibble, unsigned int mask) | ||
900 | { | ||
901 | char *p = *outp; | ||
902 | unsigned int i; | ||
903 | |||
904 | switch (mask) { | ||
905 | case 0: | ||
906 | *p++ = '?'; | ||
907 | break; | ||
908 | |||
909 | case 0xf: | ||
910 | p += sprintf(p, "%X", nibble); | ||
911 | break; | ||
912 | |||
913 | default: | ||
914 | /* | ||
915 | * Dumbly emit a match pattern for all possible matching | ||
916 | * digits. This could be improved in some cases using ranges, | ||
917 | * but it has the advantage of being trivially correct, and is | ||
918 | * often optimal. | ||
919 | */ | ||
920 | *p++ = '['; | ||
921 | for (i = 0; i < 0x10; i++) | ||
922 | if ((i & mask) == nibble) | ||
923 | p += sprintf(p, "%X", i); | ||
924 | *p++ = ']'; | ||
925 | } | ||
926 | |||
927 | /* Ensure that the string remains NUL-terminated: */ | ||
928 | *p = '\0'; | ||
929 | |||
930 | /* Advance the caller's end-of-string pointer: */ | ||
931 | *outp = p; | ||
932 | } | ||
933 | |||
934 | /* | ||
935 | * looks like: "amba:dN" | ||
936 | * | ||
937 | * N is exactly 8 digits, where each is an upper-case hex digit, or | ||
938 | * a ? or [] pattern matching exactly one digit. | ||
939 | */ | ||
940 | static int do_amba_entry(const char *filename, | ||
941 | struct amba_id *id, char *alias) | ||
942 | { | ||
943 | unsigned int digit; | ||
944 | char *p = alias; | ||
945 | |||
946 | if ((id->id & id->mask) != id->id) | ||
947 | fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " | ||
948 | "id=0x%08X, mask=0x%08X. Please fix this driver.\n", | ||
949 | filename, id->id, id->mask); | ||
950 | |||
951 | p += sprintf(alias, "amba:d"); | ||
952 | for (digit = 0; digit < 8; digit++) | ||
953 | append_nibble_mask(&p, | ||
954 | (id->id >> (4 * (7 - digit))) & 0xf, | ||
955 | (id->mask >> (4 * (7 - digit))) & 0xf); | ||
956 | |||
957 | return 1; | ||
958 | } | ||
959 | |||
892 | /* Ignore any prefix, eg. some architectures prepend _ */ | 960 | /* Ignore any prefix, eg. some architectures prepend _ */ |
893 | static inline int sym_is(const char *symbol, const char *name) | 961 | static inline int sym_is(const char *symbol, const char *name) |
894 | { | 962 | { |
@@ -1060,6 +1128,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
1060 | do_table(symval, sym->st_size, | 1128 | do_table(symval, sym->st_size, |
1061 | sizeof(struct isapnp_device_id), "isa", | 1129 | sizeof(struct isapnp_device_id), "isa", |
1062 | do_isapnp_entry, mod); | 1130 | do_isapnp_entry, mod); |
1131 | else if (sym_is(symname, "__mod_amba_device_table")) | ||
1132 | do_table(symval, sym->st_size, | ||
1133 | sizeof(struct amba_id), "amba", | ||
1134 | do_amba_entry, mod); | ||
1063 | free(zeros); | 1135 | free(zeros); |
1064 | } | 1136 | } |
1065 | 1137 | ||