]>
Commit | Line | Data |
---|---|---|
93afd047 MT |
1 | #include <stdio.h> |
2 | #include <stdlib.h> | |
3 | #include <string.h> | |
4 | #include <unistd.h> | |
5 | #include <dirent.h> | |
6 | #include <sys/stat.h> | |
7 | ||
8 | #include "hd.h" | |
9 | #include "hd_int.h" | |
10 | #include "hddb.h" | |
11 | #include "prom.h" | |
12 | ||
13 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
14 | * prom info | |
15 | * | |
16 | * Note: make sure that hd_scan_sysfs_pci() has been run! | |
17 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
18 | */ | |
19 | ||
20 | #if defined(__PPC__) | |
21 | ||
22 | static devtree_t *add_devtree_entry(devtree_t **devtree, devtree_t *new); | |
23 | static devtree_t *new_devtree_entry(devtree_t *parent); | |
24 | static void read_str(char *path, char *name, char **str); | |
25 | static void read_mem(char *path, char *name, unsigned char **mem, unsigned len); | |
26 | static void read_int(char *path, char *name, int *val); | |
27 | static void read_devtree(hd_data_t *hd_data); | |
28 | static void add_pci_prom_devices(hd_data_t *hd_data, hd_t *hd_parent, devtree_t *parent); | |
29 | static void add_legacy_prom_devices(hd_data_t *hd_data, devtree_t *dt); | |
30 | static int add_prom_display(hd_data_t *hd_data, devtree_t *dt); | |
31 | static int add_prom_vscsi(hd_data_t *hd_data, devtree_t *dt); | |
32 | static int add_prom_veth(hd_data_t *hd_data, devtree_t *dt); | |
33 | static void add_devices(hd_data_t *hd_data); | |
34 | static void dump_devtree_data(hd_data_t *hd_data); | |
35 | ||
36 | static unsigned veth_cnt, vscsi_cnt; | |
37 | ||
38 | int detect_smp_prom(hd_data_t *hd_data) | |
39 | { | |
40 | unsigned cpus; | |
41 | devtree_t *devtree; | |
42 | ||
43 | if(!(devtree = hd_data->devtree)) return -1; /* hd_scan_prom() not called */ | |
44 | ||
45 | for(cpus = 0; devtree; devtree = devtree->next) { | |
46 | if(devtree->device_type && !strcmp(devtree->device_type, "cpu")) cpus++; | |
47 | } | |
48 | ||
49 | return cpus > 1 ? cpus : 0; | |
50 | } | |
51 | ||
52 | void hd_scan_prom(hd_data_t *hd_data) | |
53 | { | |
54 | hd_t *hd; | |
55 | unsigned char buf[16]; | |
56 | FILE *f; | |
57 | prom_info_t *pt; | |
58 | ||
59 | if(!hd_probe_feature(hd_data, pr_prom)) return; | |
60 | ||
61 | hd_data->module = mod_prom; | |
62 | ||
63 | /* some clean-up */ | |
64 | remove_hd_entries(hd_data); | |
65 | hd_data->devtree = free_devtree(hd_data); | |
66 | ||
67 | veth_cnt = vscsi_cnt = 0; | |
68 | ||
69 | PROGRESS(1, 0, "devtree"); | |
70 | ||
71 | read_devtree(hd_data); | |
72 | if(hd_data->debug) dump_devtree_data(hd_data); | |
73 | add_devices(hd_data); | |
74 | ||
75 | PROGRESS(2, 0, "color"); | |
76 | ||
77 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
78 | hd->base_class.id = bc_internal; | |
79 | hd->sub_class.id = sc_int_prom; | |
80 | hd->detail = new_mem(sizeof *hd->detail); | |
81 | hd->detail->type = hd_detail_prom; | |
82 | hd->detail->prom.data = pt = new_mem(sizeof *pt); | |
83 | ||
84 | if((f = fopen(PROC_PROM "/color-code", "r"))) { | |
85 | if(fread(buf, 1, 2, f) == 2) { | |
86 | pt->has_color = 1; | |
87 | pt->color = buf[1]; | |
88 | hd_data->color_code = pt->color | 0x10000; | |
89 | ADD2LOG("color-code: 0x%04x\n", (buf[0] << 8) + buf[1]); | |
90 | } | |
91 | ||
92 | fclose(f); | |
93 | } | |
94 | ||
95 | } | |
96 | ||
97 | /* store a device tree entry */ | |
98 | devtree_t *add_devtree_entry(devtree_t **devtree, devtree_t *new) | |
99 | { | |
100 | while(*devtree) devtree = &(*devtree)->next; | |
101 | return *devtree = new; | |
102 | } | |
103 | ||
104 | /* create a new device tree entry */ | |
105 | devtree_t *new_devtree_entry(devtree_t *parent) | |
106 | { | |
107 | static unsigned idx = 0; | |
108 | devtree_t *devtree = new_mem(sizeof *devtree); | |
109 | ||
110 | if(!parent) idx = 0; | |
111 | devtree->idx = ++idx; | |
112 | devtree->parent = parent; | |
113 | ||
114 | devtree->interrupt = devtree->class_code = | |
115 | devtree->device_id = devtree->vendor_id = | |
116 | devtree->subdevice_id = devtree->subvendor_id = | |
117 | devtree->revision_id = -1; | |
118 | ||
119 | return devtree; | |
120 | } | |
121 | ||
122 | void read_str(char *path, char *name, char **str) | |
123 | { | |
124 | char *s = NULL; | |
125 | str_list_t *sl; | |
126 | ||
127 | str_printf(&s, 0, "%s/%s", path, name); | |
128 | if((sl = read_file(s, 0, 1))) { | |
129 | *str = sl->str; | |
130 | sl->str = NULL; | |
131 | sl = free_str_list(sl); | |
132 | } | |
133 | free_mem(s); | |
134 | } | |
135 | ||
136 | void read_mem(char *path, char *name, unsigned char **mem, unsigned len) | |
137 | { | |
138 | FILE *f; | |
139 | char *s = NULL; | |
140 | unsigned char *m = new_mem(len); | |
141 | ||
142 | str_printf(&s, 0, "%s/%s", path, name); | |
143 | if((f = fopen(s, "r"))) { | |
144 | if(fread(m, len, 1, f) == 1) { | |
145 | *mem = m; | |
146 | m = NULL; | |
147 | } | |
148 | fclose(f); | |
149 | } | |
150 | free_mem(s); | |
151 | free_mem(m); | |
152 | } | |
153 | ||
154 | void read_int(char *path, char *name, int *val) | |
155 | { | |
156 | unsigned char *p = NULL; | |
157 | ||
158 | read_mem(path, name, &p, sizeof (int)); | |
159 | if(p) memcpy(val, p, sizeof (int)); | |
160 | free_mem(p); | |
161 | } | |
162 | ||
163 | void read_devtree_entry(hd_data_t *hd_data, devtree_t *parent, char *dirname) | |
164 | { | |
165 | DIR *dir; | |
166 | struct dirent *de; | |
167 | struct stat sbuf; | |
168 | char *path, *s; | |
169 | devtree_t *devtree, *dt2; | |
170 | ||
171 | devtree = add_devtree_entry(&hd_data->devtree, new_devtree_entry(parent)); | |
172 | ||
173 | devtree->filename = new_str(dirname); | |
174 | ||
175 | str_printf(&devtree->path, 0, "%s%s%s", | |
176 | parent ? parent->path : "", parent && *parent->path ? "/" : "", dirname | |
177 | ); | |
178 | ||
179 | path = 0; | |
180 | str_printf(&path, 0, PROC_PROM "/%s", devtree->path); | |
181 | ||
182 | if((dir = opendir(path))) { | |
183 | while((de = readdir(dir))) { | |
184 | if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; | |
185 | s = NULL; | |
186 | str_printf(&s, 0, "%s/%s", path, de->d_name); | |
187 | if(!lstat(s, &sbuf)) { | |
188 | if(S_ISDIR(sbuf.st_mode)) { | |
189 | /* prom entries don't always have unique names, unfortunately... */ | |
190 | for(dt2 = hd_data->devtree; dt2; dt2 = dt2->next) { | |
191 | if( | |
192 | dt2->parent == devtree && | |
193 | !strcmp(dt2->filename, de->d_name) | |
194 | ) break; | |
195 | } | |
196 | if(!dt2) read_devtree_entry(hd_data, devtree, de->d_name); | |
197 | } | |
198 | } | |
199 | s = free_mem(s); | |
200 | } | |
201 | closedir(dir); | |
202 | } | |
203 | ||
204 | read_str(path, "name", &devtree->name); | |
205 | read_str(path, "model", &devtree->model); | |
206 | read_str(path, "device_type", &devtree->device_type); | |
207 | read_str(path, "compatible", &devtree->compatible); | |
208 | ||
209 | read_int(path, "interrupts", &devtree->interrupt); | |
210 | read_int(path, "AAPL,interrupts", &devtree->interrupt); | |
211 | read_int(path, "class-code", &devtree->class_code); | |
212 | read_int(path, "vendor-id", &devtree->vendor_id); | |
213 | read_int(path, "device-id", &devtree->device_id); | |
214 | read_int(path, "subsystem-vendor-id", &devtree->subvendor_id); | |
215 | read_int(path, "subsystem-id", &devtree->subdevice_id); | |
216 | read_int(path, "revision-id", &devtree->revision_id); | |
217 | ||
218 | read_mem(path, "EDID", &devtree->edid, 0x80); | |
219 | if(!devtree->edid) read_mem(path, "DFP,EDID", &devtree->edid, 0x80); | |
220 | ||
221 | if( | |
222 | devtree->class_code != -1 && devtree->vendor_id != -1 && | |
223 | devtree->device_id != -1 | |
224 | ) { | |
225 | devtree->pci = 1; | |
226 | } | |
227 | ||
228 | path = free_mem(path); | |
229 | } | |
230 | ||
231 | void read_devtree(hd_data_t *hd_data) | |
232 | { | |
233 | read_devtree_entry(hd_data, NULL, ""); | |
234 | ||
235 | } | |
236 | ||
237 | void add_pci_prom_devices(hd_data_t *hd_data, hd_t *hd_parent, devtree_t *parent) | |
238 | { | |
239 | hd_t *hd; | |
240 | hd_res_t *res; | |
241 | devtree_t *dt, *dt2; | |
242 | int irq, floppy_ctrl_idx; | |
243 | unsigned sound_ok = 0, net_ok = 0, scsi_ok = 0; | |
244 | unsigned id; | |
245 | char *s; | |
246 | ||
247 | for(dt = hd_data->devtree; dt; dt = dt->next) { | |
248 | if( | |
249 | dt->parent == parent || | |
250 | ( | |
251 | /* special magic to reach some sound chips */ | |
252 | dt->parent && | |
253 | dt->parent->parent == parent && | |
254 | !dt->parent->pci | |
255 | ) | |
256 | ) { | |
257 | ||
258 | if( | |
259 | dt->device_type && | |
260 | (!strcmp(dt->device_type, "block") || !strcmp(dt->device_type, "swim3")) | |
261 | ) { | |
262 | /* block devices */ | |
263 | ||
264 | s = dt->compatible ? dt->compatible : dt->name; | |
265 | id = 0; | |
266 | ||
267 | if(s) { | |
268 | if(strstr(s, "swim3")) { | |
269 | id = MAKE_ID(TAG_SPECIAL, 0x0040); | |
270 | } | |
271 | } | |
272 | ||
273 | if(id) { | |
274 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
275 | hd->bus.id = bus_none; | |
276 | hd->base_class.id = bc_storage; | |
277 | hd->sub_class.id = sc_sto_floppy; | |
278 | ||
279 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401); | |
280 | hd->device.id = id; | |
281 | hd->attached_to = hd_parent->idx; | |
282 | hd->rom_id = new_str(dt->path); | |
283 | if(dt->interrupt) { | |
284 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
285 | res->irq.type = res_irq; | |
286 | res->irq.enabled = 1; | |
287 | res->irq.base = dt->interrupt; | |
288 | } | |
289 | floppy_ctrl_idx = hd->idx; | |
290 | ||
291 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
292 | hd->base_class.id = bc_storage_device; | |
293 | hd->sub_class.id = sc_sdev_floppy; | |
294 | hd->bus.id = bus_floppy; | |
295 | hd->unix_dev_name = new_str("/dev/fd0"); | |
296 | ||
297 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
298 | res->size.type = res_size; | |
299 | res->size.val1 = str2float("3.5", 2); | |
300 | res->size.unit = size_unit_cinch; | |
301 | ||
302 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
303 | res->size.type = res_size; | |
304 | res->size.val1 = 2880; | |
305 | res->size.val2 = 0x200; | |
306 | res->size.unit = size_unit_sectors; | |
307 | ||
308 | hd->attached_to = floppy_ctrl_idx; | |
309 | } | |
310 | } | |
311 | ||
312 | if( | |
313 | !scsi_ok && | |
314 | dt->device_type && | |
315 | !strcmp(dt->device_type, "scsi") | |
316 | ) { | |
317 | /* scsi */ | |
318 | scsi_ok = 1; /* max. 1 controller */ | |
319 | ||
320 | s = dt->compatible ? dt->compatible : dt->name; | |
321 | id = 0; | |
322 | ||
323 | if(s) { | |
324 | if(strstr(s, "mesh")) { /* mesh || chrp,mesh0 */ | |
325 | id = MAKE_ID(TAG_SPECIAL, 0x0030); | |
326 | } | |
327 | else if(!strcmp(s, "53c94")) { | |
328 | id = MAKE_ID(TAG_SPECIAL, 0x0031); | |
329 | } | |
330 | } | |
331 | ||
332 | if(id) { | |
333 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
334 | hd->bus.id = bus_none; | |
335 | hd->base_class.id = bc_storage; | |
336 | hd->sub_class.id = sc_sto_scsi; | |
337 | ||
338 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401); | |
339 | hd->device.id = id; | |
340 | hd->attached_to = hd_parent->idx; | |
341 | hd->rom_id = new_str(dt->path); | |
342 | if(dt->interrupt) { | |
343 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
344 | res->irq.type = res_irq; | |
345 | res->irq.enabled = 1; | |
346 | res->irq.base = dt->interrupt; | |
347 | } | |
348 | } | |
349 | } | |
350 | ||
351 | if( | |
352 | !net_ok && | |
353 | dt->device_type && | |
354 | !strcmp(dt->device_type, "network") | |
355 | ) { | |
356 | /* network */ | |
357 | net_ok = 1; /* max. 1 controller */ | |
358 | ||
359 | s = dt->compatible ? dt->compatible : dt->name; | |
360 | id = 0; | |
361 | ||
362 | if(s) { | |
363 | if(!strcmp(s, "mace")) { | |
364 | id = MAKE_ID(TAG_SPECIAL, 0x0020); | |
365 | } | |
366 | else if(!strcmp(s, "bmac")) { | |
367 | id = MAKE_ID(TAG_SPECIAL, 0x0021); | |
368 | } | |
369 | else if(!strcmp(s, "bmac+")) { | |
370 | id = MAKE_ID(TAG_SPECIAL, 0x0022); | |
371 | } | |
372 | } | |
373 | ||
374 | if(id) { | |
375 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
376 | hd->bus.id = bus_none; | |
377 | hd->base_class.id = bc_network; | |
378 | hd->sub_class.id = 0; /* ethernet */ | |
379 | ||
380 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401); | |
381 | hd->device.id = id; | |
382 | hd->attached_to = hd_parent->idx; | |
383 | hd->rom_id = new_str(dt->path); | |
384 | if(dt->interrupt) { | |
385 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
386 | res->irq.type = res_irq; | |
387 | res->irq.enabled = 1; | |
388 | res->irq.base = dt->interrupt; | |
389 | } | |
390 | } | |
391 | } | |
392 | ||
393 | if( | |
394 | !sound_ok && | |
395 | dt->device_type && | |
396 | strstr(dt->device_type, "sound") == dt->device_type | |
397 | ) { | |
398 | /* sound */ | |
399 | sound_ok = 1; /* max 1 controller */ | |
400 | ||
401 | for(dt2 = dt; dt2; dt2 = dt2->next) { | |
402 | if( | |
403 | ( | |
404 | dt2 == dt || | |
405 | (dt2->parent && dt2->parent == dt) | |
406 | ) && | |
407 | ( | |
408 | !strcmp(dt2->device_type, "sound") || | |
409 | !strcmp(dt2->device_type, "soundchip") | |
410 | ) | |
411 | ) break; | |
412 | } | |
413 | if(!dt2) dt2 = dt; | |
414 | ||
415 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
416 | hd->bus.id = bus_none; | |
417 | hd->base_class.id = bc_multimedia; | |
418 | hd->sub_class.id = sc_multi_audio; | |
419 | hd->attached_to = hd_parent->idx; | |
420 | hd->rom_id = new_str(dt2->path); | |
421 | irq = dt2->interrupt; | |
422 | if(irq <= 1 && dt2->parent && !dt2->parent->pci) { | |
423 | irq = dt2->parent->interrupt; | |
424 | } | |
425 | if(irq > 1) { | |
426 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
427 | res->irq.type = res_irq; | |
428 | res->irq.enabled = 1; | |
429 | res->irq.base = irq; | |
430 | } | |
431 | ||
432 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x401); /* Apple */ | |
433 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0010); | |
434 | ||
435 | if(dt2->compatible) { | |
436 | if(!strcmp(dt2->compatible, "screamer")) { | |
437 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0011); | |
438 | } | |
439 | else if(!strcmp(dt2->compatible, "burgundy")) { | |
440 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0012); | |
441 | } | |
442 | else if(!strcmp(dt2->compatible, "daca")) { | |
443 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0013); | |
444 | } | |
445 | else if(!strcmp(dt2->compatible, "CRUS,CS4236B")) { | |
446 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x402); /* IBM */ | |
447 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x0014); | |
448 | } | |
449 | } | |
450 | } | |
451 | } | |
452 | } | |
453 | } | |
454 | ||
455 | ||
456 | void add_legacy_prom_devices(hd_data_t *hd_data, devtree_t *dt) | |
457 | { | |
458 | if(dt->pci) return; | |
459 | ||
460 | if(add_prom_display(hd_data, dt)) return; | |
461 | if(add_prom_vscsi(hd_data, dt)) return; | |
462 | if(add_prom_veth(hd_data, dt)) return; | |
463 | } | |
464 | ||
465 | int add_prom_display(hd_data_t *hd_data, devtree_t *dt) | |
466 | { | |
467 | hd_t *hd; | |
468 | hd_res_t *res; | |
469 | unsigned id; | |
470 | ||
471 | if( | |
472 | dt->device_type && | |
473 | !strcmp(dt->device_type, "display") | |
474 | ) { | |
475 | /* display devices */ | |
476 | ||
477 | id = 0; | |
478 | ||
479 | if(dt->name) { | |
480 | if(!strcmp(dt->name, "valkyrie")) { | |
481 | id = MAKE_ID(TAG_SPECIAL, 0x3000); | |
482 | } | |
483 | else if(!strcmp(dt->name, "platinum")) { | |
484 | id = MAKE_ID(TAG_SPECIAL, 0x3001); | |
485 | } | |
486 | } | |
487 | ||
488 | if(id) { | |
489 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
490 | hd->bus.id = bus_none; | |
491 | hd->base_class.id = bc_display; | |
492 | hd->sub_class.id = sc_dis_other; | |
493 | ||
494 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x0401); | |
495 | hd->device.id = id; | |
496 | hd->rom_id = new_str(dt->path); | |
497 | if(dt->interrupt) { | |
498 | res = add_res_entry(&hd->res, new_mem(sizeof *res)); | |
499 | res->irq.type = res_irq; | |
500 | res->irq.enabled = 1; | |
501 | res->irq.base = dt->interrupt; | |
502 | } | |
503 | ||
504 | return 1; | |
505 | } | |
506 | } | |
507 | ||
508 | return 0; | |
509 | } | |
510 | ||
511 | int add_prom_vscsi(hd_data_t *hd_data, devtree_t *dt) | |
512 | { | |
513 | hd_t *hd; | |
514 | char *s, *id; | |
515 | ||
516 | if( | |
517 | dt->path && | |
518 | dt->device_type && | |
519 | !strcmp(dt->device_type, "vscsi") | |
520 | ) { | |
521 | /* vscsi storage */ | |
522 | ||
523 | if( | |
524 | (s = strstr(dt->path, "v-scsi@")) && | |
525 | *(id = s + sizeof "v-scsi@" - 1) | |
526 | ) { | |
527 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
528 | hd->bus.id = bus_none; | |
529 | hd->base_class.id = bc_storage; | |
530 | hd->sub_class.id = sc_sto_scsi; | |
531 | hd->slot = veth_cnt++; | |
532 | ||
533 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001); | |
534 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x1001); | |
535 | str_printf(&hd->device.name, 0, "Virtual SCSI %d", hd->slot); | |
536 | hd->rom_id = new_str(dt->path); | |
537 | ||
538 | str_printf(&hd->sysfs_id, 0, "/devices/vio/%s", id); | |
539 | ||
540 | return 1; | |
541 | } | |
542 | } | |
543 | ||
544 | return 0; | |
545 | } | |
546 | ||
547 | int add_prom_veth(hd_data_t *hd_data, devtree_t *dt) | |
548 | { | |
549 | hd_t *hd; | |
550 | char *s, *id; | |
551 | ||
552 | if( | |
553 | dt->path && | |
554 | dt->device_type && | |
555 | dt->compatible && | |
556 | !strcmp(dt->device_type, "network") && | |
557 | !strcmp(dt->compatible, "IBM,l-lan") | |
558 | ) { | |
559 | /* veth network */ | |
560 | ||
561 | if( | |
562 | (s = strstr(dt->path, "l-lan@")) && | |
563 | *(id = s + sizeof "l-lan@" - 1) | |
564 | ) { | |
565 | hd = add_hd_entry(hd_data, __LINE__, 0); | |
566 | hd->bus.id = bus_none; | |
567 | hd->base_class.id = bc_network; | |
568 | hd->sub_class.id = 0x00; | |
569 | hd->slot = veth_cnt++; | |
570 | ||
571 | hd->vendor.id = MAKE_ID(TAG_SPECIAL, 0x6001); | |
572 | hd->device.id = MAKE_ID(TAG_SPECIAL, 0x1002); | |
573 | str_printf(&hd->device.name, 0, "Virtual Ethernet card %d", hd->slot); | |
574 | hd->rom_id = new_str(dt->path); | |
575 | ||
576 | str_printf(&hd->sysfs_id, 0, "/devices/vio/%s", id); | |
577 | ||
578 | return 1; | |
579 | } | |
580 | } | |
581 | ||
582 | return 0; | |
583 | } | |
584 | ||
585 | void add_devices(hd_data_t *hd_data) | |
586 | { | |
587 | hd_t *hd; | |
588 | devtree_t *dt; | |
589 | #if 0 | |
590 | hd_res_t *res; | |
591 | unsigned pci_slot = 0, u; | |
592 | #endif | |
593 | ||
594 | /* remove old assignments */ | |
595 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
596 | if(ID_TAG(hd->device.id) == TAG_PCI && ID_TAG(hd->vendor.id) == TAG_PCI) { | |
597 | hd->rom_id = free_mem(hd->rom_id); | |
598 | hd->detail = free_hd_detail(hd->detail); | |
599 | } | |
600 | } | |
601 | ||
602 | for(dt = hd_data->devtree; dt; dt = dt->next) { | |
603 | if(dt->pci) { | |
604 | for(hd = hd_data->hd; hd; hd = hd->next) { | |
605 | if( | |
606 | /* do *not* compare class ids */ | |
607 | /* It would be better to check the slot numbers instead but | |
608 | * as they are not stored within /proc/device-tree in a consistent | |
609 | * way, we can't do that. | |
610 | */ | |
611 | !hd->rom_id && | |
612 | ID_TAG(hd->device.id) == TAG_PCI && | |
613 | ID_TAG(hd->vendor.id) == TAG_PCI && | |
614 | ID_VALUE(hd->device.id) == dt->device_id && | |
615 | ID_VALUE(hd->vendor.id) == dt->vendor_id && | |
616 | (dt->subvendor_id == -1 || ID_VALUE(hd->sub_vendor.id) == dt->subvendor_id) && | |
617 | (dt->subdevice_id == -1 || ID_VALUE(hd->sub_device.id) == dt->subdevice_id) && | |
618 | hd->revision.id == dt->revision_id | |
619 | ) break; | |
620 | } | |
621 | ||
622 | if(hd) { | |
623 | hd->rom_id = new_str(dt->path); | |
624 | hd->detail = new_mem(sizeof *hd->detail); | |
625 | hd->detail->type = hd_detail_devtree; | |
626 | hd->detail->devtree.data = dt; | |
627 | add_pci_prom_devices(hd_data, hd, dt); | |
628 | } | |
629 | } | |
630 | else { | |
631 | add_legacy_prom_devices(hd_data, dt); | |
632 | } | |
633 | } | |
634 | } | |
635 | ||
636 | void dump_devtree_data(hd_data_t *hd_data) | |
637 | { | |
638 | unsigned u; | |
639 | devtree_t *devtree; | |
640 | ||
641 | devtree = hd_data->devtree; | |
642 | if(!devtree) return; | |
643 | ||
644 | ADD2LOG("----- /proc device tree -----\n"); | |
645 | ||
646 | for(; devtree; devtree = devtree->next) { | |
647 | u = devtree->parent ? devtree->parent->idx : 0; | |
648 | ADD2LOG(" %02u @%02u %s", devtree->idx, u, devtree->path); | |
649 | if(devtree->pci) ADD2LOG(" [pci]"); | |
650 | ADD2LOG("\n"); | |
651 | ||
652 | ADD2LOG( | |
653 | " name \"%s\", model \"%s\", dtype \"%s\", compat \"%s\"\n", | |
654 | devtree->name ? devtree->name : "", | |
655 | devtree->model ? devtree->model : "", | |
656 | devtree->device_type ? devtree->device_type : "", | |
657 | devtree->compatible ? devtree->compatible : "" | |
658 | ); | |
659 | ||
660 | if( | |
661 | devtree->class_code != -1 || devtree->vendor_id != -1 || | |
662 | devtree->device_id != -1 || devtree->revision_id != -1 || | |
663 | devtree->subdevice_id != -1 || devtree->subvendor_id != -1 || | |
664 | devtree->interrupt != -1 | |
665 | ) { | |
666 | ADD2LOG(" "); | |
667 | if(devtree->class_code != -1) ADD2LOG(" class 0x%06x", devtree->class_code); | |
668 | if(devtree->vendor_id != -1) ADD2LOG(" vend 0x%04x", devtree->vendor_id); | |
669 | if(devtree->device_id != -1) ADD2LOG(" dev 0x%04x", devtree->device_id); | |
670 | if(devtree->subvendor_id != -1) ADD2LOG(" svend 0x%04x", devtree->subvendor_id); | |
671 | if(devtree->subdevice_id != -1) ADD2LOG(" sdev 0x%04x", devtree->subdevice_id); | |
672 | if(devtree->revision_id != -1) ADD2LOG(" rev 0x%02x", devtree->revision_id); | |
673 | if(devtree->interrupt != -1) ADD2LOG(" irq %d", devtree->interrupt); | |
674 | ADD2LOG("\n"); | |
675 | } | |
676 | ||
677 | if(devtree->edid) { | |
678 | ADD2LOG(" EDID record:\n"); | |
679 | for(u = 0; u < 0x80; u += 0x10) { | |
680 | ADD2LOG(" %02x ", u); | |
681 | hexdump(&hd_data->log, 1, 0x10, devtree->edid + u); | |
682 | ADD2LOG("\n"); | |
683 | } | |
684 | } | |
685 | ||
686 | if(devtree->next) ADD2LOG("\n"); | |
687 | } | |
688 | ||
689 | ADD2LOG("----- /proc device tree end -----\n"); | |
690 | } | |
691 | ||
692 | ||
693 | #endif /* defined(__PPC__) */ | |
694 |