- parse id files in /var/lib/hardware/ids
[opensuse:hwinfo.git] / src / hd / hd.c
1 #define _GNU_SOURCE             /* canonicalize_file_name(), strcasestr() */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <stdarg.h>
7 #include <fcntl.h>
8 #include <signal.h>
9 #include <ctype.h>
10 #include <errno.h>
11 #include <dirent.h>
12 #include <time.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <sys/time.h>
17 #include <sys/ioctl.h>
18 #include <sys/mount.h>
19 #include <sys/ipc.h>
20 #include <sys/shm.h>
21 #include <sys/mman.h>
22 #include <linux/pci.h>
23 #include <linux/hdreg.h>
24 #define _LINUX_AUDIT_H_
25 #define _LINUX_PRIO_TREE_H
26 #include <linux/fs.h>
27
28 /**
29  * @defgroup libhdBUSint Bus scanning code
30  * @ingroup libhdInternals
31  */
32
33 /**
34  * @defgroup libhdDEVint Device handling
35  * @ingroup libhdInternals
36  */
37
38 /**
39  * @defgroup libhdINFOint Information gathering
40  * @ingroup libhdInternals
41  */
42
43 /**
44  * @defgroup libhdInternals Implementation internals
45  *
46  * various functions commmon to all probing modules
47  *
48  * @{
49  */
50
51 #define u64 uint64_t
52
53 #ifndef BLKSSZGET
54 #define BLKSSZGET _IO(0x12,104)         /* get block device sector size */
55 #endif
56
57 #include "hd.h"
58 #include "hddb.h"
59 #include "hd_int.h"
60 #include "smbios.h"
61 #include "memory.h"
62 #include "isapnp.h"
63 #include "monitor.h"
64 #include "cpu.h"
65 #include "misc.h"
66 #include "mouse.h"
67 #include "floppy.h"
68 #include "bios.h"
69 #include "serial.h"
70 #include "net.h"
71 #include "version.h"
72 #include "usb.h"
73 #include "modem.h"
74 #include "parallel.h"
75 #include "isa.h"
76 #include "isdn.h"
77 #include "kbd.h"
78 #include "prom.h"
79 #include "sbus.h"
80 #include "int.h"
81 #include "braille.h"
82 #include "sys.h"
83 #include "manual.h"
84 #include "fb.h"
85 #include "pppoe.h"
86 #include "pcmcia.h"
87 #include "s390.h"
88 #include "pci.h"
89 #include "block.h"
90 #include "edd.h"
91 #include "input.h"
92 #include "wlan.h"
93 #include "hal.h"
94 #include "klog.h"
95
96 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97  * various functions commmon to all probing modules
98  *
99  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100  */
101
102 #ifdef __i386__
103 #define HD_ARCH "ia32"
104 #endif
105
106 #ifdef __ia64__
107 #define HD_ARCH "ia64"
108 #endif
109
110 #ifdef __alpha__
111 #define HD_ARCH "axp"
112 #endif
113
114 #ifdef __PPC__
115 #define HD_ARCH "ppc"
116 #endif
117
118 #ifdef __sparc__
119 #define HD_ARCH "sparc"
120 #endif
121
122 #ifdef __s390x__
123 #define HD_ARCH "s390x"
124 #else
125 #ifdef __s390__
126 #define HD_ARCH "s390"
127 #endif
128 #endif
129
130 #ifdef __arm__
131 #define HD_ARCH "arm"
132 #endif
133
134 #ifdef __mips__
135 #define HD_ARCH "mips"
136 #endif
137
138 #ifdef __x86_64__
139 #define HD_ARCH "x86-64"
140 #endif
141
142 #ifdef __hppa__
143 #define HD_ARCH "hppa"
144 #endif
145
146 typedef struct disk_s {
147   struct disk_s *next;
148   unsigned crc;
149   unsigned crc_match:1;
150   unsigned hd_idx;
151   char *dev_name;
152   unsigned char *data;
153 } disk_t;
154
155 typedef struct {
156   enum probe_feature val, parent;
157   unsigned mask;        /* bit 0: default, bit 1: all, bit 2: max, bit 3: linuxrc */
158   char *name;
159   hal_prop_type_t type;
160 } pr_flags_t;
161
162 static pr_flags_t *pr_flags_by_name(char *name);
163 static pr_flags_t *pr_flags_by_id(enum probe_feature feature);
164 static int set_probe_val(hd_data_t *hd_data, enum probe_feature feature, char *val);
165 static void fix_probe_features(hd_data_t *hd_data);
166 static void set_probe_feature(hd_data_t *hd_data, enum probe_feature feature, unsigned val);
167 static void free_old_hd_entries(hd_data_t *hd_data);
168 static hd_t *free_hd_entry(hd_t *hd);
169 static hd_t *add_hd_entry2(hd_t **hd, hd_t *new_hd);
170 static void timeout_alarm_handler(int signal);
171 static void get_probe_env(hd_data_t *hd_data);
172 static void hd_scan_xtra(hd_data_t *hd_data);
173 static hd_t *hd_get_device_by_id(hd_data_t *hd_data, char *id);
174 static int has_item(hd_hw_item_t *items, hd_hw_item_t item);
175 static int has_hw_class(hd_t *hd, hd_hw_item_t *items);
176 static void hd_scan_with_hal(hd_data_t *hd_data);
177 static void hd_scan_no_hal(hd_data_t *hd_data);
178
179 static void test_read_block0_open(void *arg);
180 static void get_kernel_version(hd_data_t *hd_data);
181 static int is_modem(hd_data_t *hd_data, hd_t *hd);
182 static int is_audio(hd_data_t *hd_data, hd_t *hd);
183 static int is_pppoe(hd_data_t *hd_data, hd_t *hd);
184 static void assign_hw_class(hd_data_t *hd_data, hd_t *hd);
185 static void short_vendor(char *vendor);
186 static void create_model_name(hd_data_t *hd_data, hd_t *hd);
187
188 static void copy_log2shm(hd_data_t *hd_data);
189 static void sigchld_handler(int);
190 static void sigusr1_handler(int);
191 static pid_t child_id;
192 static volatile pid_t child;
193 static char *hd_shm_add_str(hd_data_t *hd_data, char *str);
194 static str_list_t *hd_shm_add_str_list(hd_data_t *hd_data, str_list_t *sl);
195
196 static hd_udevinfo_t *hd_free_udevinfo(hd_udevinfo_t *ui);
197 static hd_sysfsdrv_t *hd_free_sysfsdrv(hd_sysfsdrv_t *sf);
198
199 static hd_data_t *hd_data_sig;
200
201 /*
202  * Names of the probing modules.
203  * Cf. enum mod_idx in hd_int.h.
204  */
205 static struct s_mod_names {
206   unsigned val;
207   char *name;
208 } pr_modules[] = {
209   { mod_none, "none"},
210   { mod_memory, "memory"},
211   { mod_pci, "pci"},
212   { mod_isapnp, "isapnp"},
213   { mod_pnpdump, "pnpdump"},
214   { mod_net, "net"},
215   { mod_floppy, "floppy"},
216   { mod_misc, "misc" },
217   { mod_bios, "bios"},
218   { mod_cpu, "cpu"},
219   { mod_monitor, "monitor"},
220   { mod_serial, "serial"},
221   { mod_mouse, "mouse"},
222   { mod_scsi, "scsi"},
223   { mod_usb, "usb"},
224   { mod_modem, "modem"},
225   { mod_parallel, "parallel" },
226   { mod_isa, "isa" },
227   { mod_isdn, "isdn" },
228   { mod_kbd, "kbd" },
229   { mod_prom, "prom" },
230   { mod_sbus, "sbus" },
231   { mod_int, "int" },
232   { mod_braille, "braille" },
233   { mod_xtra, "hd" },
234   { mod_sys, "sys" },
235   { mod_manual, "manual" },
236   { mod_fb, "fb" },
237   { mod_pppoe, "pppoe" },
238   { mod_pcmcia, "pcmcia" },
239   { mod_s390, "s390" },
240   { mod_sysfs, "sysfs" },
241   { mod_dsl, "dsl" },
242   { mod_block, "block" },
243   { mod_edd, "edd" },
244   { mod_input, "input" },
245   { mod_hal, "hal" },
246   { mod_wlan, "wlan" }
247 };
248
249 /*
250  * Names for the probe flags. Used for debugging and command line parsing in
251  * hw.c. Cf. enum probe_feature, hd_data_t.probe.
252  */
253
254 static pr_flags_t pr_flags[] = {
255   { pr_default,      -1,                  1, "default",      p_bool },
256   { pr_all,          -1,                2  , "all",          p_bool },
257   { pr_max,          -1,              4    , "max",          p_bool },
258   { pr_lxrc,         -1,            8      , "lxrc",         p_bool },
259   { pr_memory,        0,            8|4|2|1, "memory",       p_bool },
260   { pr_pci,           0,            8|4|2|1, "pci",          p_bool },
261   { pr_s390,          0,            8|4|2|1, "s390",         p_bool },
262   { pr_s390disks,     0,                  0, "s390disks",    p_bool },
263   { pr_isapnp,        0,              4|2|1, "isapnp",       p_bool },
264   { pr_isapnp_old,    pr_isapnp,          0, "isapnp.old",   p_bool },
265   { pr_isapnp_new,    pr_isapnp,          0, "isapnp.new",   p_bool },
266   { pr_isapnp_mod,    0,              4    , "isapnp.mod",   p_bool },
267   { pr_isapnp,        0,                  0, "pnpdump",      p_bool },  /* alias for isapnp */
268   { pr_net,           0,            8|4|2|1, "net",          p_bool },
269   { pr_net_eeprom,    0,                  0, "net.eeprom",   p_bool },
270   { pr_floppy,        0,            8|4|2|1, "floppy",       p_bool },
271   { pr_misc,          pr_bios,      8|4|2|1, "misc",         p_bool },  // ugly hack!
272   { pr_misc_serial,   pr_misc,      8|4|2|1, "misc.serial",  p_bool },
273   { pr_misc_par,      pr_misc,        4|2|1, "misc.par",     p_bool },
274   { pr_misc_floppy,   pr_misc,      8|4|2|1, "misc.floppy",  p_bool },
275   { pr_bios,          0,            8|4|2|1, "bios",         p_bool },
276   { pr_bios_vesa,     pr_bios,        4|2|1, "bios.vesa",    p_bool },
277   { pr_bios_ddc,      pr_bios_vesa,       0, "bios.ddc",     p_bool },
278   { pr_bios_ddc_ports, pr_bios_ddc,       0, "bios.ddc.ports", p_int32 },
279   { pr_bios_fb,       pr_bios_vesa,       0, "bios.fb",      p_bool },
280   { pr_bios_mode,     pr_bios_vesa,       0, "bios.mode",    p_bool },
281   { pr_bios_vbe,      pr_bios_mode,       0, "bios.vbe",     p_bool }, // just an alias
282   { pr_bios_crc,      0,                  0, "bios.crc",     p_bool }, // require bios crc check to succeed
283   { pr_bios_vram,     0,                  0, "bios.vram",    p_bool }, // map video bios ram
284   { pr_bios_acpi,     0,                  0, "bios.acpi",    p_bool }, // dump acpi data
285   { pr_cpu,           0,            8|4|2|1, "cpu",          p_bool },
286   { pr_monitor,       0,            8|4|2|1, "monitor",      p_bool },
287   { pr_serial,        0,              4|2|1, "serial",       p_bool },
288   { pr_mouse,         0,              4|2|1, "mouse",        p_bool },
289   { pr_scsi,          0,            8|4|2|1, "scsi",         p_bool },
290   { pr_scsi_noserial, 0,                  0, "scsi.noserial", p_bool },
291   { pr_usb,           0,            8|4|2|1, "usb",          p_bool },
292   { pr_usb_mods,      0,              4    , "usb.mods",     p_bool },
293   { pr_modem,         0,              4|2|1, "modem",        p_bool },
294   { pr_modem_usb,     pr_modem,       4|2|1, "modem.usb",    p_bool },
295   { pr_parallel,      0,              4|2|1, "parallel",     p_bool },
296   { pr_parallel_lp,   pr_parallel,    4|2|1, "parallel.lp",  p_bool },
297   { pr_parallel_zip,  pr_parallel,    4|2|1, "parallel.zip", p_bool },
298   { pr_parallel_imm,  0,                  0, "parallel.imm", p_bool },
299   { pr_isa,           0,                  0, "isa",          p_bool },
300   { pr_isa_isdn,      pr_isa,             0, "isa.isdn",     p_bool },
301   { pr_isdn,          0,              4|2|1, "isdn",         p_bool },
302   { pr_kbd,           0,            8|4|2|1, "kbd",          p_bool },
303   { pr_prom,          0,            8|4|2|1, "prom",         p_bool },
304   { pr_sbus,          0,            8|4|2|1, "sbus",         p_bool },
305   { pr_int,           0,            8|4|2|1, "int",          p_bool },
306 #if defined(__i386__) || defined (__x86_64__)
307   { pr_braille,       0,              4|2|1, "braille",      p_bool },
308   { pr_braille_alva,  pr_braille,     4|2|1, "braille.alva", p_bool },
309   { pr_braille_fhp,   pr_braille,     4|2|1, "braille.fhp",  p_bool },
310   { pr_braille_ht,    pr_braille,     4|2|1, "braille.ht",   p_bool },
311   { pr_braille_baum,  pr_braille,     4|2|1, "braille.baum", p_bool },
312 #else
313   { pr_braille,       0,              4|2  , "braille",      p_bool },
314   { pr_braille_alva,  pr_braille,         0, "braille.alva", p_bool },
315   { pr_braille_fhp,   pr_braille,     4|2  , "braille.fhp",  p_bool },
316   { pr_braille_ht,    pr_braille,     4|2  , "braille.ht",   p_bool },
317   { pr_braille_baum,  pr_braille,     4|2  , "braille.baum", p_bool },
318 #endif
319   { pr_ignx11,        0,                  0, "ignx11",       p_bool },
320   { pr_sys,           0,            8|4|2|1, "sys",          p_bool },
321   { pr_manual,        0,                  0, "manual",       p_bool },
322   { pr_fb,            0,            8|4|2|1, "fb",           p_bool },
323   { pr_pppoe,         0,            8|4|2|1, "pppoe",        p_bool },
324   /* dummy, used to turn off hwscan */
325   { pr_scan,          0,                  0, "scan",         p_bool },
326   { pr_pcmcia,        0,            8|4|2|1, "pcmcia",       p_bool },
327   { pr_fork,          0,                  0, "fork",         p_bool },
328   { pr_cpuemu,        0,                  0, "cpuemu",       p_bool },
329   { pr_cpuemu_debug,  pr_cpuemu,          0, "cpuemu.debug", p_bool },
330   { pr_sysfs,         0,                  0, "sysfs",        p_bool },
331   { pr_udev,          0,            8|4|2|1, "udev",         p_bool },
332   { pr_block,         0,            8|4|2|1, "block",        p_bool },
333   { pr_block_cdrom,   pr_block,     8|4|2|1, "block.cdrom",  p_bool },
334   { pr_block_part,    pr_block,     8|4|2|1, "block.part",   p_bool },
335   { pr_block_mods,    pr_block,     8|4|2|1, "block.mods",   p_bool },
336   { pr_edd,           0,            8|4|2|1, "edd",          p_bool },
337   { pr_edd_mod,       pr_edd,       8|4|2|1, "edd.mod",      p_bool },
338   { pr_input,         0,            8|4|2|1, "input",        p_bool },
339   { pr_wlan,          0,            8|4|2|1, "wlan",         p_bool },
340   { pr_hal,           0,                  0, "hal",          p_bool },
341   { pr_modules_pata,  0,                  0, "modules.pata", p_bool },
342   { pr_x86emu,        0,                  0, "x86emu",       p_list },
343 };
344
345
346 /*
347  * Returns pointer to probe feature struct for name.
348  * If name is not a valid probe feature, NULL is returned.
349  *
350  */
351 pr_flags_t *pr_flags_by_name(char *name)
352 {
353   unsigned u;
354
355   if(!name) return NULL;
356
357   for(u = 0; u < sizeof pr_flags / sizeof *pr_flags; u++) {
358     if(!strcmp(name, pr_flags[u].name)) return pr_flags + u;
359   }
360
361   return NULL;
362 }
363
364
365 pr_flags_t *pr_flags_by_id(enum probe_feature feature)
366 {
367   unsigned u;
368
369   for(u = 0; u < sizeof pr_flags / sizeof *pr_flags; u++) {
370     if(feature == pr_flags[u].val) return pr_flags + u;
371   }
372
373   return NULL;
374 }
375
376
377 int get_probe_val_int(hd_data_t *hd_data, enum probe_feature feature)
378 {
379   pr_flags_t *flags;
380   hal_prop_t *prop;
381
382   flags = pr_flags_by_id(feature);
383   if(flags) {
384     prop = hal_get_int32(hd_data->probe_val, flags->name);
385     if(prop) return prop->val.int32;
386   }
387
388   return 0;
389 }
390
391
392 char *get_probe_val_str(hd_data_t *hd_data, enum probe_feature feature)
393 {
394   pr_flags_t *flags;
395   hal_prop_t *prop;
396
397   flags = pr_flags_by_id(feature);
398   if(flags) {
399     prop = hal_get_str(hd_data->probe_val, flags->name);
400     if(prop) return prop->val.str;
401   }
402
403   return NULL;
404 }
405
406
407 str_list_t *get_probe_val_list(hd_data_t *hd_data, enum probe_feature feature)
408 {
409   pr_flags_t *flags;
410   hal_prop_t *prop;
411
412   flags = pr_flags_by_id(feature);
413   if(flags) {
414     prop = hal_get_list(hd_data->probe_val, flags->name);
415     if(prop) return prop->val.list;
416   }
417
418   return NULL;
419 }
420
421
422 int set_probe_val(hd_data_t *hd_data, enum probe_feature feature, char *val)
423 {
424   hal_prop_t *prop;
425   pr_flags_t *flags;
426   char *s;
427   int i, is_set = 0;
428
429   if(!val) val = "";
430
431   flags = pr_flags_by_id(feature);
432   if(flags && flags->type != p_bool) {
433     prop = hal_get_any(hd_data->probe_val, flags->name);
434     if(!prop) {
435       prop = hal_add_new(&hd_data->probe_val);
436     }
437     else {
438       hal_invalidate(prop);
439     }
440     switch(flags->type) {
441       case p_int32:
442         i = strtol(val, &s, 0);
443         if(!*s) {
444           prop->type = flags->type;
445           prop->key = new_str(flags->name);
446           prop->val.int32 = i;
447           is_set = i ? 1 : 0;
448         }
449         break;
450
451       case p_string:
452         prop->type = flags->type;
453         prop->key = new_str(flags->name);
454         prop->val.str = new_str(val);
455         is_set = *val ? 1 : 0;
456         break;
457
458       case p_list:
459         prop->type = flags->type;
460         prop->key = new_str(flags->name);
461         prop->val.list = *val ? hd_split(':', val) : NULL;
462         is_set = prop->val.list ? 1 : 0;
463         break;
464
465       default:
466         break;
467     }
468   }
469
470   return is_set;
471 }
472
473
474 void fix_probe_features(hd_data_t *hd_data)
475 {
476   int i;
477
478   for(i = 0; i < sizeof hd_data->probe; i++) {
479     hd_data->probe[i] |= hd_data->probe_set[i];
480     hd_data->probe[i] &= ~hd_data->probe_clr[i];
481   }
482 }
483
484
485 void set_probe_feature(hd_data_t *hd_data, enum probe_feature feature, unsigned val)
486 {
487   unsigned ofs, bit, mask;
488   int i;
489   pr_flags_t *pr;
490
491   if(!(pr = pr_flags_by_id(feature))) return;
492
493   if(pr->parent == -1u) {
494     mask = pr->mask;
495     for(i = 0; (unsigned) i < sizeof pr_flags / sizeof *pr_flags; i++) {
496       if(pr_flags[i].parent != -1u && (pr_flags[i].mask & mask))
497         set_probe_feature(hd_data, pr_flags[i].val, val);
498     }
499   }
500   else {
501     ofs = feature >> 3; bit = feature & 7;
502     if(ofs < sizeof hd_data->probe) {
503       if(val) {
504         hd_data->probe_set[ofs] |= 1 << bit;
505         hd_data->probe_clr[ofs] &= ~(1 << bit);
506       }
507       else {
508         hd_data->probe_clr[ofs] |= 1 << bit;
509         hd_data->probe_set[ofs] &= ~(1 << bit);
510       }
511     }
512     if(pr->parent) set_probe_feature(hd_data, pr->parent, val);
513   }
514
515   fix_probe_features(hd_data);
516 }
517
518
519 void hd_set_probe_feature(hd_data_t *hd_data, enum probe_feature feature)
520 {
521   unsigned ofs, bit, mask;
522   int i;
523   pr_flags_t *pr;
524
525   if(!(pr = pr_flags_by_id(feature))) return;
526
527   if(pr->parent == -1u) {
528     mask = pr->mask;
529     for(i = 0; i < sizeof pr_flags / sizeof *pr_flags; i++) {
530       if(pr_flags[i].parent != -1u && (pr_flags[i].mask & mask)) {
531         hd_set_probe_feature(hd_data, pr_flags[i].val);
532       }
533     }
534   }
535   else {
536     ofs = feature >> 3; bit = feature & 7;
537     if(ofs < sizeof hd_data->probe) {
538       hd_data->probe[ofs] |= 1 << bit;
539     }
540     if(pr->parent) hd_set_probe_feature(hd_data, pr->parent);
541   }
542
543   fix_probe_features(hd_data);
544 }
545
546
547 void hd_clear_probe_feature(hd_data_t *hd_data, enum probe_feature feature)
548 {
549   unsigned ofs, bit, mask;
550   int i;
551   pr_flags_t *pr;
552
553   if(!(pr = pr_flags_by_id(feature))) return;
554
555   if(pr->parent == -1u) {
556     mask = pr->mask;
557     for(i = 0; (unsigned) i < sizeof pr_flags / sizeof *pr_flags; i++) {
558       if(pr_flags[i].parent != -1u && (pr_flags[i].mask & mask))
559         hd_clear_probe_feature(hd_data, pr_flags[i].val);
560     }
561   }
562   else {
563     ofs = feature >> 3; bit = feature & 7;
564     if(ofs < sizeof hd_data->probe)
565       hd_data->probe[ofs] &= ~(1 << bit);
566   }
567 }
568
569
570 int hd_probe_feature(hd_data_t *hd_data, enum probe_feature feature)
571 {
572   if(feature < 0 || feature >= pr_default) return 0;
573
574   return hd_data->probe[feature >> 3] & (1 << (feature & 7)) ? 1 : 0;
575 }
576
577
578 void hd_set_probe_feature_hw(hd_data_t *hd_data, hd_hw_item_t item)
579 {
580   hd_set_probe_feature(hd_data, pr_int);
581 //  hd_set_probe_feature(hd_data, pr_manual);
582
583 /*
584  * note: pr_serial needs pr_pci
585  */
586
587   switch(item) {
588     case hw_cdrom:
589       hd_set_probe_feature(hd_data, pr_pci);
590       hd_set_probe_feature(hd_data, pr_usb);
591       hd_set_probe_feature(hd_data, pr_block_mods);
592       hd_set_probe_feature(hd_data, pr_scsi);
593       if(!hd_data->flags.fast) {
594         hd_set_probe_feature(hd_data, pr_block_cdrom);
595       }
596       break;
597
598     case hw_floppy:
599       hd_set_probe_feature(hd_data, pr_floppy);
600       hd_set_probe_feature(hd_data, pr_misc_floppy);
601       hd_set_probe_feature(hd_data, pr_prom);
602       hd_set_probe_feature(hd_data, pr_pci);
603       hd_set_probe_feature(hd_data, pr_usb);
604       hd_set_probe_feature(hd_data, pr_block);
605       hd_set_probe_feature(hd_data, pr_block_mods);
606       hd_set_probe_feature(hd_data, pr_scsi);
607       break;
608
609     case hw_partition:
610       hd_set_probe_feature(hd_data, pr_block_part);
611
612     case hw_disk:
613       hd_set_probe_feature(hd_data, pr_s390disks);
614       hd_set_probe_feature(hd_data, pr_bios);           // bios disk order
615       hd_set_probe_feature(hd_data, pr_pci);
616       hd_set_probe_feature(hd_data, pr_usb);
617       hd_set_probe_feature(hd_data, pr_block);
618       hd_set_probe_feature(hd_data, pr_block_mods);
619       hd_set_probe_feature(hd_data, pr_edd_mod);
620       hd_set_probe_feature(hd_data, pr_scsi);
621       break;
622
623     case hw_block:
624       hd_set_probe_feature(hd_data, pr_prom);
625       hd_set_probe_feature(hd_data, pr_s390disks);
626       hd_set_probe_feature(hd_data, pr_bios);           // bios disk order
627       hd_set_probe_feature(hd_data, pr_pci);
628       hd_set_probe_feature(hd_data, pr_usb);
629       hd_set_probe_feature(hd_data, pr_block);
630       hd_set_probe_feature(hd_data, pr_block_mods);
631       hd_set_probe_feature(hd_data, pr_edd_mod);
632       hd_set_probe_feature(hd_data, pr_scsi);
633       if(!hd_data->flags.fast) {
634         hd_set_probe_feature(hd_data, pr_floppy);
635         hd_set_probe_feature(hd_data, pr_misc_floppy);
636         hd_set_probe_feature(hd_data, pr_block_cdrom);
637       }
638       hd_set_probe_feature(hd_data, pr_block_part);
639       break;
640
641     case hw_network:
642       hd_set_probe_feature(hd_data, pr_net);
643       hd_set_probe_feature(hd_data, pr_pci);
644       hd_set_probe_feature(hd_data, pr_prom);
645       hd_set_probe_feature(hd_data, pr_usb);
646       break;
647
648     case hw_display:
649       hd_set_probe_feature(hd_data, pr_pci);
650       hd_set_probe_feature(hd_data, pr_sbus);
651       hd_set_probe_feature(hd_data, pr_prom);
652       hd_set_probe_feature(hd_data, pr_misc);           /* for isa cards */
653       break;
654
655     case hw_monitor:
656       hd_set_probe_feature(hd_data, pr_misc);
657       hd_set_probe_feature(hd_data, pr_prom);
658       hd_set_probe_feature(hd_data, pr_pci);
659       hd_set_probe_feature(hd_data, pr_bios_ddc);
660       // hd_set_probe_feature(hd_data, pr_bios_fb);
661       hd_set_probe_feature(hd_data, pr_fb);
662       hd_set_probe_feature(hd_data, pr_monitor);
663       break;
664
665     case hw_framebuffer:
666       hd_set_probe_feature(hd_data, pr_misc);
667       hd_set_probe_feature(hd_data, pr_prom);
668       hd_set_probe_feature(hd_data, pr_pci);
669       hd_set_probe_feature(hd_data, pr_bios_fb);
670       hd_set_probe_feature(hd_data, pr_fb);
671       break;
672
673     case hw_mouse:
674       hd_set_probe_feature(hd_data, pr_misc);
675       if(!hd_data->flags.fast) {
676         hd_set_probe_feature(hd_data, pr_serial);
677       }
678       hd_set_probe_feature(hd_data, pr_usb);
679       hd_set_probe_feature(hd_data, pr_kbd);
680       hd_set_probe_feature(hd_data, pr_sys);
681       hd_set_probe_feature(hd_data, pr_bios);
682       hd_set_probe_feature(hd_data, pr_mouse);
683       hd_set_probe_feature(hd_data, pr_input);
684       hd_set_probe_feature(hd_data, pr_pci);
685       break;
686
687     case hw_joystick:
688       hd_set_probe_feature(hd_data, pr_usb);
689       hd_set_probe_feature(hd_data, pr_input);
690       break;
691
692     case hw_chipcard:
693       hd_set_probe_feature(hd_data, pr_misc);
694       if(!hd_data->flags.fast) {
695         hd_set_probe_feature(hd_data, pr_serial);
696       }
697       hd_set_probe_feature(hd_data, pr_usb);
698       hd_set_probe_feature(hd_data, pr_mouse);          /* we need the pnp code */
699       hd_set_probe_feature(hd_data, pr_pci);
700       break;
701
702     case hw_camera:
703       hd_set_probe_feature(hd_data, pr_usb);
704       break;
705
706     case hw_keyboard:
707       hd_set_probe_feature(hd_data, pr_cpu);
708       hd_set_probe_feature(hd_data, pr_misc);
709       hd_set_probe_feature(hd_data, pr_usb);
710       hd_set_probe_feature(hd_data, pr_kbd);
711       hd_set_probe_feature(hd_data, pr_input);
712 #ifdef __PPC__
713       hd_set_probe_feature(hd_data, pr_serial);
714       hd_set_probe_feature(hd_data, pr_pci);
715 #endif
716       break;
717
718     case hw_sound:
719       hd_set_probe_feature(hd_data, pr_misc);
720       hd_set_probe_feature(hd_data, pr_pci);
721       hd_set_probe_feature(hd_data, pr_isapnp);
722       hd_set_probe_feature(hd_data, pr_isapnp_mod);
723       hd_set_probe_feature(hd_data, pr_usb);
724       hd_set_probe_feature(hd_data, pr_sbus);
725       hd_set_probe_feature(hd_data, pr_prom);
726       break;
727
728     case hw_isdn:
729       hd_set_probe_feature(hd_data, pr_misc);           /* get basic i/o res */
730       hd_set_probe_feature(hd_data, pr_pci);
731       hd_set_probe_feature(hd_data, pr_pcmcia);
732       hd_set_probe_feature(hd_data, pr_isapnp);
733       hd_set_probe_feature(hd_data, pr_isapnp_mod);
734       // hd_set_probe_feature(hd_data, pr_isa_isdn);
735       hd_set_probe_feature(hd_data, pr_usb);
736       hd_set_probe_feature(hd_data, pr_isdn);
737       break;
738
739     case hw_modem:
740       hd_set_probe_feature(hd_data, pr_misc);
741       hd_set_probe_feature(hd_data, pr_serial);
742       hd_set_probe_feature(hd_data, pr_usb);
743       hd_set_probe_feature(hd_data, pr_pci);
744       hd_set_probe_feature(hd_data, pr_modem);
745       hd_set_probe_feature(hd_data, pr_modem_usb);
746       break;
747
748     case hw_storage_ctrl:
749       hd_set_probe_feature(hd_data, pr_floppy);
750       hd_set_probe_feature(hd_data, pr_sys);
751       hd_set_probe_feature(hd_data, pr_pci);
752       hd_set_probe_feature(hd_data, pr_sbus);
753       if(!hd_data->flags.fast) {
754         hd_set_probe_feature(hd_data, pr_misc_par);
755         hd_set_probe_feature(hd_data, pr_parallel_zip);
756       }
757       hd_set_probe_feature(hd_data, pr_s390);
758       hd_set_probe_feature(hd_data, pr_prom);
759 #ifdef __PPC__
760       hd_set_probe_feature(hd_data, pr_misc);
761 #endif
762       break;
763
764     case hw_network_ctrl:
765       hd_set_probe_feature(hd_data, pr_misc);
766       hd_set_probe_feature(hd_data, pr_usb);
767       hd_set_probe_feature(hd_data, pr_pci);
768       hd_set_probe_feature(hd_data, pr_net);
769       hd_set_probe_feature(hd_data, pr_pcmcia);
770       hd_set_probe_feature(hd_data, pr_isapnp);
771       hd_set_probe_feature(hd_data, pr_isapnp_mod);
772       hd_set_probe_feature(hd_data, pr_sbus);
773       hd_set_probe_feature(hd_data, pr_isdn);
774       hd_set_probe_feature(hd_data, pr_prom);
775       hd_set_probe_feature(hd_data, pr_s390);
776       hd_set_probe_feature(hd_data, pr_wlan);
777       break;
778
779     case hw_printer:
780       hd_set_probe_feature(hd_data, pr_sys);
781       hd_set_probe_feature(hd_data, pr_bios);
782       hd_set_probe_feature(hd_data, pr_misc_par);
783       hd_set_probe_feature(hd_data, pr_parallel_lp);
784       hd_set_probe_feature(hd_data, pr_usb);
785       break;
786
787     case hw_wlan:
788       hd_set_probe_feature(hd_data, pr_pcmcia);
789       hd_set_probe_feature(hd_data, pr_wlan);
790       hd_set_probe_feature(hd_data, pr_pci);
791       hd_set_probe_feature(hd_data, pr_usb);
792       hd_set_probe_feature(hd_data, pr_net);
793       break;
794
795     case hw_tv:
796     case hw_dvb:
797       hd_set_probe_feature(hd_data, pr_pci);
798       break;
799
800     case hw_scanner:
801       hd_set_probe_feature(hd_data, pr_pci);
802       hd_set_probe_feature(hd_data, pr_usb);
803       hd_set_probe_feature(hd_data, pr_scsi);
804       break;
805
806     case hw_braille:
807       hd_set_probe_feature(hd_data, pr_misc_serial);
808       hd_set_probe_feature(hd_data, pr_serial);
809       hd_set_probe_feature(hd_data, pr_braille_alva);
810       hd_set_probe_feature(hd_data, pr_braille_fhp);
811       hd_set_probe_feature(hd_data, pr_braille_ht);
812       hd_set_probe_feature(hd_data, pr_braille_baum);
813       hd_set_probe_feature(hd_data, pr_usb);
814       hd_set_probe_feature(hd_data, pr_pci);
815       break;
816
817     case hw_sys:
818       hd_set_probe_feature(hd_data, pr_bios);
819       hd_set_probe_feature(hd_data, pr_prom);
820       hd_set_probe_feature(hd_data, pr_s390);
821       hd_set_probe_feature(hd_data, pr_sys);
822       break;
823
824     case hw_cpu:
825       hd_set_probe_feature(hd_data, pr_cpu);
826       break;
827
828     case hw_bios:
829       hd_set_probe_feature(hd_data, pr_bios);
830       hd_set_probe_feature(hd_data, pr_edd_mod);
831       break;
832
833     case hw_vbe:
834       hd_set_probe_feature(hd_data, pr_bios_ddc);
835       hd_set_probe_feature(hd_data, pr_bios_fb);
836       hd_set_probe_feature(hd_data, pr_bios_mode);
837       hd_set_probe_feature(hd_data, pr_monitor);
838       break;
839
840     case hw_manual:
841       hd_set_probe_feature(hd_data, pr_manual);
842       break;
843
844     case hw_usb_ctrl:
845     case hw_pcmcia_ctrl:
846     case hw_ieee1394_ctrl:
847     case hw_hotplug_ctrl:
848       hd_set_probe_feature(hd_data, pr_misc);
849       hd_set_probe_feature(hd_data, pr_pci);
850       break;
851
852     case hw_usb:
853       hd_set_probe_feature(hd_data, pr_usb);
854       hd_set_probe_feature(hd_data, pr_input);
855       hd_set_probe_feature(hd_data, pr_isdn);   // need pr_misc, too?
856       hd_set_probe_feature(hd_data, pr_block);
857       hd_set_probe_feature(hd_data, pr_block_mods);
858       hd_set_probe_feature(hd_data, pr_scsi);
859       hd_set_probe_feature(hd_data, pr_net);
860       hd_data->flags.fast = 1;
861       break;
862
863     case hw_pci:
864       hd_set_probe_feature(hd_data, pr_misc);
865       hd_set_probe_feature(hd_data, pr_pci);
866       hd_set_probe_feature(hd_data, pr_net);
867       hd_set_probe_feature(hd_data, pr_isdn);
868       hd_set_probe_feature(hd_data, pr_prom);
869       break;
870
871     case hw_isapnp:
872       hd_set_probe_feature(hd_data, pr_isapnp);
873       hd_set_probe_feature(hd_data, pr_isapnp_mod);
874       hd_set_probe_feature(hd_data, pr_misc);
875       hd_set_probe_feature(hd_data, pr_isdn);
876       break;
877
878     case hw_bridge:
879       hd_set_probe_feature(hd_data, pr_misc);
880       hd_set_probe_feature(hd_data, pr_pci);
881       break;
882
883     case hw_hub:
884       hd_set_probe_feature(hd_data, pr_usb); 
885       break;
886
887     case hw_memory:
888       hd_set_probe_feature(hd_data, pr_memory); 
889       break;
890
891     case hw_scsi:
892     case hw_tape:
893       hd_set_probe_feature(hd_data, pr_pci);
894       hd_set_probe_feature(hd_data, pr_block);
895       hd_set_probe_feature(hd_data, pr_block_mods);
896       hd_set_probe_feature(hd_data, pr_scsi);
897       hd_set_probe_feature(hd_data, pr_usb);
898       break;
899
900     case hw_ide:
901       hd_set_probe_feature(hd_data, pr_pci);
902       hd_set_probe_feature(hd_data, pr_block);
903       hd_set_probe_feature(hd_data, pr_block_mods);
904       break;
905
906     case hw_pppoe:
907       hd_set_probe_feature(hd_data, pr_net);
908       hd_set_probe_feature(hd_data, pr_pppoe);
909       break;
910
911     case hw_dsl:
912       hd_set_probe_feature(hd_data, pr_net);
913       hd_set_probe_feature(hd_data, pr_pci);
914       hd_set_probe_feature(hd_data, pr_pppoe);
915       hd_set_probe_feature(hd_data, pr_usb);
916       break;
917
918     case hw_pcmcia:
919       hd_set_probe_feature(hd_data, pr_pci);
920       hd_set_probe_feature(hd_data, pr_pcmcia);
921       hd_set_probe_feature(hd_data, pr_wlan);
922       hd_set_probe_feature(hd_data, pr_net);
923       hd_set_probe_feature(hd_data, pr_isdn);
924       break;
925
926     case hw_bluetooth:
927       hd_set_probe_feature(hd_data, pr_usb);
928       hd_set_probe_feature(hd_data, pr_isdn);   // need pr_misc, too?
929       break;
930
931     case hw_fingerprint:
932       hd_set_probe_feature(hd_data, pr_usb);
933       break;
934
935     case hw_all:
936       hd_set_probe_feature(hd_data, pr_default);
937       break;
938     
939     case hw_redasd:
940       hd_set_probe_feature(hd_data, pr_block);
941       hd_set_probe_feature(hd_data, pr_block_mods);
942       break;
943
944     case hw_none:
945     case hw_unknown:
946     case hw_ieee1394:
947     case hw_hotplug:
948     case hw_zip:
949       break;
950   }
951 }
952
953
954 /*
955  * Free all data associated with a hd_data_t struct. *Not* the struct itself.
956  */
957 hd_data_t *hd_free_hd_data(hd_data_t *hd_data)
958 {
959   modinfo_t *p;
960   unsigned u;
961
962   add_hd_entry2(&hd_data->old_hd, hd_data->hd); hd_data->hd = NULL;
963   hd_data->log = free_mem(hd_data->log);
964   free_old_hd_entries(hd_data);         /* hd_data->old_hd */
965   /* hd_data->pci is always NULL */
966   /* hd_data->isapnp->card is always NULL */
967   hd_data->isapnp = free_mem(hd_data->isapnp);
968   /* hd_data->cdrom is always NULL */
969   hd_data->net = free_str_list(hd_data->net);
970   hd_data->floppy = free_str_list(hd_data->floppy);
971   hd_data->misc = free_misc(hd_data->misc);
972   /* hd_data->serial is always NULL */
973   /* hd_data->scsi is always NULL */
974   /* hd_data->ser_mouse is always NULL */
975   /* hd_data->ser_modem is always NULL */
976   hd_data->cpu = free_str_list(hd_data->cpu);
977   hd_data->klog = free_str_list(hd_data->klog);
978   hd_data->klog_raw = free_str_list(hd_data->klog_raw);
979   hd_data->proc_usb = free_str_list(hd_data->proc_usb);
980   /* hd_data->usb is always NULL */
981
982   if((p = hd_data->modinfo)) {
983     for(; p->type; p++) {
984       free_mem(p->module);
985       free_mem(p->alias);
986     }
987   }
988   hd_data->modinfo = free_mem(hd_data->modinfo);
989   if((p = hd_data->modinfo_ext)) {
990     for(; p->type; p++) free_mem(p->module);
991   }
992   hd_data->modinfo = free_mem(hd_data->modinfo_ext);
993
994   if(hd_data->hddb2[0]) {
995     free_mem(hd_data->hddb2[0]->list);
996     free_mem(hd_data->hddb2[0]->ids); 
997     free_mem(hd_data->hddb2[0]->strings);
998     hd_data->hddb2[0] = free_mem(hd_data->hddb2[0]);
999   }
1000   /* hddb2[1] is the static internal database; don't try to free it! */
1001   hd_data->hddb2[1] = NULL;
1002
1003   hd_data->kmods = free_str_list(hd_data->kmods);
1004   hd_data->bios_rom.data = free_mem(hd_data->bios_rom.data);
1005   hd_data->bios_ram.data = free_mem(hd_data->bios_ram.data);
1006   hd_data->bios_ebda.data = free_mem(hd_data->bios_ebda.data);
1007   hd_data->cmd_line = free_mem(hd_data->cmd_line);
1008   hd_data->xtra_hd = free_str_list(hd_data->xtra_hd);
1009   hd_data->devtree = free_devtree(hd_data);
1010
1011 #if 0
1012   // always NULL -> manual.c
1013   for(hd = hd_data->manual; hd; hd = next) {
1014     next = hd->next;
1015     hd->next = NULL;
1016     hd_free_hd_list(hd);
1017   }
1018   hd_data->manual = NULL;
1019 #endif
1020
1021   hd_data->disks = free_str_list(hd_data->disks);
1022   hd_data->partitions = free_str_list(hd_data->partitions);
1023   hd_data->cdroms = free_str_list(hd_data->cdroms);
1024
1025   hd_data->smbios = smbios_free(hd_data->smbios);
1026
1027   hd_data->udevinfo = hd_free_udevinfo(hd_data->udevinfo);
1028   hd_data->sysfsdrv = hd_free_sysfsdrv(hd_data->sysfsdrv);
1029
1030   hd_data->only = free_str_list(hd_data->only);
1031   hd_data->scanner_db = free_str_list(hd_data->scanner_db);
1032
1033   for(u = 0; u < sizeof hd_data->edd / sizeof *hd_data->edd; u++) {
1034     hd_data->edd[u].sysfs_id = free_mem(hd_data->edd[u].sysfs_id);
1035   }
1036
1037   hd_data->hal = hd_free_hal_devices(hd_data->hal);
1038
1039   hd_data->lsscsi = free_str_list(hd_data->lsscsi);
1040
1041   hd_data->probe_val = hd_free_hal_properties(hd_data->probe_val);
1042
1043   hd_data->last_idx = 0;
1044
1045   hd_shm_done(hd_data);
1046
1047   memset(hd_data, 0, sizeof *hd_data);
1048
1049   return NULL;
1050 }
1051
1052
1053 /*
1054  * Free HAL property data.
1055  */
1056 hal_prop_t *hd_free_hal_properties(hal_prop_t *prop)
1057 {
1058   hal_prop_t *next;
1059
1060   for(; prop; prop = next) {
1061     next = prop->next;
1062
1063     free_mem(prop->key);
1064     if(prop->type == p_string) free_mem(prop->val.str);
1065     if(prop->type == p_list) free_str_list(prop->val.list);
1066     free_mem(prop);
1067   }
1068
1069   return NULL;
1070 }
1071
1072
1073 /*
1074  * Free HAL data.
1075  */
1076 hal_device_t *hd_free_hal_devices(hal_device_t *dev)
1077 {
1078   hal_device_t *next;
1079
1080   for(; dev; dev = next) {
1081     next = dev->next;
1082
1083     free_mem(dev->udi);
1084     hd_free_hal_properties(dev->prop);
1085     free_mem(dev);
1086   }
1087
1088   return NULL;
1089 }
1090
1091
1092 /*
1093  * Free all data associated with a driver_info_t struct. Even the struct itself.
1094  */
1095 driver_info_t *free_driver_info(driver_info_t *di)
1096 {
1097   driver_info_t *next;
1098
1099   for(; di; di = next) {
1100     next = di->next;
1101
1102     switch(di->any.type) {
1103       case di_any:
1104       case di_display:
1105         break;
1106
1107       case di_module:
1108         free_str_list(di->module.names);
1109         free_str_list(di->module.mod_args);
1110         free_mem(di->module.conf);
1111         break;
1112
1113       case di_mouse:
1114         free_mem(di->mouse.xf86);
1115         free_mem(di->mouse.gpm);
1116         break;
1117
1118       case di_x11:
1119         free_mem(di->x11.server);
1120         free_mem(di->x11.xf86_ver);
1121         free_str_list(di->x11.extensions);
1122         free_str_list(di->x11.options);
1123         free_str_list(di->x11.raw);
1124         free_mem(di->x11.script);
1125         break;
1126
1127       case di_isdn:
1128         free_mem(di->isdn.i4l_name);
1129         if(di->isdn.params) {
1130           isdn_parm_t *p = di->isdn.params, *next;
1131           for(; p; p = next) {
1132             next = p->next;
1133             free_mem(p->name);
1134             free_mem(p->alt_value);
1135             free_mem(p);
1136           }
1137         }
1138         break;
1139
1140       case di_dsl:
1141         free_mem(di->dsl.name);
1142         free_mem(di->dsl.mode);
1143         break;
1144
1145       case di_kbd:
1146         free_mem(di->kbd.XkbRules);
1147         free_mem(di->kbd.XkbModel);
1148         free_mem(di->kbd.XkbLayout);
1149         free_mem(di->kbd.keymap);
1150         break;
1151     }
1152
1153     free_str_list(di->any.hddb0);
1154     free_str_list(di->any.hddb1);
1155
1156     free_mem(di);
1157   }
1158
1159   return NULL;
1160 }
1161
1162
1163 int exists_hd_entry(hd_data_t *hd_data, hd_t *old_hd, hd_t *hd_ex)
1164 {
1165   hd_t *hd;
1166
1167   if(!hd_ex) return 0;
1168
1169   for(hd = hd_data->hd; hd; hd = hd->next) {
1170     if(hd == hd_ex) return 1;
1171   }
1172   for(hd = old_hd; hd; hd = hd->next) {
1173     if(hd == hd_ex) return 1;
1174   }
1175
1176   return 0;
1177 }
1178
1179
1180 /*!
1181  * \note This may not free it.
1182  */
1183 hd_t *hd_free_hd_list(hd_t *hd)
1184 {
1185   hd_t *h;
1186
1187   /* Note: hd->next should better be NULL! */
1188   if(hd && hd->tag.freeit) {
1189     free_hd_entry(hd);
1190     return free_mem(hd);
1191   }
1192
1193   /* do nothing unless the list holds only copies of hd_t entries */
1194   for(h = hd; h; h = h->next) if(!h->ref) return NULL;
1195
1196   for(; hd; hd = (h = hd)->next, free_mem(h));
1197
1198   return NULL;
1199 }
1200
1201 hd_detail_t *free_hd_detail(hd_detail_t *d)
1202 {
1203   if(!d) return NULL;
1204
1205   switch(d->type) {
1206     case hd_detail_pci: {
1207         pci_t *p = d->pci.data;
1208
1209         free_mem(p->log);
1210         free_mem(p->sysfs_id);
1211         free_mem(p->sysfs_bus_id);
1212         free_mem(p);
1213       }
1214       break;
1215
1216     case hd_detail_usb:
1217       {
1218         usb_t *u = d->usb.data;
1219
1220         if(!u->cloned) {
1221           free_str_list(u->c);
1222           free_str_list(u->e);
1223         }
1224         free_str_list(u->d);
1225         free_str_list(u->p);
1226         free_str_list(u->s);
1227         free_str_list(u->t);
1228         free_str_list(u->i);
1229
1230         free_mem(u->manufact);
1231         free_mem(u->product);
1232         free_mem(u->serial);
1233         free_mem(u->driver);
1234         free_mem(u->raw_descr.data);
1235
1236         free_mem(u);
1237       }
1238       break;
1239
1240     case hd_detail_isapnp:
1241       {
1242         isapnp_dev_t *i = d->isapnp.data;
1243         int j;
1244
1245         if(!i->ref) {
1246           free_mem(i->card->serial);
1247           free_mem(i->card->card_regs);
1248           free_mem(i->card->ldev_regs);
1249           for(j = 0; j < i->card->res_len; j++) {
1250             free_mem(i->card->res[j].data);
1251           }
1252           if(i->card->res) free_mem(i->card->res);
1253         }
1254         free_mem(i->card);
1255         free_mem(i);
1256       }
1257       break;
1258
1259     case hd_detail_cdrom:
1260       {
1261         cdrom_info_t *c = d->cdrom.data;
1262
1263         if(c) {
1264           free_mem(c->name);
1265           free_mem(c->iso9660.volume);
1266           free_mem(c->iso9660.publisher);
1267           free_mem(c->iso9660.preparer);
1268           free_mem(c->iso9660.application);
1269           free_mem(c->iso9660.creation_date);
1270           free_mem(c->el_torito.id_string);
1271           free_mem(c->el_torito.label);
1272
1273           free_mem(c);
1274         }
1275       }
1276       break;
1277
1278     case hd_detail_floppy:
1279       free_mem(d->floppy.data);
1280       break;
1281
1282     case hd_detail_bios:
1283       {
1284         bios_info_t *b = d->bios.data;
1285
1286         free_mem(b->vbe.oem_name);
1287         free_mem(b->vbe.vendor_name);
1288         free_mem(b->vbe.product_name);
1289         free_mem(b->vbe.product_revision);
1290         free_mem(b->vbe.mode);
1291         free_mem(b->lcd.vendor);
1292         free_mem(b->lcd.name);
1293         free_mem(b->mouse.vendor);
1294         free_mem(b->mouse.type);
1295
1296         free_mem(b);
1297       }
1298       break;
1299
1300     case hd_detail_cpu:
1301       {
1302         cpu_info_t *c = d->cpu.data;
1303
1304         free_mem(c->vend_name);
1305         free_mem(c->model_name);
1306         free_mem(c->platform);
1307         free_str_list(c->features);
1308         free_mem(c);
1309       }
1310       break;
1311
1312     case hd_detail_prom:
1313       free_mem(d->prom.data);
1314       break;
1315
1316     case hd_detail_monitor:
1317       {
1318         monitor_info_t *m;
1319         hd_detail_monitor_t *mdetail, *next;
1320
1321         for(mdetail = &d->monitor; mdetail; mdetail = next) {
1322           next = mdetail->next;
1323           m = mdetail->data;
1324
1325           free_mem(m->vendor);
1326           free_mem(m->name);
1327           free_mem(m->serial);
1328
1329           free_mem(m);
1330
1331           if(mdetail != &d->monitor) free_mem(mdetail);
1332         }
1333       }
1334       break;
1335
1336     case hd_detail_sys:
1337       {
1338         sys_info_t *s = d->sys.data;
1339
1340         free_mem(s->system_type);
1341         free_mem(s->generation);
1342         free_mem(s->vendor);
1343         free_mem(s->model);
1344         free_mem(s->serial);
1345         free_mem(s->lang);
1346
1347         free_mem(s);
1348       }
1349       break;
1350
1351     case hd_detail_scsi:
1352       free_scsi(d->scsi.data, 1);
1353       break;
1354
1355     case hd_detail_devtree:
1356       /* is freed with hd_data->dev_tree */
1357       break;
1358
1359     case hd_detail_ccw:
1360       free_mem(d->ccw.data);
1361       break;
1362   }
1363
1364   free_mem(d);
1365
1366   return NULL;
1367 }
1368
1369
1370 hd_t *free_hd_entry(hd_t *hd)
1371 {
1372   free_mem(hd->bus.name);
1373   free_mem(hd->base_class.name);
1374   free_mem(hd->sub_class.name);
1375   free_mem(hd->prog_if.name);
1376   free_mem(hd->vendor.name);
1377   free_mem(hd->device.name);
1378   free_mem(hd->sub_vendor.name);
1379   free_mem(hd->sub_device.name);
1380   free_mem(hd->revision.name);
1381   free_mem(hd->serial);
1382   free_mem(hd->compat_vendor.name);
1383   free_mem(hd->compat_device.name);
1384   free_mem(hd->model);
1385   free_mem(hd->sysfs_id);
1386   free_mem(hd->sysfs_bus_id);
1387   free_mem(hd->sysfs_device_link);
1388   free_str_list(hd->unix_dev_names);
1389   free_mem(hd->unix_dev_name);
1390   free_mem(hd->unix_dev_name2);
1391   free_mem(hd->rom_id);
1392   free_mem(hd->unique_id);
1393   free_mem(hd->udi);
1394   free_mem(hd->block0);
1395   free_mem(hd->driver);
1396   free_str_list(hd->drivers);
1397   free_str_list(hd->driver_modules);
1398   free_mem(hd->old_unique_id);
1399   free_mem(hd->unique_id1);
1400   free_mem(hd->usb_guid);
1401   free_mem(hd->parent_id);
1402   free_str_list(hd->child_ids);
1403   free_mem(hd->config_string);
1404   free_str_list(hd->extra_info);
1405
1406   free_res_list(hd->res);
1407
1408   free_hd_detail(hd->detail);
1409
1410   free_driver_info(hd->driver_info);
1411   free_str_list(hd->requires);
1412
1413   free_mem(hd->modalias);
1414
1415   hd_free_hal_properties(hd->hal_prop);
1416   hd_free_hal_properties(hd->persistent_prop);
1417
1418   memset(hd, 0, sizeof *hd);
1419
1420   return NULL;
1421 }
1422
1423 misc_t *free_misc(misc_t *m)
1424 {
1425   int i, j;
1426
1427   if(!m) return NULL;
1428
1429   for(i = 0; (unsigned) i < m->io_len; i++) {
1430     free_mem(m->io[i].dev);
1431   }
1432   free_mem(m->io);
1433
1434   for(i = 0; (unsigned) i < m->dma_len; i++) {
1435     free_mem(m->dma[i].dev);
1436   }
1437   free_mem(m->dma);
1438
1439   for(i = 0; (unsigned) i < m->irq_len; i++) {
1440     for(j = 0; j < m->irq[i].devs; j++) {
1441       free_mem(m->irq[i].dev[j]);
1442     }
1443     free_mem(m->irq[i].dev);
1444   }
1445   free_mem(m->irq);
1446
1447   free_str_list(m->proc_io);
1448   free_str_list(m->proc_dma);
1449   free_str_list(m->proc_irq);
1450
1451   free_mem(m);
1452
1453   return NULL;
1454 }
1455
1456 scsi_t *free_scsi(scsi_t *scsi, int free_all)
1457 {
1458   scsi_t *next;
1459
1460   for(; scsi; scsi = next) {
1461     next = scsi->next;
1462
1463     free_mem(scsi->dev_name);
1464     free_mem(scsi->guessed_dev_name);
1465     free_mem(scsi->vendor);
1466     free_mem(scsi->model);
1467     free_mem(scsi->rev);
1468     free_mem(scsi->type_str);
1469     free_mem(scsi->serial);
1470     free_mem(scsi->proc_dir);
1471     free_mem(scsi->driver);
1472     free_mem(scsi->info);
1473     free_mem(scsi->usb_guid);
1474     free_str_list(scsi->host_info);
1475     free_mem(scsi->controller_id);
1476
1477     if(!free_all) {
1478       next = scsi->next;
1479       memset(scsi, 0, sizeof scsi);
1480       scsi->next = next;
1481       break;
1482     }
1483
1484     free_mem(scsi);
1485   }
1486
1487   return NULL;
1488 }
1489
1490
1491 // FIXME: obsolete
1492 hd_manual_t *hd_free_manual(hd_manual_t *manual)
1493 {
1494   return NULL;
1495 }
1496
1497
1498 /*
1499  * Removes all hd_data->old_hd entries and frees their memory.
1500  */
1501 void free_old_hd_entries(hd_data_t *hd_data)
1502 {
1503   hd_t *hd, *next;
1504
1505   for(hd = hd_data->old_hd; hd; hd = next) {
1506     next = hd->next;
1507
1508     if(exists_hd_entry(hd_data, next, hd->ref) && hd->ref->ref_cnt) hd->ref->ref_cnt--;
1509
1510     if(!hd->ref) free_hd_entry(hd);
1511
1512     free_mem(hd);
1513   }
1514
1515   hd_data->old_hd = NULL;
1516 }
1517
1518
1519 void *new_mem(size_t size)
1520 {
1521   void *p;
1522
1523   if(size == 0) return NULL;
1524
1525   p = calloc(size, 1);
1526
1527   if(p) return p;
1528
1529   fprintf(stderr, "memory oops 1\n");
1530   exit(11);
1531   /*NOTREACHED*/
1532   return 0;
1533 }
1534
1535 void *resize_mem(void *p, size_t n)
1536 {
1537   p = realloc(p, n);
1538
1539   if(!p) {
1540     fprintf(stderr, "memory oops 7\n");
1541     exit(17);
1542   }
1543
1544   return p;
1545 }
1546
1547 void *add_mem(void *p, size_t elem_size, size_t n)
1548 {
1549   p = realloc(p, (n + 1) * elem_size);
1550
1551   if(!p) {
1552     fprintf(stderr, "memory oops 7\n");
1553     exit(17);
1554   }
1555
1556   memset(p + n * elem_size, 0, elem_size);
1557
1558   return p;
1559 }
1560
1561 char *new_str(const char *s)
1562 {
1563   char *t;
1564
1565   if(!s) return NULL;
1566
1567   t = strdup(s);
1568
1569   if(t) return t;
1570
1571   fprintf(stderr, "memory oops 2\n");
1572   /*NOTREACHED*/
1573   exit(12);
1574
1575   return NULL;
1576 }
1577
1578 void *free_mem(void *p)
1579 {
1580   if(p) free(p);
1581
1582   return NULL;
1583 }
1584
1585 void join_res_io(hd_res_t **res1, hd_res_t *res2)
1586 {
1587   hd_res_t *res;
1588
1589   /*
1590    * see if we must add an i/o range (tricky...)
1591    *
1592    * We look for identical i/o bases and add a range if one was missing. If
1593    * no matching pair was found, add the i/o resource.
1594    */
1595   for(; res2; res2 = res2->next) {
1596     if(res2->io.type == res_io) {
1597       for(res = *res1; res; res = res->next) {
1598         if(res->io.type == res_io) {
1599           if(res->io.base == res2->io.base) {
1600             /* identical bases: take maximum of both ranges */
1601             if(res2->io.range > res->io.range) {
1602               res->io.range = res2->io.range;
1603             }
1604             break;
1605           }
1606           else if(
1607             res->io.range &&
1608             res2->io.range &&
1609             res->io.base + res->io.range == res2->io.base)
1610           {
1611             /* res2 directly follows res1: extend res1 to cover res2 */
1612             res->io.range += res2->io.range;
1613             break;
1614           }
1615           else if(
1616             res2->io.base >= res->io.base &&
1617             res2->io.base < res->io.base + res->io.range
1618           ) {
1619             /* res2 is totally contained in res1: ignore it */
1620             break;
1621           }
1622         }
1623       }
1624       if(!res) {
1625         res = add_res_entry(res1, new_mem(sizeof *res));
1626         *res = *res2;   /* *copy* the struct */
1627         res->next = NULL;
1628       }
1629     }
1630   }
1631 }
1632
1633 void join_res_irq(hd_res_t **res1, hd_res_t *res2)
1634 {
1635   hd_res_t *res;
1636
1637   /* see if we must add an dma channel */
1638   for(; res2; res2 = res2->next) {
1639     if(res2->irq.type == res_irq) {
1640       for(res = *res1; res; res = res->next) {
1641         if(res->irq.type == res_irq && res->irq.base == res2->irq.base) break;
1642       }
1643       if(!res) {
1644         res = add_res_entry(res1, new_mem(sizeof *res));
1645         *res = *res2;   /* *copy* the struct */
1646         res->next = NULL;
1647       }
1648     }
1649   }
1650 }
1651
1652
1653 void join_res_dma(hd_res_t **res1, hd_res_t *res2)
1654 {
1655   hd_res_t *res;
1656
1657   /* see if we must add an dma channel */
1658   for(; res2; res2 = res2->next) {
1659     if(res2->dma.type == res_dma) {
1660       for(res = *res1; res; res = res->next) {
1661         if(res->dma.type == res_dma && res->dma.base == res2->dma.base) break;
1662       }
1663       if(!res) {
1664         res = add_res_entry(res1, new_mem(sizeof *res));
1665         *res = *res2;   /* *copy* the struct */
1666         res->next = NULL;
1667       }
1668     }
1669   }
1670 }
1671
1672
1673 /*
1674  * Check whether both resource lists have common entries.
1675  */
1676 int have_common_res(hd_res_t *res1, hd_res_t *res2)
1677 {
1678   hd_res_t *res;
1679
1680   for(; res1; res1 = res1->next) {
1681     for(res = res2; res; res = res->next) {
1682       if(res->any.type == res1->any.type) {
1683         switch(res->any.type) {
1684           case res_io:
1685             if(res->io.base == res1->io.base) return 1;
1686             break;
1687
1688           case res_irq:
1689             if(res->irq.base == res1->irq.base) return 1;
1690             break;
1691
1692           case res_dma:
1693             if(res->dma.base == res1->dma.base) return 1;
1694             break;
1695
1696           default: /* gcc -Wall */
1697             break;
1698         }
1699       }
1700     }
1701   }
1702
1703   return 0;
1704 }
1705
1706
1707 /*
1708  * Free the memory allocated by a resource list.
1709  */
1710 hd_res_t *free_res_list(hd_res_t *res)
1711 {
1712   hd_res_t *next;
1713
1714   for(; res; res = next) {
1715     next = res->next;
1716
1717     if(res->any.type == res_init_strings) {
1718       free_mem(res->init_strings.init1);
1719       free_mem(res->init_strings.init2);
1720     }
1721
1722     if(res->any.type == res_pppd_option) {
1723       free_mem(res->pppd_option.option);
1724     }
1725
1726     if(res->any.type == res_hwaddr) {
1727       free_mem(res->hwaddr.addr);
1728     }
1729
1730     if(res->any.type == res_wlan) {
1731       free_str_list(res->wlan.channels);
1732       free_str_list(res->wlan.frequencies);
1733       free_str_list(res->wlan.bitrates);
1734       free_str_list(res->wlan.auth_modes);
1735       free_str_list(res->wlan.enc_modes);
1736     }
1737
1738     if(res->any.type == res_fc) {
1739       free_mem(res->fc.controller_id);
1740     }
1741
1742     free_mem(res);
1743   }
1744
1745   return NULL;
1746 }
1747
1748
1749 /*
1750  * Note: new_res is directly inserted into the list, so you *must* make sure
1751  * that new_res points to a malloc'ed pice of memory.
1752  */
1753 hd_res_t *add_res_entry(hd_res_t **res, hd_res_t *new_res)
1754 {
1755   while(*res) res = &(*res)->next;
1756
1757   return *res = new_res;
1758 }
1759
1760
1761 hd_t *add_hd_entry(hd_data_t *hd_data, unsigned line, unsigned count)
1762 {
1763   hd_t *hd;
1764
1765   hd = add_hd_entry2(&hd_data->hd, new_mem(sizeof *hd));
1766
1767   hd->idx = ++(hd_data->last_idx);
1768   hd->module = hd_data->module;
1769   hd->line = line;
1770   hd->count = count;
1771
1772   return hd;
1773 }
1774
1775
1776 hd_t *add_hd_entry2(hd_t **hd, hd_t *new_hd)
1777 {
1778   while(*hd) hd = &(*hd)->next;
1779
1780   return *hd = new_hd;
1781 }
1782
1783
1784 void hd_scan(hd_data_t *hd_data)
1785 {
1786   char *s = NULL;
1787   int i, j;
1788   hd_t *hd, *hd2;
1789   uint64_t irqs;
1790   str_list_t *sl, *sl0;
1791   pr_flags_t *pf;
1792
1793   if(!hd_data->flags.internal) {
1794   /* log debug & probe flags */
1795     if(hd_data->debug) {
1796       ADD2LOG("libhd version %s%s (%s)\n", HD_VERSION_STRING, getuid() ? "u" : "", HD_ARCH);
1797     }
1798
1799     ADD2LOG("using %s\n", hd_get_hddb_dir());
1800   }
1801
1802   get_kernel_version(hd_data);
1803
1804   /* needed only on 1st call */
1805   if(hd_data->last_idx == 0) {
1806     get_probe_env(hd_data);
1807   }
1808
1809   /* init driver info database */
1810   hddb_init(hd_data);
1811
1812   /* only first time */
1813   if(hd_data->last_idx == 0) {
1814     hd_set_probe_feature(hd_data, pr_fork);
1815     if(!hd_probe_feature(hd_data, pr_fork)) hd_data->flags.nofork = 1;
1816 //    hd_set_probe_feature(hd_data, pr_sysfs);
1817     if(!hd_probe_feature(hd_data, pr_sysfs)) hd_data->flags.nosysfs = 1;
1818     hd_set_probe_feature(hd_data, pr_cpuemu);
1819     if(hd_probe_feature(hd_data, pr_cpuemu)) hd_data->flags.cpuemu = 1;
1820     if(hd_probe_feature(hd_data, pr_udev)) hd_data->flags.udev = 1;
1821     if(!hd_probe_feature(hd_data, pr_bios_crc)) hd_data->flags.nobioscrc = 1;
1822     hd_set_probe_feature(hd_data, pr_bios_vram);
1823     if(hd_probe_feature(hd_data, pr_bios_vram)) hd_data->flags.biosvram = 1;
1824     hd_set_probe_feature(hd_data, pr_bios_acpi);
1825     hd_set_probe_feature(hd_data, pr_modules_pata);
1826     hd_set_probe_feature(hd_data, pr_net_eeprom);
1827     hd_data->flags.pata = hd_probe_feature(hd_data, pr_modules_pata) ? 1 : 0;
1828     hd_set_probe_feature(hd_data, pr_x86emu);
1829     if(!get_probe_val_list(hd_data, pr_x86emu)) {
1830       set_probe_val(hd_data, pr_x86emu, "dump");
1831     }
1832   }
1833
1834   fix_probe_features(hd_data);
1835
1836   if(hd_data->debug && !hd_data->flags.internal) {
1837     for(i = sizeof hd_data->probe - 1; i >= 0; i--) {
1838       str_printf(&s, -1, "%02x", hd_data->probe[i]);
1839     }
1840     ADD2LOG("debug = 0x%x\nprobe = 0x%s (", hd_data->debug, s);
1841     s = free_mem(s);
1842
1843     for(i = 1; i < pr_default; i++) {           /* 1 because of pr_memory */
1844       pf = pr_flags_by_id(i);
1845       if(pf) {
1846         j = hd_probe_feature(hd_data, i);
1847         ADD2LOG("%s%c%s", i == 1 ? "" : " ", j ? '+' : '-', pf->name);
1848         switch(pf->type) {
1849           case p_int32:
1850             ADD2LOG("=%d", get_probe_val_int(hd_data, i));
1851             break;
1852
1853           case p_string:
1854             ADD2LOG("=%s", get_probe_val_str(hd_data, i) ?: "");
1855             break;
1856
1857           case p_list:
1858             s = hd_join(":", get_probe_val_list(hd_data, i));
1859             ADD2LOG("=%s", s ?: "");
1860             s = free_mem(s);
1861             break;
1862
1863           default:
1864             break;
1865         }
1866       }
1867     }
1868
1869     ADD2LOG(")\n");
1870   }
1871
1872   /* get shm segment, if we didn't do it already */
1873   hd_shm_init(hd_data);
1874
1875   if(!hd_data->shm.ok && !hd_data->flags.nofork) {
1876     hd_data->flags.nofork = 1;
1877     ADD2LOG("shm: failed to get shm segment; will not fork\n");
1878   }
1879
1880   if(hd_data->only) {
1881     s = hd_join(", ", hd_data->only);
1882     ADD2LOG("only: %s\n", s);
1883     s = free_mem(s);
1884   }
1885
1886   /*
1887    * There might be old 'manual' entries left from an earlier scan. Remove
1888    * them, they will confuse us.
1889    */
1890   hd_data->module = mod_manual;
1891   remove_hd_entries(hd_data);
1892
1893   hd_scan_with_hal(hd_data);
1894
1895   if(!hd_data->hal) {
1896     hd_scan_hal_basic(hd_data);
1897     hd_scan_no_hal(hd_data);
1898   }
1899
1900   hd_scan_int(hd_data);
1901
1902   /* and again... */
1903   for(hd = hd_data->hd; hd; hd = hd->next) hd_add_id(hd_data, hd);
1904
1905   /* assign parent & child ids */
1906   for(hd = hd_data->hd; hd; hd = hd->next) {
1907     hd->child_ids = free_str_list(hd->child_ids);
1908     if((hd2 = hd_get_device_by_idx(hd_data, hd->attached_to))) {
1909       free_mem(hd->parent_id);
1910       hd->parent_id = new_str(hd2->unique_id);
1911     }
1912     else if((hd2 = hd_get_device_by_id(hd_data, hd->parent_id))) {
1913       hd->attached_to = hd2->idx;
1914     }
1915     else {
1916       hd->attached_to = 0;
1917     }
1918   }
1919
1920   for(hd = hd_data->hd; hd; hd = hd->next) {
1921     if((hd2 = hd_get_device_by_idx(hd_data, hd->attached_to))) {
1922       add_str_list(&hd2->child_ids, hd->unique_id);
1923     }
1924   }
1925
1926   /* assign a hw_class & build a useful model string */
1927   for(hd = hd_data->hd; hd; hd = hd->next) {
1928     assign_hw_class(hd_data, hd);
1929
1930     /* create model name _after_ hw_class */
1931     create_model_name(hd_data, hd);
1932   }
1933
1934 #ifndef LIBHD_TINY
1935   /* must be _after_ we have valid hw_class entries */
1936   hd_scan_manual2(hd_data);
1937 #endif
1938
1939   /* we are done... */
1940   for(hd = hd_data->hd; hd; hd = hd->next) hd->tag.fixed = 1;
1941
1942   hd_data->module = mod_none;
1943
1944   if(hd_data->debug && !hd_data->flags.internal && hd_data->klog) {
1945     dump_klog(hd_data);
1946   }
1947
1948   if(
1949     hd_data->debug &&
1950     !hd_data->flags.internal &&
1951     (
1952       hd_data->kmods ||
1953       hd_probe_feature(hd_data, pr_int /* arbitrary; just avoid /proc/modules for -pr_all */)
1954     )
1955   ) {
1956     sl0 = read_file(PROC_MODULES, 0, 0);
1957     ADD2LOG("----- /proc/modules -----\n");
1958     for(sl = sl0; sl; sl = sl->next) {
1959       ADD2LOG("  %s", sl->str);
1960     }
1961     ADD2LOG("----- /proc/modules end -----\n");
1962     free_str_list(sl0);
1963   }
1964
1965   update_irq_usage(hd_data);
1966
1967   if(hd_data->debug && !hd_data->flags.internal) {
1968     irqs = hd_data->used_irqs;
1969
1970     ADD2LOG("  used irqs:");
1971     for(i = j = 0; i < 64; i++, irqs >>= 1) {
1972       if((irqs & 1)) {
1973         ADD2LOG("%c%d", j ? ',' : ' ', i);
1974         j = 1;
1975       }
1976     }
1977     ADD2LOG("\n");
1978   }
1979 }
1980
1981
1982 void hd_scan_with_hal(hd_data_t *hd_data)
1983 {
1984   hd_t *hd;
1985
1986   hd_data->hal = hd_free_hal_devices(hd_data->hal);
1987
1988   hd_scan_hal(hd_data);
1989
1990   for(hd = hd_data->hd; hd; hd = hd->next) {
1991     if(!hd->persistent_prop) hd->persistent_prop = hd_read_properties(hd->udi);
1992   }
1993
1994 }
1995
1996
1997 void hd_scan_no_hal(hd_data_t *hd_data)
1998 {
1999   hd_t *hd;
2000
2001   /*
2002    * for various reasons, do it befor scan_misc()
2003    */
2004   hd_scan_floppy(hd_data);
2005
2006   /*
2007    * to be able to read the right parport io,
2008    * we have to do this before scan_misc()
2009    */
2010 #if defined(__i386__) || defined (__x86_64__) || defined (__ia64__)
2011   hd_scan_bios(hd_data);
2012 #endif
2013   
2014   /* before hd_scan_misc(): we need some ppc info later */
2015   hd_scan_sys(hd_data);
2016
2017   /* get basic system info */
2018   hd_scan_misc(hd_data);
2019
2020   /* hd_scan_cpu() after hd_scan_misc(): klog needed */
2021   hd_scan_cpu(hd_data);
2022   hd_scan_memory(hd_data);
2023
2024   hd_scan_sysfs_pci(hd_data);
2025
2026   /* do it _after_ hd_scan_sysfs_pci() */
2027 #if defined(__PPC__)
2028   hd_scan_prom(hd_data);
2029 #endif
2030
2031 #if defined(__s390__) || defined(__s390x__)
2032   hd_scan_s390disks(hd_data);
2033   hd_scan_s390(hd_data);
2034 #endif
2035
2036   /* after hd_scan_prom() and hd_scan_bios() */
2037   hd_scan_monitor(hd_data);
2038
2039 #ifndef LIBHD_TINY
2040 #if defined(__i386__) || defined(__alpha__)
2041   hd_scan_isapnp(hd_data);
2042 #endif
2043 #endif
2044
2045 #ifndef LIBHD_TINY
2046 #if defined(__i386__)
2047   hd_scan_isa(hd_data);
2048 #endif
2049 #endif
2050
2051   /* after pci & isa */
2052   hd_scan_pcmcia(hd_data);
2053
2054   /* after pci */
2055   hd_scan_serial(hd_data);
2056
2057   /* merge basic system info & the easy stuff */
2058   hd_scan_misc2(hd_data);
2059
2060 #ifndef LIBHD_TINY
2061   if(!hd_data->flags.no_parport) {
2062     hd_scan_parallel(hd_data);  /* after hd_scan_misc*() */
2063   }
2064 #endif
2065
2066   hd_scan_sysfs_block(hd_data);
2067   hd_scan_sysfs_scsi(hd_data);
2068   hd_scan_sysfs_usb(hd_data);
2069 #if defined(__i386__) || defined(__x86_64__)
2070   hd_scan_sysfs_edd(hd_data);
2071 #endif
2072
2073 #ifndef LIBHD_TINY
2074 #if !defined(__sparc__)
2075   hd_scan_braille(hd_data);
2076 #endif
2077   hd_scan_modem(hd_data);       /* do it before hd_scan_mouse() */
2078   hd_scan_mouse(hd_data);
2079 #endif
2080   hd_scan_sbus(hd_data);
2081
2082   hd_scan_input(hd_data);
2083
2084 #if !defined(__s390__) && !defined(__s390x__)
2085   hd_scan_kbd(hd_data);
2086 #endif
2087
2088   /* must be after hd_scan_monitor() */
2089   hd_scan_fb(hd_data);
2090
2091   /* keep these at the end of the list */
2092   hd_scan_net(hd_data);
2093
2094   hd_scan_pppoe(hd_data);
2095
2096 #ifndef LIBHD_TINY
2097   hd_scan_wlan(hd_data);
2098 #endif
2099
2100   for(hd = hd_data->hd; hd; hd = hd->next) hd_add_id(hd_data, hd);
2101
2102   hd_scan_hal_assign_udi(hd_data);
2103
2104 #ifndef LIBHD_TINY
2105   hd_scan_manual(hd_data);
2106 #endif
2107
2108   /* add test entries */
2109   hd_scan_xtra(hd_data);
2110
2111   /* some final fixup's */
2112 #if WITH_ISDN
2113   hd_scan_isdn(hd_data);
2114   hd_scan_dsl(hd_data);
2115 #endif
2116
2117 }
2118
2119
2120 /*
2121  * Note: due to byte order problems decoding the id is really a mess...
2122  * And, we use upper case for hex numbers!
2123  */
2124 char *isa_id2str(unsigned id)
2125 {
2126   char *s = new_mem(8);
2127   unsigned u = ((id & 0xff) << 8) + ((id >> 8) & 0xff);
2128   unsigned v = ((id >> 8) & 0xff00) + ((id >> 24) & 0xff);
2129
2130   s[0] = ((u >> 10) & 0x1f) + 'A' - 1;
2131   s[1] = ((u >>  5) & 0x1f) + 'A' - 1;
2132   s[2] = ( u        & 0x1f) + 'A' - 1;
2133
2134   sprintf(s + 3, "%04X", v);
2135
2136   return s;
2137 }
2138
2139 char *eisa_vendor_str(unsigned v)
2140 {
2141   static char s[4];
2142
2143   s[0] = ((v >> 10) & 0x1f) + 'A' - 1;
2144   s[1] = ((v >>  5) & 0x1f) + 'A' - 1;
2145   s[2] = ( v        & 0x1f) + 'A' - 1;
2146   s[3] = 0;
2147
2148   return s;
2149 }
2150
2151
2152 /*
2153  *  Must _not_ check that s is exactly 3 chars.
2154  */
2155 unsigned name2eisa_id(char *s)
2156 {
2157   int i;
2158   unsigned u = 0;
2159
2160   for(i = 0; i < 3; i++) {
2161     u <<= 5;
2162     if(s[i] < 'A' - 1 || s[i] > 'A' - 1 + 0x1f) return 0;
2163     u += s[i] - 'A' + 1;
2164   }
2165
2166   return MAKE_ID(TAG_EISA, u);
2167 }
2168
2169
2170 /*
2171  * Create a 'canonical' version, i.e. no spaces at start and end.
2172  *
2173  * Note: removes chars >= 0x80 as well (due to (char *))! This
2174  * is currently considered a feature.
2175  */
2176 char *canon_str(char *s, int len)
2177 {
2178   char *m2, *m1, *m0;
2179   int i;
2180
2181   if(len < 0) len = 0;          /* just to be safe */
2182
2183   m0 = new_mem(len + 1);
2184
2185   for(m1 = m0, i = 0; i < len; i++) {
2186     if(m1 == m0 && s[i] <= ' ') continue;
2187     *m1++ = s[i];
2188   }
2189   *m1 = 0;
2190   while(m1 > m0 && m1[-1] <= ' ') {
2191     *--m1 = 0;
2192   }
2193
2194   m2 = new_str(m0);
2195   free_mem(m0);
2196
2197   return m2;
2198 }
2199
2200
2201 /*
2202  * Convert a n-digit hex number to its numerical value.
2203  */
2204 int hex(char *s, int n)
2205 {
2206   int i = 0, j;
2207
2208   while(n--) {
2209     if(sscanf(s++, "%1x", &j) != 1) return -1;
2210     i = (i << 4) + j;
2211   }
2212
2213   return i;
2214 }
2215
2216
2217 /* simple 32 bit fixed point numbers with n decimals */
2218 int str2float(char *s, int n)
2219 {
2220   int i = 0;
2221   int dot = 0;
2222
2223   while(*s) {
2224     if(*s == '.') {
2225       if(dot++) return 0;
2226     }
2227     else if(*s >= '0' && *s <= '9') {
2228       if(dot) {
2229         if(!n) return i;
2230         n--;
2231       }
2232       i *= 10;
2233       i += *s - '0';
2234     }
2235     else {
2236       return 0;
2237     }
2238
2239     s++;
2240   }
2241
2242   while(n--) i *= 10;
2243
2244   return i;
2245 }
2246
2247
2248 /* simple 32 bit fixed point numbers with n decimals */
2249 char *float2str(int f, int n)
2250 {
2251   int i = 1, j, m = n;
2252   static char buf[32];
2253
2254   while(n--) i *= 10;
2255
2256   j = f / i;
2257   i = f % i;
2258
2259   while(i && !(i % 10)) i /= 10, m--;
2260
2261   if(i) {
2262     sprintf(buf, "%d.%0*d", j, m, i);
2263   }
2264   else {
2265     sprintf(buf, "%d", j);
2266   }
2267
2268   return buf;
2269 }
2270
2271
2272 /*
2273  * find hardware entry with given index
2274  */
2275 hd_t *hd_get_device_by_idx(hd_data_t *hd_data, unsigned idx)
2276 {
2277   hd_t *hd;
2278
2279   if(!idx) return NULL;         /* early out: idx is always != 0 */
2280
2281   for(hd = hd_data->hd; hd; hd = hd->next) {
2282     if(hd->idx == idx) return hd;
2283   }
2284
2285   return NULL;
2286 }
2287
2288
2289 /*
2290  * find hardware entry with given unique id
2291  */
2292 hd_t *hd_get_device_by_id(hd_data_t *hd_data, char *id)
2293 {
2294   hd_t *hd;
2295
2296   if(!id) return NULL;
2297
2298   for(hd = hd_data->hd; hd; hd = hd->next) {
2299     if(hd->unique_id && !strcmp(hd->unique_id, id)) return hd;
2300   }
2301
2302   return NULL;
2303 }
2304
2305
2306 /*
2307  * Give the actual name of the probing module.
2308  */
2309 char *mod_name_by_idx(unsigned idx)
2310 {
2311   unsigned u;
2312
2313   for(u = 0; u < sizeof pr_modules / sizeof *pr_modules; u++)
2314     if(idx == pr_modules[u].val) return pr_modules[u].name;
2315
2316   return "";
2317 }
2318
2319
2320 void hd_log(hd_data_t *hd_data, char *buf, ssize_t len)
2321 {
2322   ssize_t new_size;
2323   char *p;
2324
2325   if(len <= 0 || !buf) return;
2326
2327   if(hd_data->log_size + len + 1 > hd_data->log_max) {
2328     new_size = hd_data->log_max + len + (1 << 20);
2329     new_size += new_size / 2;
2330     p = realloc(hd_data->log, new_size);
2331     if(p) {
2332       hd_data->log = p;
2333       hd_data->log_max = new_size;
2334     }
2335   }
2336
2337   if(hd_data->log) {
2338     memcpy(hd_data->log + hd_data->log_size, buf, len);
2339     hd_data->log_size += len;
2340     hd_data->log[hd_data->log_size] = 0;
2341   }
2342 }
2343
2344
2345 void hd_log_printf(hd_data_t *hd_data, char *format, ...)
2346 {
2347   ssize_t l;
2348   char *s = NULL;
2349   va_list args;
2350
2351   va_start(args, format);
2352   l = vasprintf(&s, format, args);
2353   va_end(args);
2354
2355   hd_log(hd_data, s, l);
2356
2357   free(s);
2358 }
2359
2360
2361 void hd_log_hex(hd_data_t *hd_data, int with_ascii, unsigned data_len, unsigned char *data)
2362 {
2363   char *buf = NULL;
2364
2365   hexdump(&buf, with_ascii, data_len, data);
2366
2367   if(buf) hd_log(hd_data, buf, strlen(buf));
2368
2369   free(buf);
2370 }
2371
2372
2373 /*
2374  * Print to a string.
2375  * Note: *buf must point to a malloc'd memory area (or be NULL).
2376  *
2377  * Use an offset of -1 or -2 to append the new string.
2378  *
2379  * As this function is quite often used to extend our log messages, there
2380  * is a cache that holds the length of the last string we created. This way
2381  * we speed this up somewhat. Use an offset of -2 to use this feature.
2382  * Note: this only works as long as str_printf() is used *exclusively* to
2383  * extend the string.
2384  */
2385 void str_printf(char **buf, int offset, char *format, ...)
2386 {
2387   static char *last_buf = NULL;
2388   static int last_len = 0;
2389   int len, use_cache;
2390   char b[0x10000];
2391   va_list args;
2392
2393   use_cache = offset == -2 ? 1 : 0;
2394
2395   if(*buf) {
2396     if(offset == -1) {
2397       offset = strlen(*buf);
2398     }
2399     else if(offset == -2) {
2400       if(last_buf == *buf && last_len && !(*buf)[last_len])
2401         offset = last_len;
2402       else
2403         offset = strlen(*buf);
2404     }
2405   }
2406   else {
2407     offset = 0;
2408   }
2409
2410   va_start(args, format);
2411   vsnprintf(b, sizeof b, format, args);
2412   va_end(args);
2413
2414   *buf = resize_mem(*buf, (len = offset + strlen(b)) + 1);
2415   strcpy(*buf + offset, b);
2416
2417   if(use_cache) {
2418     last_buf = *buf;
2419     last_len = len;
2420   }
2421 }
2422
2423
2424 void hexdump(char **buf, int with_ascii, unsigned data_len, unsigned char *data)
2425 {
2426   unsigned i;
2427
2428   for(i = 0; i < data_len; i++) {
2429     if(i)
2430       str_printf(buf, -2, " %02x", data[i]);
2431     else
2432       str_printf(buf, -2, "%02x", data[i]);
2433   }
2434
2435   if(with_ascii) {
2436     str_printf(buf, -2, "  \"");
2437     for(i = 0; i < data_len; i++) {
2438       str_printf(buf, -2, "%c", data[i] < ' ' || data[i] >= 0x7f ? '.' : data[i]);
2439     }
2440     str_printf(buf, -2, "\"");
2441   }
2442 }
2443
2444
2445 /** \relates s_str_list_t
2446  * Search a string list for a string.
2447  */
2448 str_list_t *search_str_list(str_list_t *sl, char *str)
2449 {
2450   if(!str) return NULL;
2451
2452   for(; sl; sl = sl->next) if(sl->str && !strcmp(sl->str, str)) return sl;
2453
2454   return NULL;
2455 }
2456
2457
2458 /** \relates s_str_list_t
2459  * Add a string to a string list.
2460  *
2461  * The new string (str) will be *copied*!
2462  */
2463 str_list_t *add_str_list(str_list_t **sl, char *str)
2464 {
2465   while(*sl) sl = &(*sl)->next;
2466
2467   *sl = new_mem(sizeof **sl);
2468   (*sl)->str = new_str(str);
2469
2470   return *sl;
2471 }
2472
2473
2474 /** \relates s_str_list_t
2475  * Free the memory allocated by a string list.
2476  */
2477 str_list_t *free_str_list(str_list_t *list)
2478 {
2479   str_list_t *l;
2480
2481   for(; list; list = (l = list)->next, free_mem(l)) {
2482     free_mem(list->str);
2483   }
2484
2485   return NULL;
2486 }
2487
2488
2489 /** \relates s_str_list_t
2490  * Reverse string list.
2491  */
2492 str_list_t *reverse_str_list(str_list_t *list)
2493 {
2494   str_list_t *sl, *sl_new = NULL, *next;
2495
2496   for(sl = list; sl; sl = next) {
2497     next = sl->next;
2498     sl->next = sl_new;
2499     sl_new = sl;
2500   }
2501
2502   return sl_new;
2503 }
2504
2505
2506 /*
2507  * Read a file; return a linked list of lines.
2508  *
2509  * start_line is zero-based; lines == 0 -> all lines
2510  */
2511 str_list_t *read_file(char *file_name, unsigned start_line, unsigned lines)
2512 {
2513   FILE *f;
2514   char buf[0x10000];
2515   int pipe = 0;
2516   str_list_t *sl_start = NULL, *sl_end = NULL, *sl;
2517
2518   if(*file_name == '|') {
2519     pipe = 1;
2520     file_name++;
2521     if(!(f = popen(file_name, "r"))) {
2522       return NULL;
2523     }
2524   }
2525   else {
2526     if(!(f = fopen(file_name, "r"))) {
2527       return NULL;
2528     }
2529   }
2530
2531   while(fgets(buf, sizeof buf, f)) {
2532     if(start_line) {
2533       start_line--;
2534       continue;
2535     }
2536     sl = new_mem(sizeof *sl);
2537     sl->str = new_str(buf);
2538     if(sl_start)
2539       sl_end->next = sl;
2540     else
2541       sl_start = sl;
2542     sl_end = sl;
2543
2544     if(lines == 1) break;
2545     lines--;
2546   }
2547
2548   if(pipe)
2549     pclose(f);
2550   else
2551     fclose(f);
2552
2553   return sl_start;
2554 }
2555
2556
2557 /*
2558  * Read directory, return a list of entries with file type 'type'.
2559  */
2560 str_list_t *read_dir(char *dir_name, int type)
2561 {
2562   str_list_t *sl_start = NULL, *sl_end = NULL, *sl;
2563   DIR *dir;
2564   struct dirent *de;
2565   struct stat sbuf;
2566   char *s;
2567   int dir_type, link_allowed = 0;
2568
2569   if(type == 'D') {
2570     type = 'd';
2571     link_allowed = 1;
2572   }
2573
2574   if(dir_name && (dir = opendir(dir_name))) {
2575     while((de = readdir(dir))) {
2576       if(!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
2577       dir_type = 0;
2578
2579       if(type) {
2580         s = NULL;
2581         str_printf(&s, 0, "%s/%s", dir_name, de->d_name);
2582
2583         if(!lstat(s, &sbuf)) {
2584           if(S_ISDIR(sbuf.st_mode)) {
2585             dir_type = 'd';
2586           }
2587           else if(S_ISREG(sbuf.st_mode)) {
2588             dir_type = 'r';
2589           }
2590           else if(S_ISLNK(sbuf.st_mode)) {
2591             dir_type = 'l';
2592           }
2593         }
2594
2595         s = free_mem(s);
2596       }
2597
2598       if(dir_type == type || (link_allowed && dir_type == 'l')) {
2599         sl = new_mem(sizeof *sl);
2600         sl->str = new_str(de->d_name);
2601         if(sl_start)
2602           sl_end->next = sl;
2603         else
2604           sl_start = sl;
2605         sl_end = sl;
2606       }
2607     }
2608     closedir(dir);
2609   }
2610
2611   return sl_start;
2612 }
2613
2614
2615 char *hd_read_sysfs_link(char *base_dir, char *link_name)
2616 {
2617   char *s = NULL;
2618   static char *buf = NULL;
2619
2620   if(!base_dir || !link_name) return NULL;
2621
2622   str_printf(&s, 0, "%s/%s", base_dir, link_name);
2623
2624   free_mem(buf);
2625   buf = canonicalize_file_name(s);
2626
2627   free_mem(s);
2628
2629   return buf;
2630 }
2631
2632
2633 /*
2634  * Log the hardware detection progress.
2635  */
2636 void progress(hd_data_t *hd_data, unsigned pos, unsigned count, char *msg)
2637 {
2638   char buf1[32], buf2[32], buf3[128], *fn;
2639
2640   if(hd_data->shm.ok && hd_data->flags.forked) {
2641     ((hd_data_t *) (hd_data->shm.data))->shm.updated++;
2642   }
2643
2644   if(!msg) msg = "";
2645
2646   sprintf(buf1, "%u", hd_data->module);
2647   sprintf(buf2, ".%u", count);
2648   fn = mod_name_by_idx(hd_data->module);
2649
2650   sprintf(buf3, "%s.%u%s", *fn ? fn : buf1, pos, count ? buf2 : "");
2651
2652   if((hd_data->debug & HD_DEB_PROGRESS))
2653     ADD2LOG(">> %s: %s\n", buf3, msg);
2654
2655   if(hd_data->progress) hd_data->progress(buf3, msg);
2656 }
2657
2658
2659
2660 /*
2661  * Returns a probe feature suitable for hd_*probe_feature().
2662  * If name is not a valid probe feature, 0 is returned.
2663  *
2664  */
2665 enum probe_feature hd_probe_feature_by_name(char *name)
2666 {
2667   pr_flags_t *flags;
2668
2669   flags = pr_flags_by_name(name);
2670
2671   return flags ? flags->val : 0;
2672 }
2673
2674
2675 /*
2676  * Coverts a enum probe_feature to a string.
2677  * If it fails, NULL is returned.
2678  */
2679 char *hd_probe_feature_by_value(enum probe_feature feature)
2680 {
2681   pr_flags_t *flags;
2682
2683   flags = pr_flags_by_id(feature);
2684
2685   return flags ? flags->name : NULL;
2686 }
2687
2688
2689 /*
2690  * Removes all hd_data->hd entries created by the current module from the
2691  * list. The old entries are added to hd_data->old_hd.
2692  */
2693 void remove_hd_entries(hd_data_t *hd_data)
2694 {
2695   hd_t *hd;
2696
2697   for(hd = hd_data->hd; hd; hd = hd->next) {
2698     if(hd->module == hd_data->module) {
2699       hd->tag.remove = 1;
2700     }
2701   }
2702
2703   remove_tagged_hd_entries(hd_data);
2704 }
2705
2706
2707 /*
2708  * Removes all hd_data->hd entries that have the remove tag set from the
2709  * list. The old entries are added to hd_data->old_hd.
2710  */
2711 void remove_tagged_hd_entries(hd_data_t *hd_data)
2712 {
2713   hd_t *hd, **prev, **h;
2714
2715   for(hd = *(prev = &hd_data->hd); hd;) {
2716     if(hd->tag.remove) {
2717       /* find end of the old list... */
2718       h = &hd_data->old_hd;
2719       while(*h) h = &(*h)->next;
2720       *h = hd;          /* ...and append the entry */
2721
2722       hd = *prev = hd->next;
2723       (*h)->next = NULL;
2724     }
2725     else {
2726       hd = *(prev = &hd->next);
2727     }
2728   }
2729 }
2730
2731
2732 int hd_module_is_active(hd_data_t *hd_data, char *mod)
2733 {
2734   str_list_t *sl, *sl0 = read_kmods(hd_data);
2735   int active = 0;
2736   char *s;
2737 #ifdef __PPC__
2738   char *s1, *s2;
2739 #endif
2740
2741   mod = new_str(mod);
2742
2743   /* convert '-' to '_' */
2744   for(s = mod; *s; s++) if(*s == '-') *s = '_';
2745
2746   for(sl = sl0; sl; sl = sl->next) {
2747     if(!strcmp(sl->str, mod)) break;
2748   }
2749
2750   free_str_list(sl0);
2751   active = sl ? 1 : 0;
2752
2753   if(active) {
2754     free_mem(mod);
2755
2756     return active;
2757   }
2758
2759 #ifdef __PPC__
2760   /* temporary hack for ppc */
2761   if(!strcmp(mod, "gmac")) {
2762     s1 = "<6>eth";
2763     s2 = " GMAC ";
2764   }
2765   else if(!strcmp(mod, "mace")) {
2766     s1 = "<6>eth";
2767     s2 = " MACE ";
2768   }
2769   else if(!strcmp(mod, "bmac")) {
2770     s1 = "<6>eth";
2771     s2 = " BMAC";
2772   }
2773   else if(!strcmp(mod, "mac53c94")) {
2774     s1 = "<4>scsi";
2775     s2 = " 53C94";
2776   }
2777   else if(!strcmp(mod, "mesh")) {
2778     s1 = "<4>scsi";
2779     s2 = " MESH";
2780   }
2781   else if(!strcmp(mod, "swim3")) {
2782     s1 = "<6>fd";
2783     s2 = " SWIM3 ";
2784   }
2785   else {
2786     s1 = s2 = NULL;
2787   }
2788
2789   if(s1) {
2790     for(sl = hd_data->klog; sl; sl = sl->next) {
2791       if(strstr(sl->str, s1) == sl->str && strstr(sl->str, s2)) {
2792         active = 1;
2793         break;
2794       }
2795     }
2796   }
2797 #endif
2798
2799   free_mem(mod);
2800
2801   return active;
2802 }
2803
2804
2805 int hd_has_pcmcia(hd_data_t *hd_data)
2806 {
2807   hd_t *hd;
2808
2809   for(hd = hd_data->hd; hd; hd = hd->next) {
2810     if(is_pcmcia_ctrl(hd_data, hd)) return 1;
2811   }
2812
2813   return 0;
2814 }
2815
2816
2817 int hd_apm_enabled(hd_data_t *hd_data)
2818 {
2819   hd_t *hd;
2820
2821   for(hd = hd_data->hd; hd; hd = hd->next) {
2822     if(
2823       hd->base_class.id == bc_internal &&
2824       hd->sub_class.id == sc_int_bios &&
2825       hd->detail &&
2826       hd->detail->type == hd_detail_bios &&
2827       hd->detail->bios.data
2828     ) {
2829       return hd->detail->bios.data->apm_enabled;
2830     }
2831   }
2832
2833   return 0;
2834 }
2835
2836
2837 int hd_usb_support(hd_data_t *hd_data)
2838 {
2839   hd_t *hd;
2840   hd_res_t *res;
2841
2842   for(hd = hd_data->hd; hd; hd = hd->next) {
2843     if(hd->base_class.id == bc_serial && hd->sub_class.id == sc_ser_usb) {
2844       for(res = hd->res; res; res = res->next) {
2845         if(res->any.type == res_irq)
2846           return hd->prog_if.id == pif_usb_ohci ? 2 : 1;        /* 2: ohci, 1: uhci */
2847       }
2848     }
2849   }
2850
2851   return 0;
2852 }
2853
2854
2855 int hd_smp_support(hd_data_t *hd_data)
2856 {
2857   int is_smp = 0;
2858   unsigned u;
2859   hd_t *hd, *hd0;
2860 #if defined(__i386__) || defined (__x86_64__)
2861   unsigned cpu_threads = 0;
2862   cpu_info_t *ct;
2863 #endif
2864
2865   u = hd_data->flags.internal;
2866   hd_data->flags.internal = 1;
2867   hd = hd_list(hd_data, hw_cpu, 0, NULL);
2868   if(!hd) hd = hd_list(hd_data, hw_cpu, 1, NULL);
2869   hd_data->flags.internal = u;
2870
2871   for(is_smp = 0, hd0 = hd; hd0; hd0 = hd0->next) is_smp++;
2872   if(is_smp == 1) is_smp = 0;
2873
2874 #if defined(__i386__) || defined (__x86_64__)
2875   if(
2876     hd &&
2877     hd->detail &&
2878     hd->detail->type == hd_detail_cpu &&
2879     (ct = hd->detail->cpu.data)
2880   ) {
2881     cpu_threads = ct->units;
2882   }
2883 #endif
2884
2885   hd = hd_free_hd_list(hd);
2886
2887 #if !defined(LIBHD_TINY) && (defined(__i386__) || defined (__x86_64__))
2888   if(is_smp < 2) {
2889     if(!hd_data->bios_ram.data) {
2890       hd_free_hd_list(hd_list(hd_data, hw_sys, 1, NULL));
2891     }
2892     is_smp = detect_smp_bios(hd_data);
2893     // at least 2 processors
2894     if(is_smp < 2) is_smp = 0;
2895     if(!is_smp && cpu_threads > 1) is_smp = 2;
2896   }
2897 #endif
2898
2899 #ifdef __PPC__
2900   if(is_smp < 2) {
2901     if(!hd_data->devtree) {
2902       hd_free_hd_list(hd_list(hd_data, hw_sys, 1, NULL));
2903     }
2904     is_smp = detect_smp_prom(hd_data);
2905     if(is_smp < 0) is_smp = 0;
2906   }
2907 #endif
2908
2909 #if defined(__s390__) || defined(__s390x__)
2910   if(!is_smp) is_smp = 1;
2911 #endif
2912
2913   return is_smp;
2914 }
2915
2916
2917 int hd_color(hd_data_t *hd_data)
2918 {
2919 #if 0
2920   hd_t *hd;
2921   prom_info_t *pt;
2922
2923   for(hd = hd_data->hd; hd; hd = hd->next) {
2924     if(
2925       hd->base_class.id == bc_internal && hd->sub_class.id == sc_int_prom &&
2926       hd->detail && hd->detail->type == hd_detail_prom &&
2927       (pt = hd->detail->prom.data) &&
2928       pt->has_color
2929     ) {
2930       return pt->color;
2931     }
2932   }
2933 #endif
2934
2935   if(hd_data->color_code) return hd_data->color_code & 0xffff;
2936
2937   return -1;
2938 }
2939
2940
2941 int hd_mac_color(hd_data_t *hd_data)
2942 {
2943   return hd_color(hd_data);
2944 }
2945
2946
2947 unsigned hd_display_adapter(hd_data_t *hd_data)
2948 {
2949   hd_t *hd;
2950   driver_info_t *di;
2951   unsigned disp, disp_sbus, disp_pci, disp_any, disp_di;
2952   unsigned disp_cnt, disp_any_cnt;
2953
2954   /* if we know exactly where our primary display is, return it */
2955   if(hd_get_device_by_idx(hd_data, hd_data->display)) return hd_data->display;
2956
2957   disp = disp_sbus = disp_pci = disp_any = disp_di = 0;
2958   disp_cnt = disp_any_cnt = 0;
2959
2960   for(hd = hd_data->hd; hd; hd = hd->next) {
2961     if(hd->base_class.id == bc_display) {
2962       disp_any_cnt++;
2963       if(!disp_any) disp_any = hd->idx;
2964       if(hd->sub_class.id == sc_dis_vga) {
2965         disp_cnt++;
2966         if(!disp) disp = hd->idx;
2967         if(hd->bus.id == bus_pci && !disp_pci) disp_pci = hd->idx;
2968         if(hd->bus.id == bus_sbus && !disp_sbus) disp_sbus = hd->idx;
2969       }
2970       if(!disp_di) {
2971         if(!(di = hd->driver_info)) {
2972           hddb_add_info(hd_data, hd);
2973           di = hd->driver_info;
2974         }
2975         if(di && di->any.type == di_x11 && di->x11.server) {
2976           disp_di = hd->idx;
2977         }
2978       }
2979     }
2980   }
2981
2982   /* if there's only one display adapter, return it */
2983   if(disp_any_cnt == 1) return disp_any;
2984
2985   /* if there's only one vga compatible adapter, return it */
2986   if(disp_cnt == 1) return disp;
2987
2988   /* return 1st (vga compatible) sbus card */
2989   /* note: the sbus code enters display cards as 'vga compatible' */
2990   if(disp_sbus) return disp_sbus;
2991
2992   /* return 1st display adapter that has some x11 info */
2993   if(disp_di) return disp_di;
2994
2995   /* return 1st vga compatible pci card */
2996   if(disp_pci) return disp_pci;
2997
2998   /* return 1st vga compatible card */
2999   if(disp) return disp;
3000
3001   /* return 1st display adapter */
3002   if(disp_any) return disp_any;
3003
3004   /* there were none... */
3005   return 0;
3006 }
3007
3008
3009 enum cpu_arch hd_cpu_arch(hd_data_t *hd_data)
3010 {
3011   hd_t *hd;
3012
3013   for(hd = hd_data->hd; hd; hd = hd->next) {
3014     if(
3015       hd->base_class.id == bc_internal &&
3016       hd->sub_class.id == sc_int_cpu &&
3017       hd->detail &&
3018       hd->detail->type == hd_detail_cpu &&
3019       hd->detail->cpu.data
3020     ) {
3021       return hd->detail->cpu.data->architecture;
3022     }
3023   }
3024
3025 #ifdef __i386__
3026   return arch_intel;
3027 #else
3028 #ifdef __alpha__
3029   return arch_alpha;
3030 #else
3031 #ifdef __PPC__
3032   return arch_ppc;
3033 #else
3034 #ifdef __sparc__
3035   return arch_sparc;
3036 #else
3037 #ifdef __s390x__
3038   return arch_s390x;
3039 #else
3040 #ifdef __s390__
3041   return arch_s390;
3042 #else
3043 #ifdef __ia64__
3044   return arch_ia64;
3045 #else
3046 #ifdef __x86_64__
3047   return arch_x86_64;
3048 #else
3049   return arch_unknown;
3050 #endif
3051 #endif
3052 #endif
3053 #endif
3054 #endif
3055 #endif
3056 #endif
3057 #endif
3058 }
3059
3060
3061 enum boot_arch hd_boot_arch(hd_data_t *hd_data)
3062 {
3063   return hd_data->boot;
3064 }
3065
3066
3067 int hd_is_uml(hd_data_t *hd_data)
3068 {
3069   int is_uml = 0;
3070   hd_t *hd;
3071   cpu_info_t *ct;
3072   unsigned u;
3073   unsigned saved_mod = hd_data->module;
3074   unsigned char probe_save[sizeof hd_data->probe];
3075
3076   u = hd_data->flags.internal;
3077   hd_data->flags.internal = 1;
3078   hd = hd_list(hd_data, hw_cpu, 0, NULL);
3079   if(!hd) {
3080     /* Do *not* run hd_list(,, 1,) here! */
3081     memcpy(probe_save, hd_data->probe, sizeof probe_save);
3082     hd_set_probe_feature(hd_data, pr_cpu);
3083     hd_scan_cpu(hd_data);
3084     memcpy(hd_data->probe, probe_save, sizeof hd_data->probe);
3085     for(hd = hd_data->hd; hd; hd = hd->next) {
3086       if(hd->base_class.id == bc_internal && hd->sub_class.id == sc_int_cpu) break;
3087     }
3088   }
3089   hd_data->flags.internal = u;
3090
3091   if(
3092     hd &&
3093     hd->detail &&
3094     hd->detail->type == hd_detail_cpu &&
3095     (ct = hd->detail->cpu.data) &&
3096     ct->model_name &&
3097     !strcmp(ct->model_name, "UML")
3098   ) {
3099     is_uml = 1;
3100   }
3101
3102   hd = hd_free_hd_list(hd);
3103
3104   hd_data->module = saved_mod;
3105
3106   return is_uml;
3107 }
3108
3109
3110 int hd_is_sgi_altix(hd_data_t *hd_data)
3111 {
3112   struct stat sbuf;
3113
3114   return stat("/proc/sgi_sn", &sbuf) ? 0 : 1;
3115 }
3116
3117
3118
3119
3120 /*
3121  * check for xen hypervisor
3122  */
3123 int hd_is_xen(hd_data_t *hd_data)
3124 {
3125 #if defined(__i386__) || defined(__x86_64__)
3126
3127   char signature[13];
3128   unsigned u, foo;
3129
3130   __asm__(
3131 #ifdef __i386__
3132     "push %%ebx\n\t"
3133     "cpuid\n\t"
3134     "mov %%ebx,(%%esi)\n\t"
3135     "mov %%ecx,4(%%esi)\n\t"
3136     "mov %%edx,8(%%esi)\n\t"
3137     "pop %%ebx"
3138 #else
3139     "push %%rbx\n\t"
3140     "cpuid\n\t"
3141     "mov %%ebx,(%%rsi)\n\t"
3142     "mov %%ecx,4(%%rsi)\n\t"
3143     "mov %%edx,8(%%rsi)\n\t"
3144     "pop %%rbx"
3145 #endif
3146     : "=a" (u), "=c" (foo)
3147     : "a" (0x40000000), "c" (0), "S" (signature)
3148     : "%edx"
3149   );
3150
3151   signature[12] = 0;
3152
3153   return u < 0x40000002 || strcmp(signature, "XenVMMXenVMM") ? 0 : 1;
3154
3155 #else
3156
3157   return 0;
3158
3159 #endif
3160 }
3161
3162
3163 /*
3164  * makes a (shallow) copy; does some magic fixes
3165  */
3166 void hd_copy(hd_t *dst, hd_t *src)
3167 {
3168   hd_t *tmp;
3169 //  unsigned u;
3170
3171   tmp = dst->next;
3172 //  u = dst->idx;
3173
3174   *dst = *src;
3175   src->ref_cnt++;
3176   dst->ref = src;
3177
3178   dst->next = tmp;
3179 //  dst->idx = u;
3180
3181   /* needed to keep in sync with the real device tree */
3182   if(
3183     dst->detail &&
3184     dst->detail->type == hd_detail_devtree
3185   ) {
3186     dst->detail = NULL;         /* ??? was: free_mem(dst->detail); */
3187   }
3188 }
3189
3190
3191 hd_t *hd_list(hd_data_t *hd_data, hd_hw_item_t item, int rescan, hd_t *hd_old)
3192 {
3193   hd_t *hd, *hd1, *hd_list = NULL;
3194   unsigned char probe_save[sizeof hd_data->probe];
3195   unsigned fast_save;
3196
3197   if(rescan) {
3198     memcpy(probe_save, hd_data->probe, sizeof probe_save);
3199     fast_save = hd_data->flags.fast;
3200     hd_clear_probe_feature(hd_data, pr_all);
3201 #ifdef __powerpc__
3202     hd_set_probe_feature(hd_data, pr_sys);
3203     hd_scan(hd_data);
3204 #endif
3205     hd_set_probe_feature_hw(hd_data, item);
3206     hd_scan(hd_data);
3207     memcpy(hd_data->probe, probe_save, sizeof hd_data->probe);
3208     hd_data->flags.fast = fast_save;
3209   }
3210
3211   for(hd = hd_data->hd; hd; hd = hd->next) {
3212     if(!hd_report_this(hd_data, hd)) continue;
3213
3214     if(
3215       (
3216         item == hw_manual || hd_is_hw_class(hd, item)
3217       )
3218 #ifndef LIBHD_TINY
3219 /* with LIBHD_TINY hd->status is not maintained (cf. manual.c) */
3220       && (
3221         hd_data->hal ||
3222         hd->status.available == status_yes ||
3223         hd->status.available == status_unknown ||
3224         item == hw_manual ||
3225         hd_data->flags.list_all
3226       )
3227 #endif
3228     ) {
3229 //      if(hd->is.softraiddisk) continue;               /* don't report them */
3230
3231       /* don't report old entries again */
3232       for(hd1 = hd_old; hd1; hd1 = hd1->next) {
3233         if(!cmp_hd(hd1, hd)) break;
3234       }
3235       if(!hd1) {
3236         hd1 = add_hd_entry2(&hd_list, new_mem(sizeof *hd_list));
3237         hd_copy(hd1, hd);
3238       }
3239     }
3240   }
3241
3242   if(item == hw_manual) {
3243     for(hd = hd_list; hd; hd = hd->next) {
3244       hd->status.available = hd->status.available_orig;
3245     }
3246   }
3247
3248   return hd_list;
3249 }
3250
3251
3252 hd_t *hd_list_with_status(hd_data_t *hd_data, hd_hw_item_t item, hd_status_t status)
3253 {
3254   hd_t *hd, *hd1, *hd_list = NULL;
3255   unsigned char probe_save[sizeof hd_data->probe];
3256
3257   memcpy(probe_save, hd_data->probe, sizeof probe_save);
3258   hd_clear_probe_feature(hd_data, pr_all);
3259 //  hd_set_probe_feature(hd_data, pr_manual);
3260   hd_scan(hd_data);
3261   memcpy(hd_data->probe, probe_save, sizeof hd_data->probe);
3262
3263   for(hd = hd_data->hd; hd; hd = hd->next) {
3264     if(hd_is_hw_class(hd, item)) {
3265       if(
3266         (status.configured == 0 || status.configured == hd->status.configured) &&
3267         (status.available == 0 || status.available == hd->status.available) &&
3268         (status.needed == 0 || status.needed == hd->status.needed) &&
3269         (status.reconfig == 0 || status.reconfig == hd->status.reconfig)
3270       ) {
3271         hd1 = add_hd_entry2(&hd_list, new_mem(sizeof *hd_list));
3272         hd_copy(hd1, hd);