]>
Commit | Line | Data |
---|---|---|
a6316ce4 MT |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <fcntl.h> | |
6 | #include <dirent.h> | |
7 | #include <sys/ioctl.h> | |
8 | #include <sys/types.h> | |
9 | #include <sys/stat.h> | |
10 | #include <sys/mount.h> | |
11 | #include <linux/hdreg.h> | |
12 | ||
13 | #include "hd.h" | |
14 | #include "hd_int.h" | |
15 | #include "pcmcia.h" | |
16 | ||
17 | static void read_cardinfo(hd_data_t *hd_data); | |
18 | static void assign_bridges(hd_data_t *hd_data); | |
19 | static void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd); | |
20 | ||
21 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
22 | * PCMCIA info via cardctl | |
23 | * | |
24 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
25 | */ | |
26 | ||
27 | ||
28 | void hd_scan_pcmcia(hd_data_t *hd_data) | |
29 | { | |
30 | if(!hd_probe_feature(hd_data, pr_pcmcia)) return; | |
31 | ||
32 | hd_data->module = mod_pcmcia; | |
33 | ||
34 | /* some clean-up */ | |
35 | remove_hd_entries(hd_data); | |
36 | ||
37 | read_cardinfo(hd_data); | |
38 | ||
39 | assign_bridges(hd_data); | |
40 | ||
41 | } | |
42 | ||
43 | ||
44 | void read_cardinfo(hd_data_t *hd_data) | |
45 | { | |
46 | str_list_t *sl, *sl0, *sl1; | |
47 | int i0, i1, pcmcia_sock, manf_id0, manf_id1, func, prod_info; | |
48 | char buf0[256], buf1[256], buf2[256], buf3[256]; | |
49 | hd_t *hd; | |
50 | unsigned cardbus = 0; /* bitmask: cardbus vs. pc-card */ | |
51 | ||
52 | sl0 = read_file("| /sbin/cardctl status 2>/dev/null", 0, 0); | |
53 | ||
54 | ADD2LOG("----- cardctl status -----\n"); | |
55 | for(sl = sl0; sl; sl = sl->next) { | |
56 | ADD2LOG(" %s", sl->str); | |
57 | } | |
58 | ADD2LOG("----- cardctl status end -----\n"); | |
59 | ||
60 | for(pcmcia_sock = -1, sl = sl0; sl; sl = sl->next) { | |
61 | if(sscanf(sl->str, " Socket %d:", &i0) == 1) { | |
62 | pcmcia_sock = i0; | |
63 | continue; | |
64 | } | |
65 | ||
66 | if(strstr(sl->str, " CardBus card")) { | |
67 | if(pcmcia_sock >= 0 && pcmcia_sock < 8 * (int) sizeof cardbus) { | |
68 | cardbus |= 1 << pcmcia_sock; | |
69 | } | |
70 | pcmcia_sock = -1; | |
71 | continue; | |
72 | } | |
73 | } | |
74 | ||
75 | free_str_list(sl0); | |
76 | ||
77 | sl0 = read_file("| /sbin/cardctl ident 2>/dev/null", 0, 0); | |
78 | ||
79 | ADD2LOG("----- cardctl ident -----\n"); | |
80 | for(sl = sl0; sl; sl = sl->next) { | |
81 | ADD2LOG(" %s", sl->str); | |
82 | } | |
83 | ADD2LOG("----- cardctl ident end -----\n"); | |
84 | ||
85 | for( | |
86 | pcmcia_sock = manf_id0 = manf_id1 = func = prod_info = -1, sl = sl0; | |
87 | sl; | |
88 | sl = sl->next | |
89 | ) { | |
90 | if(sscanf(sl->str, " manfid: %i, %i", &i0, &i1) == 2) { | |
91 | manf_id0 = i0; | |
92 | manf_id1 = i1; | |
93 | } | |
94 | ||
95 | if(sscanf(sl->str, " function: %d", &i0) == 1) { | |
96 | /* | |
97 | * "multifunction", "memory", "serial", "parallel", | |
98 | * "fixed disk", "video", "network", "AIMS", | |
99 | * "SCSI" | |
100 | */ | |
101 | func = i0; | |
102 | } | |
103 | ||
104 | if( | |
105 | (i0 = sscanf( | |
106 | sl->str, | |
107 | " product info: \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\", \"%255[^\"]\"", | |
108 | buf0, buf1, buf2, buf3 | |
109 | )) >= 1 | |
110 | ) { | |
111 | prod_info = i0; | |
112 | } | |
113 | ||
114 | if(sscanf(sl->str, " Socket %d:", &i0) == 1) { | |
115 | i1 = 1; | |
116 | } | |
117 | else { | |
118 | i1 = 0; | |
119 | } | |
120 | ||
121 | if(i1 || !sl->next) { | |
122 | if(pcmcia_sock >= 0 && (prod_info >= 1 || manf_id0 != -1)) { | |
123 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
124 | hd->bus.id = bus_pcmcia; | |
125 | hd->slot = pcmcia_sock; | |
126 | hd->hotplug_slot = pcmcia_sock + 1; | |
127 | if(manf_id0 != -1 && manf_id1 != -1) { | |
128 | hd->vendor.id = MAKE_ID(TAG_PCMCIA, manf_id0); | |
129 | hd->device.id = MAKE_ID(TAG_PCMCIA, manf_id1); | |
130 | } | |
131 | if(pcmcia_sock < 8 * (int) sizeof cardbus && (cardbus & (1 << pcmcia_sock))) { | |
132 | hd->hotplug = hp_cardbus; | |
133 | } | |
134 | else { | |
135 | hd->hotplug = hp_pcmcia; | |
136 | } | |
137 | ||
138 | if(func == 6) { | |
139 | hd->base_class.id = bc_network; | |
140 | hd->sub_class.id = 0x80; /* other */ | |
141 | } | |
142 | if(prod_info >= 1) add_str_list(&hd->extra_info, buf0); | |
143 | if(prod_info >= 2) add_str_list(&hd->extra_info, buf1); | |
144 | if(prod_info >= 3) add_str_list(&hd->extra_info, buf2); | |
145 | if(prod_info >= 4) add_str_list(&hd->extra_info, buf3); | |
146 | if(prod_info >= 2) { | |
147 | hd->vendor.name = new_str(buf0); | |
148 | hd->device.name = new_str(buf1); | |
149 | } | |
150 | for(sl1 = hd->extra_info; sl1 ; sl1 = sl1->next) { | |
151 | if(strstr(sl1->str, "Ethernet")) hd->sub_class.id = 0; /* ethernet */ | |
152 | if( | |
153 | !hd->revision.name && | |
154 | !sl1->next && | |
155 | ( | |
156 | !strncasecmp(sl1->str, "rev.", sizeof "rev." - 1) || | |
157 | ( | |
158 | (sl1->str[0] == 'V' || sl1->str[0] == 'v') && | |
159 | (sl1->str[1] >= '0' && sl1->str[1] <= '9') | |
160 | ) | |
161 | ) | |
162 | ) { | |
163 | hd->revision.name = new_str(sl1->str); | |
164 | } | |
165 | } | |
166 | } | |
167 | ||
168 | manf_id0 = manf_id1 = func = prod_info = -1; | |
169 | } | |
170 | ||
171 | if(i1) pcmcia_sock = i0; | |
172 | ||
173 | } | |
174 | ||
175 | free_str_list(sl0); | |
176 | } | |
177 | ||
178 | ||
179 | /* | |
180 | * Identify hotpluggable devices. | |
181 | */ | |
182 | void assign_bridges(hd_data_t *hd_data) | |
183 | { | |
184 | hd_t *hd, *hd1, *bridge_hd; | |
185 | unsigned p_sock[8], p_socks, u = 0; | |
186 | ||
187 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
188 | if((bridge_hd = hd_get_device_by_idx(hd_data, hd->attached_to))) { | |
189 | if( | |
190 | bridge_hd->base_class.id == bc_bridge && | |
191 | bridge_hd->sub_class.id == sc_bridge_cardbus | |
192 | ) { | |
193 | hd->hotplug = hp_cardbus; | |
194 | } | |
195 | else if( | |
196 | bridge_hd->base_class.id == bc_bridge && | |
197 | bridge_hd->sub_class.id == sc_bridge_pcmcia | |
198 | ) { | |
199 | hd->hotplug = hp_pcmcia; | |
200 | } | |
201 | } | |
202 | } | |
203 | ||
204 | for(p_socks = 0, hd = hd_data->hd; hd; hd = hd->next) { | |
205 | if( | |
206 | u < sizeof p_sock / sizeof *p_sock && | |
207 | is_pcmcia_ctrl(hd_data, hd) | |
208 | ) { | |
209 | p_sock[p_socks++] = hd->idx; | |
210 | } | |
211 | } | |
212 | ||
213 | if(p_socks) { | |
214 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
215 | if( | |
216 | !hd->tag.remove && | |
217 | hd->bus.id == bus_pcmcia && | |
218 | hd->slot < p_socks && | |
219 | p_sock[hd->slot] | |
220 | ) { | |
221 | for(u = p_sock[hd->slot], hd1 = hd_data->hd; hd1; hd1 = hd1->next) { | |
222 | if(hd1->tag.remove) continue; | |
223 | if(hd1->status.available == status_no) continue; | |
224 | if(hd1->attached_to == u) break; | |
225 | } | |
226 | if(hd1) { | |
227 | hd1->hotplug = hd->hotplug; | |
228 | hd1->hotplug_slot = hd->hotplug_slot; | |
229 | if(!hd1->extra_info) { | |
230 | hd1->extra_info = hd->extra_info; | |
231 | hd->extra_info = NULL; | |
232 | } | |
233 | hd->tag.remove = 1; | |
234 | } | |
235 | else { | |
236 | hd->attached_to = p_sock[hd->slot]; | |
237 | add_sysfs_stuff(hd_data, hd); | |
238 | } | |
239 | p_sock[hd->slot] = 0; | |
240 | } | |
241 | } | |
242 | ||
243 | remove_tagged_hd_entries(hd_data); | |
244 | } | |
245 | } | |
246 | ||
247 | ||
248 | void add_sysfs_stuff(hd_data_t *hd_data, hd_t *hd) | |
249 | { | |
250 | hd_t *hd_par; | |
251 | char *s = NULL, *s1; | |
252 | struct sysfs_device *sf_dev; | |
253 | ||
254 | hd_par = hd_get_device_by_idx(hd_data, hd->attached_to); | |
255 | ||
256 | if(!hd_par || !hd_par->sysfs_id || hd->sysfs_id) return; | |
257 | ||
258 | str_printf(&s, 0, "/sys%s/%d.0", hd_par->sysfs_id, hd->slot); | |
259 | ||
260 | sf_dev = sysfs_open_device_path(s); | |
261 | ||
262 | if(sf_dev) { | |
263 | hd->sysfs_id = new_str(hd_sysfs_id(s)); | |
264 | s1 = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1); | |
265 | if(s1) add_str_list(&hd->drivers, s1); | |
266 | } | |
267 | ||
268 | sysfs_close_device(sf_dev); | |
269 | ||
270 | s = free_mem(s); | |
271 | } | |
272 |