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