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