diff options
Diffstat (limited to 'drivers/ieee1394/config_roms.c')
-rw-r--r-- | drivers/ieee1394/config_roms.c | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c new file mode 100644 index 000000000000..1017fd717248 --- /dev/null +++ b/drivers/ieee1394/config_roms.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * IEEE 1394 for Linux | ||
3 | * | ||
4 | * ConfigROM entries | ||
5 | * | ||
6 | * Copyright (C) 2004 Ben Collins | ||
7 | * | ||
8 | * This code is licensed under the GPL. See the file COPYING in the root | ||
9 | * directory of the kernel sources for details. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/types.h> | ||
14 | |||
15 | #include "csr1212.h" | ||
16 | #include "ieee1394.h" | ||
17 | #include "ieee1394_types.h" | ||
18 | #include "hosts.h" | ||
19 | #include "ieee1394_core.h" | ||
20 | #include "highlevel.h" | ||
21 | #include "csr.h" | ||
22 | #include "config_roms.h" | ||
23 | |||
24 | struct hpsb_config_rom_entry { | ||
25 | const char *name; | ||
26 | |||
27 | /* Base initialization, called at module load */ | ||
28 | int (*init)(void); | ||
29 | |||
30 | /* Add entry to specified host */ | ||
31 | int (*add)(struct hpsb_host *host); | ||
32 | |||
33 | /* Remove entry from specified host */ | ||
34 | void (*remove)(struct hpsb_host *host); | ||
35 | |||
36 | /* Cleanup called at module exit */ | ||
37 | void (*cleanup)(void); | ||
38 | |||
39 | /* The flag added to host->config_roms */ | ||
40 | unsigned int flag; | ||
41 | }; | ||
42 | |||
43 | |||
44 | int hpsb_default_host_entry(struct hpsb_host *host) | ||
45 | { | ||
46 | struct csr1212_keyval *root; | ||
47 | struct csr1212_keyval *vend_id = NULL; | ||
48 | struct csr1212_keyval *text = NULL; | ||
49 | char csr_name[128]; | ||
50 | int ret; | ||
51 | |||
52 | sprintf(csr_name, "Linux - %s", host->driver->name); | ||
53 | root = host->csr.rom->root_kv; | ||
54 | |||
55 | vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8); | ||
56 | text = csr1212_new_string_descriptor_leaf(csr_name); | ||
57 | |||
58 | if (!vend_id || !text) { | ||
59 | if (vend_id) | ||
60 | csr1212_release_keyval(vend_id); | ||
61 | if (text) | ||
62 | csr1212_release_keyval(text); | ||
63 | csr1212_destroy_csr(host->csr.rom); | ||
64 | return -ENOMEM; | ||
65 | } | ||
66 | |||
67 | ret = csr1212_associate_keyval(vend_id, text); | ||
68 | csr1212_release_keyval(text); | ||
69 | ret |= csr1212_attach_keyval_to_directory(root, vend_id); | ||
70 | csr1212_release_keyval(vend_id); | ||
71 | if (ret != CSR1212_SUCCESS) { | ||
72 | csr1212_destroy_csr(host->csr.rom); | ||
73 | return -ENOMEM; | ||
74 | } | ||
75 | |||
76 | host->update_config_rom = 1; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | |||
82 | #ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 | ||
83 | #include "eth1394.h" | ||
84 | |||
85 | static struct csr1212_keyval *ip1394_ud; | ||
86 | |||
87 | static int config_rom_ip1394_init(void) | ||
88 | { | ||
89 | struct csr1212_keyval *spec_id = NULL; | ||
90 | struct csr1212_keyval *spec_desc = NULL; | ||
91 | struct csr1212_keyval *ver = NULL; | ||
92 | struct csr1212_keyval *ver_desc = NULL; | ||
93 | int ret = -ENOMEM; | ||
94 | |||
95 | ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT); | ||
96 | |||
97 | spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID, | ||
98 | ETHER1394_GASP_SPECIFIER_ID); | ||
99 | spec_desc = csr1212_new_string_descriptor_leaf("IANA"); | ||
100 | ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION, | ||
101 | ETHER1394_GASP_VERSION); | ||
102 | ver_desc = csr1212_new_string_descriptor_leaf("IPv4"); | ||
103 | |||
104 | if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc) | ||
105 | goto ip1394_fail; | ||
106 | |||
107 | if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS && | ||
108 | csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS && | ||
109 | csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS && | ||
110 | csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS) | ||
111 | ret = 0; | ||
112 | |||
113 | ip1394_fail: | ||
114 | if (ret && ip1394_ud) { | ||
115 | csr1212_release_keyval(ip1394_ud); | ||
116 | ip1394_ud = NULL; | ||
117 | } | ||
118 | |||
119 | if (spec_id) | ||
120 | csr1212_release_keyval(spec_id); | ||
121 | if (spec_desc) | ||
122 | csr1212_release_keyval(spec_desc); | ||
123 | if (ver) | ||
124 | csr1212_release_keyval(ver); | ||
125 | if (ver_desc) | ||
126 | csr1212_release_keyval(ver_desc); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static void config_rom_ip1394_cleanup(void) | ||
132 | { | ||
133 | if (ip1394_ud) { | ||
134 | csr1212_release_keyval(ip1394_ud); | ||
135 | ip1394_ud = NULL; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int config_rom_ip1394_add(struct hpsb_host *host) | ||
140 | { | ||
141 | if (!ip1394_ud) | ||
142 | return -ENODEV; | ||
143 | |||
144 | if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv, | ||
145 | ip1394_ud) != CSR1212_SUCCESS) | ||
146 | return -ENOMEM; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static void config_rom_ip1394_remove(struct hpsb_host *host) | ||
152 | { | ||
153 | csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud); | ||
154 | } | ||
155 | |||
156 | static struct hpsb_config_rom_entry ip1394_entry = { | ||
157 | .name = "ip1394", | ||
158 | .init = config_rom_ip1394_init, | ||
159 | .add = config_rom_ip1394_add, | ||
160 | .remove = config_rom_ip1394_remove, | ||
161 | .cleanup = config_rom_ip1394_cleanup, | ||
162 | .flag = HPSB_CONFIG_ROM_ENTRY_IP1394, | ||
163 | }; | ||
164 | #endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */ | ||
165 | |||
166 | |||
167 | static struct hpsb_config_rom_entry *const config_rom_entries[] = { | ||
168 | #ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 | ||
169 | &ip1394_entry, | ||
170 | #endif | ||
171 | NULL, | ||
172 | }; | ||
173 | |||
174 | |||
175 | int hpsb_init_config_roms(void) | ||
176 | { | ||
177 | int i, error = 0; | ||
178 | |||
179 | for (i = 0; config_rom_entries[i]; i++) { | ||
180 | if (!config_rom_entries[i]->init) | ||
181 | continue; | ||
182 | |||
183 | if (config_rom_entries[i]->init()) { | ||
184 | HPSB_ERR("Failed to initialize config rom entry `%s'", | ||
185 | config_rom_entries[i]->name); | ||
186 | error = -1; | ||
187 | } else | ||
188 | HPSB_DEBUG("Initialized config rom entry `%s'", | ||
189 | config_rom_entries[i]->name); | ||
190 | } | ||
191 | |||
192 | return error; | ||
193 | } | ||
194 | |||
195 | void hpsb_cleanup_config_roms(void) | ||
196 | { | ||
197 | int i; | ||
198 | |||
199 | for (i = 0; config_rom_entries[i]; i++) { | ||
200 | if (config_rom_entries[i]->cleanup) | ||
201 | config_rom_entries[i]->cleanup(); | ||
202 | } | ||
203 | } | ||
204 | |||
205 | int hpsb_add_extra_config_roms(struct hpsb_host *host) | ||
206 | { | ||
207 | int i, error = 0; | ||
208 | |||
209 | for (i = 0; config_rom_entries[i]; i++) { | ||
210 | if (config_rom_entries[i]->add(host)) { | ||
211 | HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'", | ||
212 | host->id, config_rom_entries[i]->name); | ||
213 | error = -1; | ||
214 | } else { | ||
215 | host->config_roms |= config_rom_entries[i]->flag; | ||
216 | host->update_config_rom = 1; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | return error; | ||
221 | } | ||
222 | |||
223 | void hpsb_remove_extra_config_roms(struct hpsb_host *host) | ||
224 | { | ||
225 | int i; | ||
226 | |||
227 | for (i = 0; config_rom_entries[i]; i++) { | ||
228 | if (!(host->config_roms & config_rom_entries[i]->flag)) | ||
229 | continue; | ||
230 | |||
231 | config_rom_entries[i]->remove(host); | ||
232 | |||
233 | host->config_roms &= ~config_rom_entries[i]->flag; | ||
234 | host->update_config_rom = 1; | ||
235 | } | ||
236 | } | ||