]>
Commit | Line | Data |
---|---|---|
93afd047 MT |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | ||
5 | #include "hd.h" | |
6 | #include "hd_int.h" | |
7 | #include "hddb.h" | |
8 | #include "isapnp.h" | |
9 | ||
10 | ||
11 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
12 | * isapnp stuff | |
13 | * | |
14 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
15 | */ | |
16 | ||
17 | #if defined(__i386__) || defined(__alpha__) | |
18 | ||
19 | static void get_pnp_devs(hd_data_t *hd_data); | |
20 | ||
21 | #if 0 | |
22 | static void get_read_port(hd_data_t *hd_data, isapnp_t *); | |
23 | static void build_list(hd_data_t *hd_data, str_list_t *isapnp_list); | |
24 | #endif | |
25 | ||
26 | void hd_scan_isapnp(hd_data_t *hd_data) | |
27 | { | |
28 | #if 0 | |
29 | hd_t *hd; | |
30 | hd_res_t *res; | |
31 | int isapnp_ok; | |
32 | str_list_t *isapnp_list = NULL, *sl; | |
33 | #endif | |
34 | ||
35 | if(!hd_probe_feature(hd_data, pr_isapnp)) return; | |
36 | ||
37 | hd_data->module = mod_isapnp; | |
38 | ||
39 | /* some clean-up */ | |
40 | remove_hd_entries(hd_data); | |
41 | ||
42 | PROGRESS(1, 0, "pnp devices"); | |
43 | ||
44 | get_pnp_devs(hd_data); | |
45 | ||
46 | #if 0 | |
47 | PROGRESS(1, 0, "read port"); | |
48 | ||
49 | if(!hd_data->isapnp) { | |
50 | hd_data->isapnp = new_mem(sizeof *hd_data->isapnp); | |
51 | } | |
52 | else { | |
53 | hd_data->isapnp->cards = 0; | |
54 | /* just in case... */ | |
55 | hd_data->isapnp->card = free_mem(hd_data->isapnp->card); | |
56 | /* keep the port */ | |
57 | } | |
58 | ||
59 | if(!hd_data->isapnp->read_port) get_read_port(hd_data, hd_data->isapnp); | |
60 | ||
61 | PROGRESS(3, 0, "get pnp data"); | |
62 | ||
63 | isapnp_list = read_file(PROC_ISAPNP, 0, 0); | |
64 | ||
65 | if((hd_data->debug & HD_DEB_ISAPNP)) { | |
66 | ADD2LOG("----- %s -----\n", PROC_ISAPNP); | |
67 | for(sl = isapnp_list; sl; sl = sl->next) { | |
68 | ADD2LOG(" %s", sl->str); | |
69 | } | |
70 | ADD2LOG("----- %s end -----\n", PROC_ISAPNP); | |
71 | } | |
72 | ||
73 | isapnp_ok = isapnp_list && hd_data->isapnp->read_port ? 1 : 1; | |
74 | ||
75 | PROGRESS(4, 0, "build list"); | |
76 | ||
77 | if(isapnp_ok) { | |
78 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
79 | hd->bus.id = bus_isa; | |
80 | hd->base_class.id = bc_internal; | |
81 | hd->sub_class.id = sc_int_isapnp_if; | |
82 | ||
83 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
84 | res->io.type = res_io; | |
85 | res->io.enabled = 1; | |
86 | res->io.base = ISAPNP_ADDR_PORT; | |
87 | res->io.range = 1; | |
88 | res->io.access = acc_wo; | |
89 | ||
90 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
91 | res->io.type = res_io; | |
92 | res->io.enabled = 1; | |
93 | res->io.base = ISAPNP_DATA_PORT; | |
94 | res->io.range = 1; | |
95 | res->io.access = acc_wo; | |
96 | ||
97 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
98 | res->io.type = res_io; | |
99 | res->io.enabled = 1; | |
100 | res->io.base = hd_data->isapnp->read_port; | |
101 | res->io.range = 1; | |
102 | res->io.access = acc_ro; | |
103 | } | |
104 | ||
105 | build_list(hd_data, isapnp_list); | |
106 | ||
107 | free_str_list(isapnp_list); | |
108 | #endif | |
109 | ||
110 | } | |
111 | ||
112 | ||
113 | void get_pnp_devs(hd_data_t *hd_data) | |
114 | { | |
115 | hd_t *hd; | |
116 | char *s, *t, buf[4]; | |
117 | unsigned u1, u2, u3; | |
118 | ||
119 | struct sysfs_bus *sf_bus; | |
120 | struct dlist *sf_dev_list; | |
121 | struct sysfs_device *sf_dev; | |
122 | struct sysfs_device *sf_dev_2; | |
123 | ||
124 | sf_bus = sysfs_open_bus("pnp"); | |
125 | ||
126 | if(!sf_bus) { | |
127 | ADD2LOG("sysfs: no such bus: pnp\n"); | |
128 | return; | |
129 | } | |
130 | ||
131 | sf_dev_list = sysfs_get_bus_devices(sf_bus); | |
132 | ||
133 | ||
134 | if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) { | |
135 | ADD2LOG( | |
136 | " pnp device: name = %s, bus_id = %s, bus = %s\n path = %s\n", | |
137 | sf_dev->name, | |
138 | sf_dev->bus_id, | |
139 | sf_dev->bus, | |
140 | hd_sysfs_id(sf_dev->path) | |
141 | ); | |
142 | ||
143 | if((s = hd_attr_str(sysfs_get_device_attr(sf_dev, "id")))) { | |
144 | if(sscanf(s, "%3s%4x", buf, &u1) == 2 && (u2 = name2eisa_id(buf))) { | |
145 | ADD2LOG(" id = %s %04x\n", eisa_vendor_str(u2), u1); | |
146 | ||
147 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
148 | ||
149 | hd->sysfs_id = new_str(hd_sysfs_id(sf_dev->path)); | |
150 | hd->sysfs_bus_id = new_str(sf_dev->bus_id); | |
151 | ||
152 | hd->bus.id = bus_isa; | |
153 | hd->is.isapnp = 1; | |
154 | ||
155 | hd->sub_vendor.id = u2; | |
156 | hd->sub_device.id = MAKE_ID(TAG_EISA, u1); | |
157 | ||
158 | if(sscanf(hd->sysfs_bus_id, "%2x:%2x.%2x", &u1, &u2, &u3) == 3) { | |
159 | hd->slot = u2; | |
160 | hd->func = u3; | |
161 | } | |
162 | ||
163 | s = new_str(sf_dev->path); | |
164 | if((t = strrchr(s, '/'))) *t = 0; | |
165 | ||
166 | sf_dev_2 = sysfs_open_device_path(s); | |
167 | if(sf_dev_2) { | |
168 | if((t = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "card_id")))) { | |
169 | if(sscanf(t, "%3s%4x", buf, &u1) == 2 && (u2 = name2eisa_id(buf))) { | |
170 | ADD2LOG(" card id = %s %04x\n", eisa_vendor_str(u2), u1); | |
171 | ||
172 | hd->vendor.id = u2; | |
173 | hd->device.id = MAKE_ID(TAG_EISA, u1); | |
174 | } | |
175 | } | |
176 | if((t = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "name")))) { | |
177 | hd->device.name = canon_str(t, strlen(t)); | |
178 | if(!strcasecmp(hd->device.name, "unknown")) { | |
179 | hd->device.name = free_mem(hd->device.name); | |
180 | } | |
181 | } | |
182 | ||
183 | sysfs_close_device(sf_dev_2); | |
184 | } | |
185 | ||
186 | ||
187 | free_mem(s); | |
188 | ||
189 | ||
190 | if(hd->sub_vendor.id == hd->vendor.id && hd->sub_device.id == hd->device.id) { | |
191 | hd->sub_vendor.id = hd->sub_device.id = 0; | |
192 | } | |
193 | ||
194 | } | |
195 | } | |
196 | ||
197 | } | |
198 | ||
199 | ||
200 | sysfs_close_bus(sf_bus); | |
201 | ||
202 | } | |
203 | ||
204 | ||
205 | #if 0 | |
206 | unsigned char *add_isapnp_card_res(isapnp_card_t *ic, int len, int type) | |
207 | { | |
208 | ic->res = add_mem(ic->res, sizeof *ic->res, ic->res_len); | |
209 | ||
210 | ic->res[ic->res_len].len = len; | |
211 | ic->res[ic->res_len].type = type; | |
212 | ic->res[ic->res_len].data = new_mem(len); | |
213 | ||
214 | if(type == RES_LOG_DEV_ID) { /* logical device id */ | |
215 | ic->log_devs++; | |
216 | } | |
217 | ||
218 | return ic->res[ic->res_len++].data; | |
219 | } | |
220 | ||
221 | ||
222 | isapnp_card_t *add_isapnp_card(isapnp_t *ip, int csn) | |
223 | { | |
224 | isapnp_card_t *c; | |
225 | ||
226 | ip->card = add_mem(ip->card, sizeof *ip->card, ip->cards); | |
227 | c = ip->card + ip->cards++; | |
228 | ||
229 | c->csn = csn; | |
230 | c->serial = new_mem(sizeof *c->serial * 8); | |
231 | c->card_regs = new_mem(sizeof *c->card_regs * 0x30); | |
232 | ||
233 | return c; | |
234 | } | |
235 | ||
236 | ||
237 | void get_read_port(hd_data_t *hd_data, isapnp_t *p) | |
238 | { | |
239 | hd_res_t *res; | |
240 | ||
241 | p->read_port = 0; | |
242 | ||
243 | res = NULL; | |
244 | gather_resources(hd_data->misc, &res, "ISAPnP", W_IO); | |
245 | if(res && res->any.type == res_io) p->read_port = res->io.base; | |
246 | free_res_list(res); | |
247 | } | |
248 | ||
249 | ||
250 | void build_list(hd_data_t *hd_data, str_list_t *isapnp_list) | |
251 | { | |
252 | hd_t *hd = NULL; | |
253 | str_list_t *sl; | |
254 | char s1[4], s2[100]; | |
255 | int card, ldev, cdev_id, ldev_active = 0; | |
256 | char *dev_name = NULL, *ldev_name = NULL; | |
257 | unsigned dev_id = 0, vend_id = 0, base_class = 0, sub_class = 0, ldev_id; | |
258 | unsigned u, ux[5]; | |
259 | int i, j; | |
260 | hd_res_t *res; | |
261 | ||
262 | for(sl = isapnp_list; sl; sl = sl->next) { | |
263 | ||
264 | if(sscanf(sl->str, "Card %d '%3s%4x:%99[^']", &card, s1, &dev_id, s2) == 4) { | |
265 | // ADD2LOG("\n\n** card %d >%s< %04x >%s<**\n", card, s1, dev_id, s2); | |
266 | ||
267 | dev_name = free_mem(dev_name); | |
268 | if(strcmp(s2, "Unknown")) dev_name = new_str(s2); | |
269 | ||
270 | dev_id = MAKE_ID(TAG_EISA, dev_id); | |
271 | vend_id = name2eisa_id(s1); | |
272 | ||
273 | base_class = sub_class = 0; | |
274 | if((u = device_class(hd_data, vend_id, dev_id))) { | |
275 | base_class = u >> 8; | |
276 | sub_class = u & 0xff; | |
277 | } | |
278 | ||
279 | #if 0 | |
280 | // ########## FIXME | |
281 | if( | |
282 | (ID_VALUE(vend_id) || ID_VALUE(dev_id)) && | |
283 | !((db_name = hd_device_name(hd_data, vend_id, dev_id)) && *db_name) | |
284 | ) { | |
285 | if(dev_name) { | |
286 | add_device_name(hd_data, vend_id, dev_id, dev_name); | |
287 | } | |
288 | } | |
289 | #endif | |
290 | ||
291 | continue; | |
292 | } | |
293 | ||
294 | if(sscanf(sl->str, " Logical device %d '%3s%4x:%99[^']", &ldev, s1, &ldev_id, s2) == 4) { | |
295 | // ADD2LOG("\n\n** ldev %d >%s< %04x >%s<**\n", ldev, s1, ldev_id, s2); | |
296 | ||
297 | ldev_name = free_mem(ldev_name); | |
298 | if(strcmp(s2, "Unknown")) ldev_name = new_str(s2); | |
299 | ||
300 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
301 | ||
302 | hd->bus.id = bus_isa; | |
303 | hd->is.isapnp = 1; | |
304 | hd->slot = card; | |
305 | hd->func = ldev; | |
306 | ||
307 | hd->vendor.id = vend_id; | |
308 | hd->device.id = dev_id; | |
309 | ||
310 | hd->base_class.id = base_class; | |
311 | hd->sub_class.id = sub_class; | |
312 | ||
313 | hd->sub_device.id = MAKE_ID(TAG_EISA, ldev_id); | |
314 | hd->sub_vendor.id = name2eisa_id(s1); | |
315 | ||
316 | if(hd->sub_vendor.id == hd->vendor.id && hd->sub_device.id == hd->device.id) { | |
317 | hd->sub_vendor.id = hd->sub_device.id = 0; | |
318 | } | |
319 | ||
320 | if((u = sub_device_class(hd_data, hd->vendor.id, hd->device.id, hd->sub_vendor.id, hd->sub_device.id))) { | |
321 | hd->base_class.id = u >> 8; | |
322 | hd->sub_class.id = u & 0xff; | |
323 | } | |
324 | ||
325 | #if 0 | |
326 | # ############# FIXME | |
327 | if( | |
328 | (ID_VALUE(hd->sub_vendor.id) || ID_VALUE(hd->sub_device.id)) && | |
329 | !hd_sub_device_name(hd_data, hd->vend, hd->dev, hd->sub_vend, hd->sub_device.id) | |
330 | ) { | |
331 | if(ldev_name) { | |
332 | add_sub_device_name(hd_data, hd->vend, hd->dev, hd->sub_vend, hd->sub_device.id, ldev_name); | |
333 | } | |
334 | } | |
335 | #endif | |
336 | ||
337 | continue; | |
338 | } | |
339 | ||
340 | if(strstr(sl->str, "Device is not active")) { | |
341 | ldev_active = 0; | |
342 | continue; | |
343 | } | |
344 | ||
345 | if(strstr(sl->str, "Device is active")) { | |
346 | ldev_active = 1; | |
347 | continue; | |
348 | } | |
349 | ||
350 | if(hd && sscanf(sl->str, " Compatible device %3s%4x", s1, &cdev_id) == 2) { | |
351 | // ADD2LOG("\n\n** cdev >%s< %04x **\n", s1, cdev_id); | |
352 | ||
353 | hd->compat_device.id = MAKE_ID(TAG_EISA, cdev_id); | |
354 | hd->compat_vendor.id = name2eisa_id(s1); | |
355 | ||
356 | if(!(hd->base_class.id || hd->sub_class.id)) { | |
357 | if((u = device_class(hd_data, hd->compat_vendor.id, hd->compat_device.id))) { | |
358 | hd->base_class.id = u >> 8; | |
359 | hd->sub_class.id = u & 0xff; | |
360 | } | |
361 | else if(hd->compat_vendor.id == MAKE_ID(TAG_EISA, 0x41d0)) { | |
362 | /* 0x41d0 is 'PNP' */ | |
363 | switch((hd->compat_device.id >> 12) & 0xf) { | |
364 | case 8: | |
365 | hd->base_class.id = bc_network; | |
366 | hd->sub_class.id = 0x80; | |
367 | break; | |
368 | case 0xa: | |
369 | hd->base_class.id = bc_storage; | |
370 | hd->sub_class.id = 0x80; | |
371 | break; | |
372 | case 0xb: | |
373 | hd->base_class.id = bc_multimedia; | |
374 | hd->sub_class.id = 0x80; | |
375 | break; | |
376 | case 0xc: | |
377 | case 0xd: | |
378 | hd->base_class.id = bc_modem; | |
379 | break; | |
380 | } | |
381 | } | |
382 | } | |
383 | ||
384 | continue; | |
385 | } | |
386 | ||
387 | if( | |
388 | hd && | |
389 | (j = sscanf(sl->str, | |
390 | " Active port %x, %x, %x, %x, %x, %x", | |
391 | ux, ux + 1, ux + 2, ux + 3, ux + 4, ux + 5 | |
392 | )) >= 1 | |
393 | ) { | |
394 | ||
395 | for(i = 0; i < j; i++) { | |
396 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
397 | res->io.type = res_io; | |
398 | res->io.enabled = ldev_active ? 1 : 0; | |
399 | res->io.base = ux[i]; | |
400 | res->io.access = acc_rw; | |
401 | } | |
402 | ||
403 | continue; | |
404 | } | |
405 | ||
406 | if(hd && (j = sscanf(sl->str, " Active IRQ %d [%x], %d [%x]", ux, ux + 1, ux + 2, ux + 3)) >= 1) { | |
407 | for(i = 0; i < j; i += 2) { | |
408 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
409 | res->irq.type = res_irq; | |
410 | res->irq.enabled = ldev_active ? 1 : 0; | |
411 | res->irq.base = ux[i]; | |
412 | } | |
413 | ||
414 | continue; | |
415 | } | |
416 | ||
417 | if(hd && (j = sscanf(sl->str, " Active DMA %d, %d", ux, ux + 1)) >= 1) { | |
418 | for(i = 0; i < j; i++) { | |
419 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
420 | res->dma.type = res_dma; | |
421 | res->dma.enabled = ldev_active ? 1 : 0; | |
422 | res->dma.base = ux[i]; | |
423 | } | |
424 | ||
425 | continue; | |
426 | } | |
427 | ||
428 | ||
429 | } | |
430 | ||
431 | free_mem(dev_name); | |
432 | free_mem(ldev_name); | |
433 | } | |
434 | #endif | |
435 | ||
436 | ||
437 | #endif /* defined(__i386__) || defined(__alpha__) */ | |
438 |