13 #include <sys/types.h>
16 #include <sys/ioctl.h>
17 #include <sys/mount.h>
21 typedef unsigned long kernel_ulong_t
;
22 #include <linux/types.h>
23 #include <linux/pci.h>
24 #include <linux/hdreg.h>
25 #define _LINUX_AUDIT_H_
31 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
72 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
73 * various functions commmon to all probing modules
75 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79 #define HD_ARCH "ia32"
83 #define HD_ARCH "ia64"
95 #define HD_ARCH "sparc"
99 #define HD_ARCH "s390x"
102 #define HD_ARCH "s390"
107 #define HD_ARCH "arm"
111 #define HD_ARCH "mips"
115 #define HD_ARCH "x86-64"
119 #define HD_ARCH "hppa"
122 typedef struct disk_s
{
125 unsigned crc_match
:1;
131 static struct s_pr_flags
*get_pr_flags(enum probe_feature feature
);
132 static void fix_probe_features(hd_data_t
*hd_data
);
133 static void set_probe_feature(hd_data_t
*hd_data
, enum probe_feature feature
, unsigned val
);
134 static void free_old_hd_entries(hd_data_t
*hd_data
);
135 static hd_t
*free_hd_entry(hd_t
*hd
);
136 static hd_t
*add_hd_entry2(hd_t
**hd
, hd_t
*new_hd
);
137 static void timeout_alarm_handler(int signal
);
138 static void get_probe_env(hd_data_t
*hd_data
);
139 static void hd_scan_xtra(hd_data_t
*hd_data
);
140 static hd_t
*hd_get_device_by_id(hd_data_t
*hd_data
, char *id
);
141 static int has_item(hd_hw_item_t
*items
, hd_hw_item_t item
);
142 static int has_hw_class(hd_t
*hd
, hd_hw_item_t
*items
);
144 static void test_read_block0_open(void *arg
);
145 static void get_kernel_version(hd_data_t
*hd_data
);
146 static int is_modem(hd_data_t
*hd_data
, hd_t
*hd
);
147 static int is_audio(hd_data_t
*hd_data
, hd_t
*hd
);
148 static void assign_hw_class(hd_data_t
*hd_data
, hd_t
*hd
);
149 static void short_vendor(char *vendor
);
150 static void create_model_name(hd_data_t
*hd_data
, hd_t
*hd
);
152 static void sigchld_handler(int);
153 static pid_t child_id
;
154 static volatile pid_t child
;
155 static char *hd_shm_add_str(hd_data_t
*hd_data
, char *str
);
156 static str_list_t
*hd_shm_add_str_list(hd_data_t
*hd_data
, str_list_t
*sl
);
158 static hd_udevinfo_t
*hd_free_udevinfo(hd_udevinfo_t
*ui
);
159 static hd_sysfsdrv_t
*hd_free_sysfsdrv(hd_sysfsdrv_t
*sf
);
163 * Names of the probing modules.
164 * Cf. enum mod_idx in hd_int.h.
166 static struct s_mod_names
{
171 { mod_memory
, "memory"},
173 { mod_isapnp
, "isapnp"},
174 { mod_pnpdump
, "pnpdump"},
176 { mod_floppy
, "floppy"},
177 { mod_misc
, "misc" },
180 { mod_monitor
, "monitor"},
181 { mod_serial
, "serial"},
182 { mod_mouse
, "mouse"},
186 { mod_modem
, "modem"},
187 { mod_parallel
, "parallel" },
189 { mod_isdn
, "isdn" },
191 { mod_prom
, "prom" },
192 { mod_sbus
, "sbus" },
194 { mod_braille
, "braille" },
197 { mod_manual
, "manual" },
199 { mod_pppoe
, "pppoe" },
200 { mod_pcmcia
, "pcmcia" },
201 { mod_s390
, "s390" },
202 { mod_sysfs
, "sysfs" },
204 { mod_block
, "block" },
206 { mod_input
, "input" }
210 * Names for the probe flags. Used for debugging and command line parsing in
211 * hw.c. Cf. enum probe_feature, hd_data_t.probe.
213 static struct s_pr_flags
{
214 enum probe_feature val
, parent
;
215 unsigned mask
; /* bit 0: default, bit 1: all, bit 2: max, bit 3: linuxrc */
218 { pr_default
, -1, 1, "default" },
219 { pr_all
, -1, 2 , "all" },
220 { pr_max
, -1, 4 , "max" },
221 { pr_lxrc
, -1, 8 , "lxrc" },
222 { pr_memory
, 0, 8|4|2|1, "memory" },
223 { pr_pci
, 0, 8|4|2|1, "pci" },
224 { pr_s390
, 0, 8|4|2|1, "s390" },
225 { pr_s390disks
, 0, 0, "s390disks" },
226 { pr_isapnp
, 0, 4|2|1, "isapnp" },
227 { pr_isapnp_old
, pr_isapnp
, 0, "isapnp.old" },
228 { pr_isapnp_new
, pr_isapnp
, 0, "isapnp.new" },
229 { pr_isapnp_mod
, 0, 4 , "isapnp.mod" },
230 { pr_isapnp
, 0, 0, "pnpdump" }, /* alias for isapnp */
231 { pr_net
, 0, 8|4|2|1, "net" },
232 { pr_floppy
, 0, 8|4|2|1, "floppy" },
233 { pr_misc
, pr_bios
, 8|4|2|1, "misc" }, // ugly hack!
234 { pr_misc_serial
, pr_misc
, 8|4|2|1, "misc.serial" },
235 { pr_misc_par
, pr_misc
, 4|2|1, "misc.par" },
236 { pr_misc_floppy
, pr_misc
, 8|4|2|1, "misc.floppy" },
237 { pr_bios
, 0, 8|4|2|1, "bios" },
238 { pr_bios_vesa
, pr_bios
, 4|2|1, "bios.vesa" },
239 { pr_bios_ddc
, pr_bios_vesa
, 0, "bios.ddc" },
240 { pr_bios_fb
, pr_bios_vesa
, 0, "bios.fb" },
241 { pr_bios_mode
, pr_bios_vesa
, 0, "bios.mode" },
242 { pr_bios_vbe
, pr_bios_mode
, 0, "bios.vbe" }, // just an alias
243 { pr_cpu
, 0, 8|4|2|1, "cpu" },
244 { pr_monitor
, 0, 8|4|2|1, "monitor" },
245 { pr_serial
, 0, 4|2|1, "serial" },
246 #if defined(__sparc__)
247 /* Probe for mouse on SPARC */
248 { pr_mouse
, 0, 8|4|2|1, "mouse" },
250 { pr_mouse
, 0, 4|2|1, "mouse" },
252 { pr_scsi
, 0, 8|4|2|1, "scsi" },
253 { pr_scsi_noserial
, 0, 0, "scsi.noserial" },
254 { pr_usb
, 0, 8|4|2|1, "usb" },
255 { pr_usb_mods
, 0, 4 , "usb.mods" },
256 { pr_adb
, 0, 8|4|2|1, "adb" },
257 { pr_modem
, 0, 4|2|1, "modem" },
258 { pr_modem_usb
, pr_modem
, 4|2|1, "modem.usb" },
259 { pr_parallel
, 0, 4|2|1, "parallel" },
260 { pr_parallel_lp
, pr_parallel
, 4|2|1, "parallel.lp" },
261 { pr_parallel_zip
, pr_parallel
, 4|2|1, "parallel.zip" },
262 { pr_parallel_imm
, 0, 0, "parallel.imm" },
263 { pr_isa
, 0, 4|2|1, "isa" },
264 { pr_isa_isdn
, pr_isa
, 4|2|1, "isa.isdn" },
265 { pr_isdn
, 0, 4|2|1, "isdn" },
266 { pr_kbd
, 0, 8|4|2|1, "kbd" },
267 { pr_prom
, 0, 8|4|2|1, "prom" },
268 { pr_sbus
, 0, 8|4|2|1, "sbus" },
269 { pr_int
, 0, 8|4|2|1, "int" },
270 #if defined(__i386__) || defined (__x86_64__)
271 { pr_braille
, 0, 4|2|1, "braille" },
272 { pr_braille_alva
, pr_braille
, 4|2|1, "braille.alva" },
273 { pr_braille_fhp
, pr_braille
, 4|2|1, "braille.fhp" },
274 { pr_braille_ht
, pr_braille
, 4|2|1, "braille.ht" },
275 { pr_braille_baum
, pr_braille
, 4|2|1, "braille.baum" },
277 { pr_braille
, 0, 4|2 , "braille" },
278 { pr_braille_alva
, pr_braille
, 0, "braille.alva" },
279 { pr_braille_fhp
, pr_braille
, 4|2 , "braille.fhp" },
280 { pr_braille_ht
, pr_braille
, 4|2 , "braille.ht" },
281 { pr_braille_baum
, pr_braille
, 4|2 , "braille.baum" },
283 { pr_ignx11
, 0, 0, "ignx11" },
284 { pr_sys
, 0, 8|4|2|1, "sys" },
285 { pr_manual
, 0, 8|4|2|1, "manual" },
286 { pr_fb
, 0, 8|4|2|1, "fb" },
287 { pr_pppoe
, 0, 8|4|2|1, "pppoe" },
288 /* dummy, used to turn off hwscan */
289 { pr_scan
, 0, 0, "scan" },
290 { pr_pcmcia
, 0, 8|4|2|1, "pcmcia" },
291 { pr_fork
, 0, 0, "fork" },
292 { pr_cpuemu
, 0, 0, "cpuemu" },
293 { pr_cpuemu_debug
, pr_cpuemu
, 0, "cpuemu.debug" },
294 { pr_sysfs
, 0, 0, "sysfs" },
295 { pr_dsl
, 0, 4|2|1, "dsl" },
296 { pr_udev
, 0, 8|4|2|1, "udev" },
297 { pr_block
, 0, 8|4|2|1, "block" },
298 { pr_block_cdrom
, pr_block
, 8|4|2|1, "block.cdrom" },
299 { pr_block_part
, pr_block
, 8|4|2|1, "block.part" },
300 { pr_block_mods
, pr_block
, 8|4|2|1, "block.mods" },
301 { pr_edd
, 0, 8|4|2|1, "edd" },
302 { pr_edd_mod
, pr_edd
, 8|4|2|1, "edd.mod" },
303 { pr_input
, 0, 8|4|2|1, "input" },
304 { pr_wlan
, 0, 8|4|2|1, "wlan" }
307 struct s_pr_flags
*get_pr_flags(enum probe_feature feature
)
311 for(i
= 0; (unsigned) i
< sizeof pr_flags
/ sizeof *pr_flags
; i
++) {
312 if(feature
== pr_flags
[i
].val
) return pr_flags
+ i
;
318 void fix_probe_features(hd_data_t
*hd_data
)
322 for(i
= 0; (unsigned) i
< sizeof hd_data
->probe
; i
++) {
323 hd_data
->probe
[i
] |= hd_data
->probe_set
[i
];
324 hd_data
->probe
[i
] &= ~hd_data
->probe_clr
[i
];
328 void set_probe_feature(hd_data_t
*hd_data
, enum probe_feature feature
, unsigned val
)
330 unsigned ofs
, bit
, mask
;
332 struct s_pr_flags
*pr
;
334 if(!(pr
= get_pr_flags(feature
))) return;
336 if(pr
->parent
== -1u) {
338 for(i
= 0; (unsigned) i
< sizeof pr_flags
/ sizeof *pr_flags
; i
++) {
339 if(pr_flags
[i
].parent
!= -1u && (pr_flags
[i
].mask
& mask
))
340 set_probe_feature(hd_data
, pr_flags
[i
].val
, val
);
344 ofs
= feature
>> 3; bit
= feature
& 7;
345 if(ofs
< sizeof hd_data
->probe
) {
347 hd_data
->probe_set
[ofs
] |= 1 << bit
;
348 hd_data
->probe_clr
[ofs
] &= ~(1 << bit
);
351 hd_data
->probe_clr
[ofs
] |= 1 << bit
;
352 hd_data
->probe_set
[ofs
] &= ~(1 << bit
);
355 if(pr
->parent
) set_probe_feature(hd_data
, pr
->parent
, val
);
358 fix_probe_features(hd_data
);
361 void hd_set_probe_feature(hd_data_t
*hd_data
, enum probe_feature feature
)
363 unsigned ofs
, bit
, mask
;
365 struct s_pr_flags
*pr
;
367 #ifdef LIBHD_MEMCHECK
370 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_set_probe_feature
, hd_data
), hd_data
);
374 if(!(pr
= get_pr_flags(feature
))) return;
376 if(pr
->parent
== -1u) {
378 for(i
= 0; (unsigned) i
< sizeof pr_flags
/ sizeof *pr_flags
; i
++) {
379 if(pr_flags
[i
].parent
!= -1u && (pr_flags
[i
].mask
& mask
))
380 hd_set_probe_feature(hd_data
, pr_flags
[i
].val
);
384 ofs
= feature
>> 3; bit
= feature
& 7;
385 if(ofs
< sizeof hd_data
->probe
)
386 hd_data
->probe
[ofs
] |= 1 << bit
;
387 if(pr
->parent
) hd_set_probe_feature(hd_data
, pr
->parent
);
390 fix_probe_features(hd_data
);
393 void hd_clear_probe_feature(hd_data_t
*hd_data
, enum probe_feature feature
)
395 unsigned ofs
, bit
, mask
;
397 struct s_pr_flags
*pr
;
399 #ifdef LIBHD_MEMCHECK
402 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_clear_probe_feature
, hd_data
), hd_data
);
406 if(!(pr
= get_pr_flags(feature
))) return;
408 if(pr
->parent
== -1u) {
410 for(i
= 0; (unsigned) i
< sizeof pr_flags
/ sizeof *pr_flags
; i
++) {
411 if(pr_flags
[i
].parent
!= -1u && (pr_flags
[i
].mask
& mask
))
412 hd_clear_probe_feature(hd_data
, pr_flags
[i
].val
);
416 ofs
= feature
>> 3; bit
= feature
& 7;
417 if(ofs
< sizeof hd_data
->probe
)
418 hd_data
->probe
[ofs
] &= ~(1 << bit
);
422 int hd_probe_feature(hd_data_t
*hd_data
, enum probe_feature feature
)
424 #ifdef LIBHD_MEMCHECK
427 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_probe_feature
, hd_data
), hd_data
);
431 if(feature
< 0 || feature
>= pr_default
) return 0;
433 return hd_data
->probe
[feature
>> 3] & (1 << (feature
& 7)) ? 1 : 0;
437 void hd_set_probe_feature_hw(hd_data_t
*hd_data
, hd_hw_item_t item
)
439 hd_set_probe_feature(hd_data
, pr_int
);
440 hd_set_probe_feature(hd_data
, pr_manual
);
444 hd_set_probe_feature(hd_data
, pr_pci
);
445 hd_set_probe_feature(hd_data
, pr_usb
);
446 hd_set_probe_feature(hd_data
, pr_block_mods
);
447 hd_set_probe_feature(hd_data
, pr_scsi
);
448 if(!hd_data
->flags
.fast
) {
449 hd_set_probe_feature(hd_data
, pr_block_cdrom
);
454 hd_set_probe_feature(hd_data
, pr_floppy
);
455 hd_set_probe_feature(hd_data
, pr_misc_floppy
);
456 hd_set_probe_feature(hd_data
, pr_prom
);
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
);
460 hd_set_probe_feature(hd_data
, pr_block_mods
);
461 hd_set_probe_feature(hd_data
, pr_scsi
);
465 hd_set_probe_feature(hd_data
, pr_block_part
);
468 hd_set_probe_feature(hd_data
, pr_s390disks
);
469 hd_set_probe_feature(hd_data
, pr_bios
); // bios disk order
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_edd_mod
);
475 hd_set_probe_feature(hd_data
, pr_scsi
);
479 hd_set_probe_feature(hd_data
, pr_prom
);
480 hd_set_probe_feature(hd_data
, pr_s390disks
);
481 hd_set_probe_feature(hd_data
, pr_bios
); // bios disk order
482 hd_set_probe_feature(hd_data
, pr_pci
);
483 hd_set_probe_feature(hd_data
, pr_usb
);
484 hd_set_probe_feature(hd_data
, pr_block
);
485 hd_set_probe_feature(hd_data
, pr_block_mods
);
486 hd_set_probe_feature(hd_data
, pr_edd_mod
);
487 hd_set_probe_feature(hd_data
, pr_scsi
);
488 if(!hd_data
->flags
.fast
) {
489 hd_set_probe_feature(hd_data
, pr_floppy
);
490 hd_set_probe_feature(hd_data
, pr_misc_floppy
);
491 hd_set_probe_feature(hd_data
, pr_block_cdrom
);
493 hd_set_probe_feature(hd_data
, pr_block_part
);
497 hd_set_probe_feature(hd_data
, pr_net
);
498 hd_set_probe_feature(hd_data
, pr_pci
);
499 hd_set_probe_feature(hd_data
, pr_prom
);
500 hd_set_probe_feature(hd_data
, pr_usb
);
504 hd_set_probe_feature(hd_data
, pr_pci
);
505 hd_set_probe_feature(hd_data
, pr_sbus
);
506 hd_set_probe_feature(hd_data
, pr_prom
);
507 hd_set_probe_feature(hd_data
, pr_misc
); /* for isa cards */
511 hd_set_probe_feature(hd_data
, pr_misc
);
512 hd_set_probe_feature(hd_data
, pr_prom
);
513 hd_set_probe_feature(hd_data
, pr_pci
);
514 hd_set_probe_feature(hd_data
, pr_bios_ddc
);
515 hd_set_probe_feature(hd_data
, pr_fb
);
516 hd_set_probe_feature(hd_data
, pr_monitor
);
520 hd_set_probe_feature(hd_data
, pr_misc
);
521 hd_set_probe_feature(hd_data
, pr_prom
);
522 hd_set_probe_feature(hd_data
, pr_pci
);
523 hd_set_probe_feature(hd_data
, pr_bios_fb
);
524 hd_set_probe_feature(hd_data
, pr_fb
);
528 hd_set_probe_feature(hd_data
, pr_misc
);
529 if(!hd_data
->flags
.fast
) {
530 hd_set_probe_feature(hd_data
, pr_serial
);
532 hd_set_probe_feature(hd_data
, pr_adb
);
533 hd_set_probe_feature(hd_data
, pr_usb
);
534 hd_set_probe_feature(hd_data
, pr_kbd
);
535 hd_set_probe_feature(hd_data
, pr_sys
);
536 hd_set_probe_feature(hd_data
, pr_bios
);
537 hd_set_probe_feature(hd_data
, pr_mouse
);
538 hd_set_probe_feature(hd_data
, pr_input
);
542 hd_set_probe_feature(hd_data
, pr_usb
);
543 hd_set_probe_feature(hd_data
, pr_input
);
547 hd_set_probe_feature(hd_data
, pr_misc
);
548 if(!hd_data
->flags
.fast
) {
549 hd_set_probe_feature(hd_data
, pr_serial
);
551 hd_set_probe_feature(hd_data
, pr_usb
);
552 hd_set_probe_feature(hd_data
, pr_mouse
); /* we need the pnp code */
556 hd_set_probe_feature(hd_data
, pr_usb
);
560 hd_set_probe_feature(hd_data
, pr_cpu
);
561 hd_set_probe_feature(hd_data
, pr_misc
);
562 hd_set_probe_feature(hd_data
, pr_adb
);
563 hd_set_probe_feature(hd_data
, pr_usb
);
564 hd_set_probe_feature(hd_data
, pr_kbd
);
565 hd_set_probe_feature(hd_data
, pr_input
);
567 hd_set_probe_feature(hd_data
, pr_serial
);
572 hd_set_probe_feature(hd_data
, pr_misc
);
573 hd_set_probe_feature(hd_data
, pr_pci
);
574 hd_set_probe_feature(hd_data
, pr_isapnp
);
575 hd_set_probe_feature(hd_data
, pr_isapnp_mod
);
576 hd_set_probe_feature(hd_data
, pr_sbus
);
577 hd_set_probe_feature(hd_data
, pr_prom
);
581 hd_set_probe_feature(hd_data
, pr_misc
); /* get basic i/o res */
582 hd_set_probe_feature(hd_data
, pr_pci
);
583 hd_set_probe_feature(hd_data
, pr_pcmcia
);
584 hd_set_probe_feature(hd_data
, pr_isapnp
);
585 hd_set_probe_feature(hd_data
, pr_isapnp_mod
);
586 hd_set_probe_feature(hd_data
, pr_isa_isdn
);
587 hd_set_probe_feature(hd_data
, pr_usb
);
588 hd_set_probe_feature(hd_data
, pr_isdn
);
592 hd_set_probe_feature(hd_data
, pr_misc
);
593 hd_set_probe_feature(hd_data
, pr_serial
);
594 hd_set_probe_feature(hd_data
, pr_usb
);
595 hd_set_probe_feature(hd_data
, pr_pci
);
596 hd_set_probe_feature(hd_data
, pr_modem
);
597 hd_set_probe_feature(hd_data
, pr_modem_usb
);
600 case hw_storage_ctrl
:
601 hd_set_probe_feature(hd_data
, pr_floppy
);
602 hd_set_probe_feature(hd_data
, pr_sys
);
603 hd_set_probe_feature(hd_data
, pr_pci
);
604 hd_set_probe_feature(hd_data
, pr_sbus
);
605 if(!hd_data
->flags
.fast
) {
606 hd_set_probe_feature(hd_data
, pr_misc_par
);
607 hd_set_probe_feature(hd_data
, pr_parallel_zip
);
609 hd_set_probe_feature(hd_data
, pr_s390
);
610 hd_set_probe_feature(hd_data
, pr_prom
);
612 hd_set_probe_feature(hd_data
, pr_misc
);
616 case hw_network_ctrl
:
617 hd_set_probe_feature(hd_data
, pr_misc
);
618 hd_set_probe_feature(hd_data
, pr_usb
);
619 hd_set_probe_feature(hd_data
, pr_pci
);
620 hd_set_probe_feature(hd_data
, pr_net
);
621 hd_set_probe_feature(hd_data
, pr_pcmcia
);
622 hd_set_probe_feature(hd_data
, pr_isapnp
);
623 hd_set_probe_feature(hd_data
, pr_isapnp_mod
);
624 hd_set_probe_feature(hd_data
, pr_sbus
);
625 hd_set_probe_feature(hd_data
, pr_isdn
);
626 hd_set_probe_feature(hd_data
, pr_dsl
);
627 hd_set_probe_feature(hd_data
, pr_prom
);
628 hd_set_probe_feature(hd_data
, pr_s390
);
629 hd_set_probe_feature(hd_data
, pr_wlan
);
633 hd_set_probe_feature(hd_data
, pr_sys
);
634 hd_set_probe_feature(hd_data
, pr_bios
);
635 hd_set_probe_feature(hd_data
, pr_misc_par
);
636 hd_set_probe_feature(hd_data
, pr_parallel_lp
);
637 hd_set_probe_feature(hd_data
, pr_usb
);
641 hd_set_probe_feature(hd_data
, pr_pcmcia
);
642 hd_set_probe_feature(hd_data
, pr_wlan
);
643 hd_set_probe_feature(hd_data
, pr_pci
);
644 hd_set_probe_feature(hd_data
, pr_usb
);
645 hd_set_probe_feature(hd_data
, pr_net
);
650 hd_set_probe_feature(hd_data
, pr_pci
);
654 hd_set_probe_feature(hd_data
, pr_pci
);
655 hd_set_probe_feature(hd_data
, pr_usb
);
656 hd_set_probe_feature(hd_data
, pr_scsi
);
660 hd_set_probe_feature(hd_data
, pr_misc_serial
);
661 hd_set_probe_feature(hd_data
, pr_serial
);
662 hd_set_probe_feature(hd_data
, pr_braille_alva
);
663 hd_set_probe_feature(hd_data
, pr_braille_fhp
);
664 hd_set_probe_feature(hd_data
, pr_braille_ht
);
665 hd_set_probe_feature(hd_data
, pr_braille_baum
);
666 hd_set_probe_feature(hd_data
, pr_usb
);
670 hd_set_probe_feature(hd_data
, pr_bios
);
671 hd_set_probe_feature(hd_data
, pr_prom
);
672 hd_set_probe_feature(hd_data
, pr_s390
);
673 hd_set_probe_feature(hd_data
, pr_sys
);
677 hd_set_probe_feature(hd_data
, pr_cpu
);
681 hd_set_probe_feature(hd_data
, pr_bios
);
682 hd_set_probe_feature(hd_data
, pr_edd_mod
);
686 hd_set_probe_feature(hd_data
, pr_bios_ddc
);
687 hd_set_probe_feature(hd_data
, pr_bios_fb
);
688 hd_set_probe_feature(hd_data
, pr_bios_mode
);
689 hd_set_probe_feature(hd_data
, pr_monitor
);
693 hd_set_probe_feature(hd_data
, pr_manual
);
698 case hw_ieee1394_ctrl
:
699 case hw_hotplug_ctrl
:
700 hd_set_probe_feature(hd_data
, pr_misc
);
701 hd_set_probe_feature(hd_data
, pr_pci
);
705 hd_set_probe_feature(hd_data
, pr_usb
);
706 hd_set_probe_feature(hd_data
, pr_isdn
); // need pr_misc, too?
707 hd_set_probe_feature(hd_data
, pr_dsl
);
708 hd_set_probe_feature(hd_data
, pr_block
);
709 hd_set_probe_feature(hd_data
, pr_block_mods
);
710 hd_set_probe_feature(hd_data
, pr_scsi
);
711 hd_set_probe_feature(hd_data
, pr_net
);
712 hd_data
->flags
.fast
= 1;
716 hd_set_probe_feature(hd_data
, pr_misc
);
717 hd_set_probe_feature(hd_data
, pr_pci
);
718 hd_set_probe_feature(hd_data
, pr_net
);
719 hd_set_probe_feature(hd_data
, pr_isdn
);
720 hd_set_probe_feature(hd_data
, pr_dsl
);
721 hd_set_probe_feature(hd_data
, pr_prom
);
725 hd_set_probe_feature(hd_data
, pr_isapnp
);
726 hd_set_probe_feature(hd_data
, pr_isapnp_mod
);
727 hd_set_probe_feature(hd_data
, pr_misc
);
728 hd_set_probe_feature(hd_data
, pr_isdn
);
732 hd_set_probe_feature(hd_data
, pr_misc
);
733 hd_set_probe_feature(hd_data
, pr_pci
);
737 hd_set_probe_feature(hd_data
, pr_usb
);
741 hd_set_probe_feature(hd_data
, pr_memory
);
746 hd_set_probe_feature(hd_data
, pr_pci
);
747 hd_set_probe_feature(hd_data
, pr_block
);
748 hd_set_probe_feature(hd_data
, pr_block_mods
);
749 hd_set_probe_feature(hd_data
, pr_scsi
);
753 hd_set_probe_feature(hd_data
, pr_pci
);
754 hd_set_probe_feature(hd_data
, pr_block
);
755 hd_set_probe_feature(hd_data
, pr_block_mods
);
759 hd_set_probe_feature(hd_data
, pr_net
);
760 hd_set_probe_feature(hd_data
, pr_pppoe
);
764 hd_set_probe_feature(hd_data
, pr_net
);
765 hd_set_probe_feature(hd_data
, pr_pci
);
766 hd_set_probe_feature(hd_data
, pr_pppoe
);
767 hd_set_probe_feature(hd_data
, pr_usb
);
771 hd_set_probe_feature(hd_data
, pr_pci
);
772 hd_set_probe_feature(hd_data
, pr_pcmcia
);
773 hd_set_probe_feature(hd_data
, pr_wlan
);
774 hd_set_probe_feature(hd_data
, pr_net
);
775 hd_set_probe_feature(hd_data
, pr_isdn
);
779 hd_set_probe_feature(hd_data
, pr_usb
);
780 hd_set_probe_feature(hd_data
, pr_isdn
); // need pr_misc, too?
781 hd_set_probe_feature(hd_data
, pr_dsl
);
785 hd_set_probe_feature(hd_data
, pr_default
);
789 hd_set_probe_feature(hd_data
, pr_block
);
790 hd_set_probe_feature(hd_data
, pr_block_mods
);
803 * Free all data associated with a hd_data_t struct. *Not* the struct itself.
805 hd_data_t
*hd_free_hd_data(hd_data_t
*hd_data
)
810 #ifdef LIBHD_MEMCHECK
813 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_free_hd_data
, hd_data
), hd_data
);
817 add_hd_entry2(&hd_data
->old_hd
, hd_data
->hd
); hd_data
->hd
= NULL
;
818 hd_data
->log
= free_mem(hd_data
->log
);
819 free_old_hd_entries(hd_data
); /* hd_data->old_hd */
820 /* hd_data->pci is always NULL */
821 /* hd_data->isapnp->card is always NULL */
822 hd_data
->isapnp
= free_mem(hd_data
->isapnp
);
823 /* hd_data->cdrom is always NULL */
824 hd_data
->net
= free_str_list(hd_data
->net
);
825 hd_data
->floppy
= free_str_list(hd_data
->floppy
);
826 hd_data
->misc
= free_misc(hd_data
->misc
);
827 /* hd_data->serial is always NULL */
828 /* hd_data->scsi is always NULL */
829 /* hd_data->ser_mouse is always NULL */
830 /* hd_data->ser_modem is always NULL */
831 hd_data
->cpu
= free_str_list(hd_data
->cpu
);
832 hd_data
->klog
= free_str_list(hd_data
->klog
);
833 hd_data
->proc_usb
= free_str_list(hd_data
->proc_usb
);
834 /* hd_data->usb is always NULL */
836 if((p
= hd_data
->hddb_pci
)) {
837 for(; p
->module
; p
++) free_mem(p
->module
);
839 if(hd_data
->hddb2
[0]) {
840 free_mem(hd_data
->hddb2
[0]->list
);
841 free_mem(hd_data
->hddb2
[0]->ids
);
842 free_mem(hd_data
->hddb2
[0]->strings
);
843 hd_data
->hddb2
[0] = free_mem(hd_data
->hddb2
[0]);
845 /* hddb2[1] is the static internal database; don't try to free it! */
846 hd_data
->hddb2
[1] = NULL
;
848 hd_data
->hddb_pci
= free_mem(hd_data
->hddb_pci
);
849 hd_data
->kmods
= free_str_list(hd_data
->kmods
);
850 hd_data
->bios_rom
.data
= free_mem(hd_data
->bios_rom
.data
);
851 hd_data
->bios_ram
.data
= free_mem(hd_data
->bios_ram
.data
);
852 hd_data
->bios_ebda
.data
= free_mem(hd_data
->bios_ebda
.data
);
853 hd_data
->cmd_line
= free_mem(hd_data
->cmd_line
);
854 hd_data
->xtra_hd
= free_str_list(hd_data
->xtra_hd
);
855 hd_data
->devtree
= free_devtree(hd_data
);
856 hd_data
->manual
= hd_free_manual(hd_data
->manual
);
857 hd_data
->disks
= free_str_list(hd_data
->disks
);
858 hd_data
->partitions
= free_str_list(hd_data
->partitions
);
859 hd_data
->cdroms
= free_str_list(hd_data
->cdroms
);
861 hd_data
->smbios
= smbios_free(hd_data
->smbios
);
863 hd_data
->udevinfo
= hd_free_udevinfo(hd_data
->udevinfo
);
864 hd_data
->sysfsdrv
= hd_free_sysfsdrv(hd_data
->sysfsdrv
);
866 hd_data
->only
= free_str_list(hd_data
->only
);
867 hd_data
->scanner_db
= free_str_list(hd_data
->scanner_db
);
869 for(u
= 0; u
< sizeof hd_data
->edd
/ sizeof *hd_data
->edd
; u
++) {
870 hd_data
->edd
[u
].sysfs_id
= free_mem(hd_data
->edd
[u
].sysfs_id
);
873 hd_data
->last_idx
= 0;
875 hd_shm_done(hd_data
);
877 memset(hd_data
, 0, sizeof *hd_data
);
884 * Free all data associated with a driver_info_t struct. Even the struct itself.
886 driver_info_t
*free_driver_info(driver_info_t
*di
)
890 #ifdef LIBHD_MEMCHECK
893 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(free_driver_info
, di
), di
);
897 for(; di
; di
= next
) {
900 switch(di
->any
.type
) {
906 free_str_list(di
->module
.names
);
907 free_str_list(di
->module
.mod_args
);
908 free_mem(di
->module
.conf
);
912 free_mem(di
->mouse
.xf86
);
913 free_mem(di
->mouse
.gpm
);
917 free_mem(di
->x11
.server
);
918 free_mem(di
->x11
.xf86_ver
);
919 free_str_list(di
->x11
.extensions
);
920 free_str_list(di
->x11
.options
);
921 free_str_list(di
->x11
.raw
);
922 free_mem(di
->x11
.script
);
926 free_mem(di
->isdn
.i4l_name
);
927 if(di
->isdn
.params
) {
928 isdn_parm_t
*p
= di
->isdn
.params
, *next
;
932 free_mem(p
->alt_value
);
939 free_mem(di
->dsl
.name
);
940 free_mem(di
->dsl
.mode
);
944 free_mem(di
->kbd
.XkbRules
);
945 free_mem(di
->kbd
.XkbModel
);
946 free_mem(di
->kbd
.XkbLayout
);
947 free_mem(di
->kbd
.keymap
);
951 free_str_list(di
->any
.hddb0
);
952 free_str_list(di
->any
.hddb1
);
961 int exists_hd_entry(hd_data_t
*hd_data
, hd_t
*old_hd
, hd_t
*hd_ex
)
967 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
968 if(hd
== hd_ex
) return 1;
970 for(hd
= old_hd
; hd
; hd
= hd
->next
) {
971 if(hd
== hd_ex
) return 1;
979 * \note This may not free it.
981 hd_t
*hd_free_hd_list(hd_t
*hd
)
985 #ifdef LIBHD_MEMCHECK
988 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_free_hd_list
, hd
), hd
);
992 /* Note: hd->next should better be NULL! */
993 if(hd
&& hd
->tag
.freeit
) {
998 /* do nothing unless the list holds only copies of hd_t entries */
999 for(h
= hd
; h
; h
= h
->next
) if(!h
->ref
) return NULL
;
1001 for(; hd
; hd
= (h
= hd
)->next
, free_mem(h
));
1006 hd_detail_t
*free_hd_detail(hd_detail_t
*d
)
1011 case hd_detail_pci
: {
1012 pci_t
*p
= d
->pci
.data
;
1015 free_mem(p
->sysfs_id
);
1016 free_mem(p
->sysfs_bus_id
);
1023 usb_t
*u
= d
->usb
.data
;
1026 free_str_list(u
->c
);
1027 free_str_list(u
->e
);
1029 free_str_list(u
->d
);
1030 free_str_list(u
->p
);
1031 free_str_list(u
->s
);
1032 free_str_list(u
->t
);
1033 free_str_list(u
->i
);
1035 free_mem(u
->manufact
);
1036 free_mem(u
->product
);
1037 free_mem(u
->serial
);
1038 free_mem(u
->driver
);
1039 free_mem(u
->raw_descr
.data
);
1045 case hd_detail_isapnp
:
1047 isapnp_dev_t
*i
= d
->isapnp
.data
;
1051 free_mem(i
->card
->serial
);
1052 free_mem(i
->card
->card_regs
);
1053 free_mem(i
->card
->ldev_regs
);
1054 for(j
= 0; j
< i
->card
->res_len
; j
++) {
1055 free_mem(i
->card
->res
[j
].data
);
1057 if(i
->card
->res
) free_mem(i
->card
->res
);
1064 case hd_detail_cdrom
:
1066 cdrom_info_t
*c
= d
->cdrom
.data
;
1070 free_mem(c
->iso9660
.volume
);
1071 free_mem(c
->iso9660
.publisher
);
1072 free_mem(c
->iso9660
.preparer
);
1073 free_mem(c
->iso9660
.application
);
1074 free_mem(c
->iso9660
.creation_date
);
1075 free_mem(c
->el_torito
.id_string
);
1076 free_mem(c
->el_torito
.label
);
1083 case hd_detail_floppy
:
1084 free_mem(d
->floppy
.data
);
1087 case hd_detail_bios
:
1089 bios_info_t
*b
= d
->bios
.data
;
1091 free_mem(b
->vbe
.oem_name
);
1092 free_mem(b
->vbe
.vendor_name
);
1093 free_mem(b
->vbe
.product_name
);
1094 free_mem(b
->vbe
.product_revision
);
1095 free_mem(b
->vbe
.mode
);
1096 free_mem(b
->lcd
.vendor
);
1097 free_mem(b
->lcd
.name
);
1098 free_mem(b
->mouse
.vendor
);
1099 free_mem(b
->mouse
.type
);
1107 cpu_info_t
*c
= d
->cpu
.data
;
1109 free_mem(c
->vend_name
);
1110 free_mem(c
->model_name
);
1111 free_mem(c
->platform
);
1112 free_str_list(c
->features
);
1117 case hd_detail_prom
:
1118 free_mem(d
->prom
.data
);
1121 case hd_detail_monitor
:
1123 monitor_info_t
*m
= d
->monitor
.data
;
1125 free_mem(m
->vendor
);
1127 free_mem(m
->serial
);
1135 sys_info_t
*s
= d
->sys
.data
;
1137 free_mem(s
->system_type
);
1138 free_mem(s
->generation
);
1139 free_mem(s
->vendor
);
1141 free_mem(s
->serial
);
1148 case hd_detail_scsi
:
1149 free_scsi(d
->scsi
.data
, 1);
1152 case hd_detail_devtree
:
1153 /* is freed with hd_data->dev_tree */
1157 free_mem(d
->ccw
.data
);
1167 hd_t
*free_hd_entry(hd_t
*hd
)
1169 free_mem(hd
->bus
.name
);
1170 free_mem(hd
->base_class
.name
);
1171 free_mem(hd
->sub_class
.name
);
1172 free_mem(hd
->prog_if
.name
);
1173 free_mem(hd
->vendor
.name
);
1174 free_mem(hd
->device
.name
);
1175 free_mem(hd
->sub_vendor
.name
);
1176 free_mem(hd
->sub_device
.name
);
1177 free_mem(hd
->revision
.name
);
1178 free_mem(hd
->serial
);
1179 free_mem(hd
->compat_vendor
.name
);
1180 free_mem(hd
->compat_device
.name
);
1181 free_mem(hd
->model
);
1182 free_mem(hd
->sysfs_id
);
1183 free_mem(hd
->sysfs_bus_id
);
1184 free_mem(hd
->sysfs_device_link
);
1185 free_str_list(hd
->unix_dev_names
);
1186 free_mem(hd
->unix_dev_name
);
1187 free_mem(hd
->unix_dev_name2
);
1188 free_mem(hd
->rom_id
);
1189 free_mem(hd
->unique_id
);
1190 free_mem(hd
->block0
);
1191 free_mem(hd
->driver
);
1192 free_str_list(hd
->drivers
);
1193 free_mem(hd
->old_unique_id
);
1194 free_mem(hd
->unique_id1
);
1195 free_mem(hd
->usb_guid
);
1196 free_mem(hd
->parent_id
);
1197 free_str_list(hd
->child_ids
);
1198 free_mem(hd
->config_string
);
1199 free_str_list(hd
->extra_info
);
1201 free_res_list(hd
->res
);
1203 free_hd_detail(hd
->detail
);
1205 free_driver_info(hd
->driver_info
);
1206 free_str_list(hd
->requires
);
1208 memset(hd
, 0, sizeof *hd
);
1213 misc_t
*free_misc(misc_t
*m
)
1219 for(i
= 0; (unsigned) i
< m
->io_len
; i
++) {
1220 free_mem(m
->io
[i
].dev
);
1224 for(i
= 0; (unsigned) i
< m
->dma_len
; i
++) {
1225 free_mem(m
->dma
[i
].dev
);
1229 for(i
= 0; (unsigned) i
< m
->irq_len
; i
++) {
1230 for(j
= 0; j
< m
->irq
[i
].devs
; j
++) {
1231 free_mem(m
->irq
[i
].dev
[j
]);
1233 free_mem(m
->irq
[i
].dev
);
1237 free_str_list(m
->proc_io
);
1238 free_str_list(m
->proc_dma
);
1239 free_str_list(m
->proc_irq
);
1246 scsi_t
*free_scsi(scsi_t
*scsi
, int free_all
)
1250 for(; scsi
; scsi
= next
) {
1253 free_mem(scsi
->dev_name
);
1254 free_mem(scsi
->guessed_dev_name
);
1255 free_mem(scsi
->vendor
);
1256 free_mem(scsi
->model
);
1257 free_mem(scsi
->rev
);
1258 free_mem(scsi
->type_str
);
1259 free_mem(scsi
->serial
);
1260 free_mem(scsi
->proc_dir
);
1261 free_mem(scsi
->driver
);
1262 free_mem(scsi
->info
);
1263 free_mem(scsi
->usb_guid
);
1264 free_str_list(scsi
->host_info
);
1265 free_mem(scsi
->controller_id
);
1269 memset(scsi
, 0, sizeof scsi
);
1281 hd_manual_t
*hd_free_manual(hd_manual_t
*manual
)
1285 if(!manual
) return NULL
;
1287 for(; manual
; manual
= next
) {
1288 next
= manual
->next
;
1290 free_mem(manual
->unique_id
);
1291 free_mem(manual
->parent_id
);
1292 free_mem(manual
->child_ids
);
1293 free_mem(manual
->model
);
1295 free_mem(manual
->config_string
);
1297 free_str_list(manual
->key
);
1298 free_str_list(manual
->value
);
1308 * Removes all hd_data->old_hd entries and frees their memory.
1310 void free_old_hd_entries(hd_data_t
*hd_data
)
1314 for(hd
= hd_data
->old_hd
; hd
; hd
= next
) {
1317 if(exists_hd_entry(hd_data
, next
, hd
->ref
) && hd
->ref
->ref_cnt
) hd
->ref
->ref_cnt
--;
1319 if(!hd
->ref
) free_hd_entry(hd
);
1324 hd_data
->old_hd
= NULL
;
1328 void *new_mem(size_t size
)
1332 if(size
== 0) return NULL
;
1334 p
= calloc(size
, 1);
1336 #ifdef LIBHD_MEMCHECK
1338 if(libhd_log
) fprintf(libhd_log
, "%p\t%p\t0x%x\n", CALLED_FROM(new_mem
, size
), p
, size
);
1344 fprintf(stderr
, "memory oops 1\n");
1350 void *resize_mem(void *p
, size_t n
)
1352 #ifdef LIBHD_MEMCHECK
1354 if(libhd_log
&& p
) fprintf(libhd_log
, "%p\t%p\n", CALLED_FROM(resize_mem
, p
), p
);
1360 #ifdef LIBHD_MEMCHECK
1362 if(libhd_log
) fprintf(libhd_log
, "%p\t%p\t0x%x\n", CALLED_FROM(resize_mem
, p
), p
, n
);
1367 fprintf(stderr
, "memory oops 7\n");
1374 void *add_mem(void *p
, size_t elem_size
, size_t n
)
1376 #ifdef LIBHD_MEMCHECK
1378 if(libhd_log
&& p
) fprintf(libhd_log
, "%p\t%p\n", CALLED_FROM(add_mem
, p
), p
);
1382 p
= realloc(p
, (n
+ 1) * elem_size
);
1384 #ifdef LIBHD_MEMCHECK
1386 if(libhd_log
) fprintf(libhd_log
, "%p\t%p\t0x%x\n", CALLED_FROM(add_mem
, p
), p
, (n
+ 1) * elem_size
);
1391 fprintf(stderr
, "memory oops 7\n");
1395 memset(p
+ n
* elem_size
, 0, elem_size
);
1400 char *new_str(const char *s
)
1408 #ifdef LIBHD_MEMCHECK
1410 if(libhd_log
) fprintf(libhd_log
, "%p\t%p\t0x%x\n", CALLED_FROM(new_str
, s
), t
, strlen(t
) + 1);
1416 fprintf(stderr
, "memory oops 2\n");
1423 void *free_mem(void *p
)
1425 #ifdef LIBHD_MEMCHECK
1427 if(libhd_log
&& p
) fprintf(libhd_log
, "%p\t%p\n", CALLED_FROM(free_mem
, p
), p
);
1436 void join_res_io(hd_res_t
**res1
, hd_res_t
*res2
)
1441 * see if we must add an i/o range (tricky...)
1443 * We look for identical i/o bases and add a range if one was missing. If
1444 * no matching pair was found, add the i/o resource.
1446 for(; res2
; res2
= res2
->next
) {
1447 if(res2
->io
.type
== res_io
) {
1448 for(res
= *res1
; res
; res
= res
->next
) {
1449 if(res
->io
.type
== res_io
) {
1450 if(res
->io
.base
== res2
->io
.base
) {
1451 /* identical bases: take maximum of both ranges */
1452 if(res2
->io
.range
> res
->io
.range
) {
1453 res
->io
.range
= res2
->io
.range
;
1460 res
->io
.base
+ res
->io
.range
== res2
->io
.base
)
1462 /* res2 directly follows res1: extend res1 to cover res2 */
1463 res
->io
.range
+= res2
->io
.range
;
1467 res2
->io
.base
>= res
->io
.base
&&
1468 res2
->io
.base
< res
->io
.base
+ res
->io
.range
1470 /* res2 is totally contained in res1: ignore it */
1476 res
= add_res_entry(res1
, new_mem(sizeof *res
));
1477 *res
= *res2
; /* *copy* the struct */
1484 void join_res_irq(hd_res_t
**res1
, hd_res_t
*res2
)
1488 /* see if we must add an dma channel */
1489 for(; res2
; res2
= res2
->next
) {
1490 if(res2
->irq
.type
== res_irq
) {
1491 for(res
= *res1
; res
; res
= res
->next
) {
1492 if(res
->irq
.type
== res_irq
&& res
->irq
.base
== res2
->irq
.base
) break;
1495 res
= add_res_entry(res1
, new_mem(sizeof *res
));
1496 *res
= *res2
; /* *copy* the struct */
1504 void join_res_dma(hd_res_t
**res1
, hd_res_t
*res2
)
1508 /* see if we must add an dma channel */
1509 for(; res2
; res2
= res2
->next
) {
1510 if(res2
->dma
.type
== res_dma
) {
1511 for(res
= *res1
; res
; res
= res
->next
) {
1512 if(res
->dma
.type
== res_dma
&& res
->dma
.base
== res2
->dma
.base
) break;
1515 res
= add_res_entry(res1
, new_mem(sizeof *res
));
1516 *res
= *res2
; /* *copy* the struct */
1525 * Check whether both resource lists have common entries.
1527 int have_common_res(hd_res_t
*res1
, hd_res_t
*res2
)
1531 for(; res1
; res1
= res1
->next
) {
1532 for(res
= res2
; res
; res
= res
->next
) {
1533 if(res
->any
.type
== res1
->any
.type
) {
1534 switch(res
->any
.type
) {
1536 if(res
->io
.base
== res1
->io
.base
) return 1;
1540 if(res
->irq
.base
== res1
->irq
.base
) return 1;
1544 if(res
->dma
.base
== res1
->dma
.base
) return 1;
1547 default: /* gcc -Wall */
1559 * Free the memory allocated by a resource list.
1561 hd_res_t
*free_res_list(hd_res_t
*res
)
1565 for(; res
; res
= next
) {
1568 if(res
->any
.type
== res_init_strings
) {
1569 free_mem(res
->init_strings
.init1
);
1570 free_mem(res
->init_strings
.init2
);
1573 if(res
->any
.type
== res_pppd_option
) {
1574 free_mem(res
->pppd_option
.option
);
1577 if(res
->any
.type
== res_hwaddr
) {
1578 free_mem(res
->hwaddr
.addr
);
1589 * Note: new_res is directly inserted into the list, so you *must* make sure
1590 * that new_res points to a malloc'ed pice of memory.
1592 hd_res_t
*add_res_entry(hd_res_t
**res
, hd_res_t
*new_res
)
1594 while(*res
) res
= &(*res
)->next
;
1596 return *res
= new_res
;
1600 hd_t
*add_hd_entry(hd_data_t
*hd_data
, unsigned line
, unsigned count
)
1604 hd
= add_hd_entry2(&hd_data
->hd
, new_mem(sizeof *hd
));
1606 hd
->idx
= ++(hd_data
->last_idx
);
1607 hd
->module
= hd_data
->module
;
1615 hd_t
*add_hd_entry2(hd_t
**hd
, hd_t
*new_hd
)
1617 while(*hd
) hd
= &(*hd
)->next
;
1619 return *hd
= new_hd
;
1623 void hd_scan(hd_data_t
*hd_data
)
1629 str_list_t
*sl
, *sl0
;
1631 #ifdef LIBHD_MEMCHECK
1633 char *s
= getenv("LIBHD_MEMCHECK");
1636 libhd_log
= fopen(s
, "w");
1637 if(libhd_log
) setlinebuf(libhd_log
);
1642 #ifdef LIBHD_MEMCHECK
1645 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_scan
, hd_data
), hd_data
);
1649 /* log the debug & probe flags */
1650 if(hd_data
->debug
&& !hd_data
->flags
.internal
) {
1651 ADD2LOG("libhd version %s%s (%s)\n", HD_VERSION_STRING
, getuid() ? "u" : "", HD_ARCH
);
1654 get_kernel_version(hd_data
);
1656 /* needed only on 1st call */
1657 if(hd_data
->last_idx
== 0) {
1658 get_probe_env(hd_data
);
1661 fix_probe_features(hd_data
);
1663 if(hd_data
->debug
&& !hd_data
->flags
.internal
) {
1664 for(i
= sizeof hd_data
->probe
- 1; i
>= 0; i
--) {
1665 str_printf(&s
, -1, "%02x", hd_data
->probe
[i
]);
1667 ADD2LOG("debug = 0x%x\nprobe = 0x%s (", hd_data
->debug
, s
);
1670 for(i
= 1; i
< pr_default
; i
++) { /* 1 because of pr_memory */
1671 if((s
= hd_probe_feature_by_value(i
))) {
1672 ADD2LOG("%s%c%s", i
== 1 ? "" : " ", hd_probe_feature(hd_data
, i
) ? '+' : '-', s
);
1679 /* init driver info database */
1682 /* only first time */
1683 if(hd_data
->last_idx
== 0) {
1684 hd_set_probe_feature(hd_data
, pr_fork
);
1685 if(!hd_probe_feature(hd_data
, pr_fork
)) hd_data
->flags
.nofork
= 1;
1686 // hd_set_probe_feature(hd_data, pr_sysfs);
1687 if(!hd_probe_feature(hd_data
, pr_sysfs
)) hd_data
->flags
.nosysfs
= 1;
1688 if(hd_probe_feature(hd_data
, pr_cpuemu
)) hd_data
->flags
.cpuemu
= 1;
1689 if(hd_probe_feature(hd_data
, pr_udev
)) hd_data
->flags
.udev
= 1;
1692 /* get shm segment, if we didn't do it already */
1693 hd_shm_init(hd_data
);
1695 if(!hd_data
->shm
.ok
&& !hd_data
->flags
.nofork
) {
1696 hd_data
->flags
.nofork
= 1;
1697 ADD2LOG("shm: failed to get shm segment; will not fork\n");
1701 s
= hd_join(", ", hd_data
->only
);
1702 ADD2LOG("only: %s\n", s
);
1708 * There might be old 'manual' entries left from an earlier scan. Remove
1709 * them, they will confuse us.
1711 if(hd_probe_feature(hd_data
, pr_manual
)) {
1712 hd_data
->module
= mod_manual
;
1713 remove_hd_entries(hd_data
);
1718 * for various reasons, do it befor scan_misc()
1720 hd_scan_floppy(hd_data
);
1723 * to be able to read the right parport io,
1724 * we have to do this before scan_misc()
1726 #if defined(__i386__) || defined (__x86_64__) || defined (__ia64__)
1727 hd_scan_bios(hd_data
);
1730 /* before hd_scan_misc(): we need some ppc info later */
1731 hd_scan_sys(hd_data
);
1733 /* get basic system info */
1734 hd_scan_misc(hd_data
);
1736 /* hd_scan_cpu() after hd_scan_misc(): klog needed */
1737 hd_scan_cpu(hd_data
);
1738 hd_scan_memory(hd_data
);
1740 hd_scan_sysfs_pci(hd_data
);
1742 /* do it _after_ hd_scan_sysfs_pci() */
1743 #if defined(__PPC__)
1744 hd_scan_prom(hd_data
);
1747 #if defined(__s390__) || defined(__s390x__)
1748 hd_scan_s390disks(hd_data
);
1749 hd_scan_s390(hd_data
);
1752 /* after hd_scan_prom() and hd_scan_bios() */
1753 hd_scan_monitor(hd_data
);
1756 #if defined(__i386__) || defined(__alpha__)
1757 hd_scan_isapnp(hd_data
);
1762 #if defined(__i386__)
1763 hd_scan_isa(hd_data
);
1767 /* after pci & isa */
1768 hd_scan_pcmcia(hd_data
);
1770 hd_scan_serial(hd_data
);
1772 /* merge basic system info & the easy stuff */
1773 hd_scan_misc2(hd_data
);
1776 if(!hd_data
->flags
.no_parport
) {
1777 hd_scan_parallel(hd_data
); /* after hd_scan_misc*() */
1781 hd_scan_sysfs_block(hd_data
);
1782 hd_scan_sysfs_scsi(hd_data
);
1783 hd_scan_sysfs_usb(hd_data
);
1784 hd_scan_sysfs_edd(hd_data
);
1786 #if defined(__PPC__)
1787 hd_scan_adb(hd_data
);
1791 #if !defined(__sparc__)
1792 hd_scan_braille(hd_data
);
1794 hd_scan_modem(hd_data
); /* do it before hd_scan_mouse() */
1795 hd_scan_mouse(hd_data
);
1797 hd_scan_sbus(hd_data
);
1799 hd_scan_input(hd_data
);
1801 #if !defined(__s390__) && !defined(__s390x__)
1802 hd_scan_kbd(hd_data
);
1805 /* must be after hd_scan_monitor() */
1806 hd_scan_fb(hd_data
);
1808 /* keep these at the end of the list */
1809 hd_scan_net(hd_data
);
1811 hd_scan_pppoe(hd_data
);
1814 hd_scan_wlan(hd_data
);
1817 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) hd_add_id(hd_data
, hd
);
1820 hd_scan_manual(hd_data
);
1823 /* add test entries */
1824 hd_scan_xtra(hd_data
);
1826 /* some final fixup's */
1828 hd_scan_isdn(hd_data
);
1829 hd_scan_dsl(hd_data
);
1831 hd_scan_int(hd_data
);
1834 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) hd_add_id(hd_data
, hd
);
1836 /* assign parent & child ids */
1837 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1838 hd
->child_ids
= free_str_list(hd
->child_ids
);
1839 if((hd2
= hd_get_device_by_idx(hd_data
, hd
->attached_to
))) {
1840 free_mem(hd
->parent_id
);
1841 hd
->parent_id
= new_str(hd2
->unique_id
);
1843 else if((hd2
= hd_get_device_by_id(hd_data
, hd
->parent_id
))) {
1844 hd
->attached_to
= hd2
->idx
;
1847 hd
->attached_to
= 0;
1851 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1852 if((hd2
= hd_get_device_by_idx(hd_data
, hd
->attached_to
))) {
1853 add_str_list(&hd2
->child_ids
, hd
->unique_id
);
1857 /* assign a hw_class & build a useful model string */
1858 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1859 assign_hw_class(hd_data
, hd
);
1861 /* create model name _after_ hw_class */
1862 create_model_name(hd_data
, hd
);
1866 /* must be _after_ we have valid hw_class entries */
1867 hd_scan_manual2(hd_data
);
1870 /* we are done... */
1871 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) hd
->tag
.fixed
= 1;
1873 /* for compatibility */
1874 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
1875 hd
->driver
= free_mem(hd
->driver
);
1876 if(hd
->drivers
&& hd
->drivers
->str
) hd
->driver
= new_str(hd
->drivers
->str
);
1879 hd_data
->module
= mod_none
;
1883 !hd_data
->flags
.internal
&&
1886 hd_probe_feature(hd_data
, pr_int
/* arbitrary; just avoid /proc/modules for -pr_all */)
1889 sl0
= read_file(PROC_MODULES
, 0, 0);
1890 ADD2LOG("----- /proc/modules -----\n");
1891 for(sl
= sl0
; sl
; sl
= sl
->next
) {
1892 ADD2LOG(" %s", sl
->str
);
1894 ADD2LOG("----- /proc/modules end -----\n");
1898 update_irq_usage(hd_data
);
1900 if(hd_data
->debug
&& !hd_data
->flags
.internal
) {
1901 irqs
= hd_data
->used_irqs
;
1903 ADD2LOG(" used irqs:");
1904 for(i
= j
= 0; i
< 64; i
++, irqs
>>= 1) {
1906 ADD2LOG("%c%d", j
? ',' : ' ', i
);
1916 * Note: due to byte order problems decoding the id is really a mess...
1917 * And, we use upper case for hex numbers!
1919 char *isa_id2str(unsigned id
)
1921 char *s
= new_mem(8);
1922 unsigned u
= ((id
& 0xff) << 8) + ((id
>> 8) & 0xff);
1923 unsigned v
= ((id
>> 8) & 0xff00) + ((id
>> 24) & 0xff);
1925 s
[0] = ((u
>> 10) & 0x1f) + 'A' - 1;
1926 s
[1] = ((u
>> 5) & 0x1f) + 'A' - 1;
1927 s
[2] = ( u
& 0x1f) + 'A' - 1;
1929 sprintf(s
+ 3, "%04X", v
);
1934 char *eisa_vendor_str(unsigned v
)
1938 s
[0] = ((v
>> 10) & 0x1f) + 'A' - 1;
1939 s
[1] = ((v
>> 5) & 0x1f) + 'A' - 1;
1940 s
[2] = ( v
& 0x1f) + 'A' - 1;
1948 * Must _not_ check that s is exactly 3 chars.
1950 unsigned name2eisa_id(char *s
)
1955 for(i
= 0; i
< 3; i
++) {
1957 if(s
[i
] < 'A' - 1 || s
[i
] > 'A' - 1 + 0x1f) return 0;
1958 u
+= s
[i
] - 'A' + 1;
1961 return MAKE_ID(TAG_EISA
, u
);
1966 * Create a 'canonical' version, i.e. no spaces at start and end.
1968 * Note: removes chars >= 0x80 as well (due to (char *))! This
1969 * is currently considered a feature.
1971 char *canon_str(char *s
, int len
)
1976 #ifdef LIBHD_MEMCHECK
1978 if(libhd_log
) fprintf(libhd_log
, ">%p\n", CALLED_FROM(canon_str
, s
));
1982 if(len
< 0) len
= 0; /* just to be safe */
1984 m0
= new_mem(len
+ 1);
1986 for(m1
= m0
, i
= 0; i
< len
; i
++) {
1987 if(m1
== m0
&& s
[i
] <= ' ') continue;
1991 while(m1
> m0
&& m1
[-1] <= ' ') {
1998 #ifdef LIBHD_MEMCHECK
2000 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(canon_str
, s
));
2009 * Convert a n-digit hex number to its numerical value.
2011 int hex(char *s
, int n
)
2016 if(sscanf(s
++, "%1x", &j
) != 1) return -1;
2024 /* simple 32 bit fixed point numbers with n decimals */
2025 int str2float(char *s
, int n
)
2034 else if(*s
>= '0' && *s
<= '9') {
2055 /* simple 32 bit fixed point numbers with n decimals */
2056 char *float2str(int f
, int n
)
2058 int i
= 1, j
, m
= n
;
2059 static char buf
[32];
2066 while(i
&& !(i
% 10)) i
/= 10, m
--;
2069 sprintf(buf
, "%d.%0*d", j
, m
, i
);
2072 sprintf(buf
, "%d", j
);
2080 * find hardware entry with given index
2082 hd_t
*hd_get_device_by_idx(hd_data_t
*hd_data
, unsigned idx
)
2086 #ifdef LIBHD_MEMCHECK
2089 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_get_device_by_idx
, hd_data
), hd_data
);
2093 if(!idx
) return NULL
; /* early out: idx is always != 0 */
2095 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2096 if(hd
->idx
== idx
) return hd
;
2104 * find hardware entry with given unique id
2106 hd_t
*hd_get_device_by_id(hd_data_t
*hd_data
, char *id
)
2110 if(!id
) return NULL
;
2112 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2113 if(hd
->unique_id
&& !strcmp(hd
->unique_id
, id
)) return hd
;
2121 * Give the actual name of the probing module.
2123 char *mod_name_by_idx(unsigned idx
)
2127 for(u
= 0; u
< sizeof pr_modules
/ sizeof *pr_modules
; u
++)
2128 if(idx
== pr_modules
[u
].val
) return pr_modules
[u
].name
;
2135 * Print to a string.
2136 * Note: *buf must point to a malloc'd memory area (or be NULL).
2138 * Use an offset of -1 or -2 to append the new string.
2140 * As this function is quite often used to extend our log messages, there
2141 * is a cache that holds the length of the last string we created. This way
2142 * we speed this up somewhat. Use an offset of -2 to use this feature.
2143 * Note: this only works as long as str_printf() is used *exclusively* to
2144 * extend the string.
2146 void str_printf(char **buf
, int offset
, char *format
, ...)
2148 static char *last_buf
= NULL
;
2149 static int last_len
= 0;
2154 #ifdef LIBHD_MEMCHECK
2156 if(libhd_log
) fprintf(libhd_log
, ">%p\n", CALLED_FROM(str_printf
, buf
));
2160 use_cache
= offset
== -2 ? 1 : 0;
2164 offset
= strlen(*buf
);
2166 else if(offset
== -2) {
2167 if(last_buf
== *buf
&& last_len
&& !(*buf
)[last_len
])
2170 offset
= strlen(*buf
);
2177 va_start(args
, format
);
2178 vsnprintf(b
, sizeof b
, format
, args
);
2181 *buf
= resize_mem(*buf
, (len
= offset
+ strlen(b
)) + 1);
2182 strcpy(*buf
+ offset
, b
);
2189 #ifdef LIBHD_MEMCHECK
2191 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(str_printf
, buf
));
2197 void hexdump(char **buf
, int with_ascii
, unsigned data_len
, unsigned char *data
)
2201 for(i
= 0; i
< data_len
; i
++) {
2203 str_printf(buf
, -2, " %02x", data
[i
]);
2205 str_printf(buf
, -2, "%02x", data
[i
]);
2209 str_printf(buf
, -2, " \"");
2210 for(i
= 0; i
< data_len
; i
++) {
2211 str_printf(buf
, -2, "%c", data
[i
] < ' ' || data
[i
] >= 0x7f ? '.' : data
[i
]);
2213 str_printf(buf
, -2, "\"");
2218 /** \relates s_str_list_t
2219 * Search a string list for a string.
2221 str_list_t
*search_str_list(str_list_t
*sl
, char *str
)
2223 if(!str
) return NULL
;
2225 for(; sl
; sl
= sl
->next
) if(sl
->str
&& !strcmp(sl
->str
, str
)) return sl
;
2231 /** \relates s_str_list_t
2232 * Add a string to a string list.
2234 * The new string (str) will be *copied*!
2236 str_list_t
*add_str_list(str_list_t
**sl
, char *str
)
2238 #ifdef LIBHD_MEMCHECK
2240 if(libhd_log
) fprintf(libhd_log
, ">%p\n", CALLED_FROM(add_str_list
, sl
));
2244 while(*sl
) sl
= &(*sl
)->next
;
2246 *sl
= new_mem(sizeof **sl
);
2247 (*sl
)->str
= new_str(str
);
2249 #ifdef LIBHD_MEMCHECK
2251 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(add_str_list
, sl
));
2259 /** \relates s_str_list_t
2260 * Free the memory allocated by a string list.
2262 str_list_t
*free_str_list(str_list_t
*list
)
2266 for(; list
; list
= (l
= list
)->next
, free_mem(l
)) {
2267 free_mem(list
->str
);
2275 * Read a file; return a linked list of lines.
2277 * start_line is zero-based; lines == 0 -> all lines
2279 str_list_t
*read_file(char *file_name
, unsigned start_line
, unsigned lines
)
2284 str_list_t
*sl_start
= NULL
, *sl_end
= NULL
, *sl
;
2286 #ifdef LIBHD_MEMCHECK
2288 if(libhd_log
) fprintf(libhd_log
, ">%p\n", CALLED_FROM(read_file
, file_name
));
2292 if(*file_name
== '|') {
2295 if(!(f
= popen(file_name
, "r"))) {
2296 #ifdef LIBHD_MEMCHECK
2298 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(read_file
, file_name
));
2305 if(!(f
= fopen(file_name
, "r"))) {
2306 #ifdef LIBHD_MEMCHECK
2308 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(read_file
, file_name
));
2315 while(fgets(buf
, sizeof buf
, f
)) {
2320 sl
= new_mem(sizeof *sl
);
2321 sl
->str
= new_str(buf
);
2328 if(lines
== 1) break;
2337 #ifdef LIBHD_MEMCHECK
2339 if(libhd_log
) fprintf(libhd_log
, "<%p\n", CALLED_FROM(read_file
, file_name
));
2348 * Read directory, return a list of entries with file type 'type'.
2350 str_list_t
*read_dir(char *dir_name
, int type
)
2352 str_list_t
*sl_start
= NULL
, *sl_end
= NULL
, *sl
;
2359 if(dir_name
&& (dir
= opendir(dir_name
))) {
2360 while((de
= readdir(dir
))) {
2361 if(!strcmp(de
->d_name
, ".") || !strcmp(de
->d_name
, "..")) continue;
2366 str_printf(&s
, 0, "%s/%s", dir_name
, de
->d_name
);
2368 if(!lstat(s
, &sbuf
)) {
2369 if(S_ISDIR(sbuf
.st_mode
)) {
2372 else if(S_ISREG(sbuf
.st_mode
)) {
2375 else if(S_ISLNK(sbuf
.st_mode
)) {
2383 if(dir_type
== type
) {
2384 sl
= new_mem(sizeof *sl
);
2385 sl
->str
= new_str(de
->d_name
);
2400 char *hd_read_symlink(char *link_name
)
2402 static char buf
[256];
2405 i
= readlink(link_name
, buf
, sizeof buf
);
2406 buf
[sizeof buf
- 1] = 0;
2407 if(i
>= 0 && (unsigned) i
< sizeof buf
) buf
[i
] = 0;
2415 * Log the hardware detection progress.
2417 void progress(hd_data_t
*hd_data
, unsigned pos
, unsigned count
, char *msg
)
2419 char buf1
[32], buf2
[32], buf3
[128], *fn
;
2421 if(hd_data
->shm
.ok
&& hd_data
->flags
.forked
) {
2422 ((hd_data_t
*) (hd_data
->shm
.data
))->shm
.updated
++;
2427 sprintf(buf1
, "%u", hd_data
->module
);
2428 sprintf(buf2
, ".%u", count
);
2429 fn
= mod_name_by_idx(hd_data
->module
);
2431 sprintf(buf3
, "%s.%u%s", *fn
? fn
: buf1
, pos
, count
? buf2
: "");
2433 if((hd_data
->debug
& HD_DEB_PROGRESS
))
2434 ADD2LOG(">> %s: %s\n", buf3
, msg
);
2436 if(hd_data
->progress
) hd_data
->progress(buf3
, msg
);
2442 * Returns a probe feature suitable for hd_*probe_feature().
2443 * If name is not a valid probe feature, 0 is returned.
2446 enum probe_feature
hd_probe_feature_by_name(char *name
)
2450 #ifdef LIBHD_MEMCHECK
2453 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_probe_feature_by_name
, name
), name
);
2457 for(u
= 0; u
< sizeof pr_flags
/ sizeof *pr_flags
; u
++)
2458 if(!strcmp(name
, pr_flags
[u
].name
)) return pr_flags
[u
].val
;
2465 * Coverts a enum probe_feature to a string.
2466 * If it fails, NULL is returned.
2468 char *hd_probe_feature_by_value(enum probe_feature feature
)
2472 #ifdef LIBHD_MEMCHECK
2475 fprintf(libhd_log
, "; %s\t%p\t%u\n", __FUNCTION__
, CALLED_FROM(hd_probe_feature_by_value
, feature
), feature
);
2479 for(u
= 0; u
< sizeof pr_flags
/ sizeof *pr_flags
; u
++)
2480 if(feature
== pr_flags
[u
].val
) return pr_flags
[u
].name
;
2487 * Removes all hd_data->hd entries created by the current module from the
2488 * list. The old entries are added to hd_data->old_hd.
2490 void remove_hd_entries(hd_data_t
*hd_data
)
2494 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2495 if(hd
->module
== hd_data
->module
) {
2500 remove_tagged_hd_entries(hd_data
);
2505 * Removes all hd_data->hd entries that have the remove tag set from the
2506 * list. The old entries are added to hd_data->old_hd.
2508 void remove_tagged_hd_entries(hd_data_t
*hd_data
)
2510 hd_t
*hd
, **prev
, **h
;
2512 for(hd
= *(prev
= &hd_data
->hd
); hd
;) {
2513 if(hd
->tag
.remove
) {
2514 /* find end of the old list... */
2515 h
= &hd_data
->old_hd
;
2516 while(*h
) h
= &(*h
)->next
;
2517 *h
= hd
; /* ...and append the entry */
2519 hd
= *prev
= hd
->next
;
2523 hd
= *(prev
= &hd
->next
);
2529 int hd_module_is_active(hd_data_t
*hd_data
, char *mod
)
2531 str_list_t
*sl
, *sl0
= read_kmods(hd_data
);
2538 #ifdef LIBHD_MEMCHECK
2541 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_module_is_active
, hd_data
), hd_data
);
2547 /* convert '-' to '_' */
2548 for(s
= mod
; *s
; s
++) if(*s
== '-') *s
= '_';
2550 for(sl
= sl0
; sl
; sl
= sl
->next
) {
2551 if(!strcmp(sl
->str
, mod
)) break;
2555 active
= sl
? 1 : 0;
2564 /* temporary hack for ppc */
2565 if(!strcmp(mod
, "gmac")) {
2569 else if(!strcmp(mod
, "mace")) {
2573 else if(!strcmp(mod
, "bmac")) {
2577 else if(!strcmp(mod
, "mac53c94")) {
2581 else if(!strcmp(mod
, "mesh")) {
2585 else if(!strcmp(mod
, "swim3")) {
2594 for(sl
= hd_data
->klog
; sl
; sl
= sl
->next
) {
2595 if(strstr(sl
->str
, s1
) == sl
->str
&& strstr(sl
->str
, s2
)) {
2609 int hd_has_pcmcia(hd_data_t
*hd_data
)
2613 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2614 if(is_pcmcia_ctrl(hd_data
, hd
)) return 1;
2621 int hd_apm_enabled(hd_data_t
*hd_data
)
2625 #ifdef LIBHD_MEMCHECK
2628 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_apm_enabled
, hd_data
), hd_data
);
2632 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2634 hd
->base_class
.id
== bc_internal
&&
2635 hd
->sub_class
.id
== sc_int_bios
&&
2637 hd
->detail
->type
== hd_detail_bios
&&
2638 hd
->detail
->bios
.data
2640 return hd
->detail
->bios
.data
->apm_enabled
;
2648 int hd_usb_support(hd_data_t
*hd_data
)
2653 #ifdef LIBHD_MEMCHECK
2656 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_usb_support
, hd_data
), hd_data
);
2660 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2661 if(hd
->base_class
.id
== bc_serial
&& hd
->sub_class
.id
== sc_ser_usb
) {
2662 for(res
= hd
->res
; res
; res
= res
->next
) {
2663 if(res
->any
.type
== res_irq
)
2664 return hd
->prog_if
.id
== pif_usb_ohci
? 2 : 1; /* 2: ohci, 1: uhci */
2673 int hd_smp_support(hd_data_t
*hd_data
)
2678 #if defined(__i386__) || defined (__x86_64__)
2679 unsigned cpu_threads
= 0;
2683 #ifdef LIBHD_MEMCHECK
2686 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_smp_support
, hd_data
), hd_data
);
2690 u
= hd_data
->flags
.internal
;
2691 hd_data
->flags
.internal
= 1;
2692 hd
= hd_list(hd_data
, hw_cpu
, 0, NULL
);
2693 if(!hd
) hd
= hd_list(hd_data
, hw_cpu
, 1, NULL
);
2694 hd_data
->flags
.internal
= u
;
2696 for(is_smp
= 0, hd0
= hd
; hd0
; hd0
= hd0
->next
) is_smp
++;
2697 if(is_smp
== 1) is_smp
= 0;
2699 #if defined(__i386__) || defined (__x86_64__)
2703 hd
->detail
->type
== hd_detail_cpu
&&
2704 (ct
= hd
->detail
->cpu
.data
)
2706 cpu_threads
= ct
->units
;
2710 hd
= hd_free_hd_list(hd
);
2712 #if !defined(LIBHD_TINY) && (defined(__i386__) || defined (__x86_64__))
2714 if(!hd_data
->bios_ram
.data
) {
2715 hd_free_hd_list(hd_list(hd_data
, hw_sys
, 1, NULL
));
2717 is_smp
= detect_smp_bios(hd_data
);
2718 // at least 2 processors
2719 if(is_smp
< 2) is_smp
= 0;
2720 if(!is_smp
&& cpu_threads
> 1) is_smp
= 2;
2726 if(!hd_data
->devtree
) {
2727 hd_free_hd_list(hd_list(hd_data
, hw_sys
, 1, NULL
));
2729 is_smp
= detect_smp_prom(hd_data
);
2730 if(is_smp
< 0) is_smp
= 0;
2734 #if defined(__s390__) || defined(__s390x__)
2735 if(!is_smp
) is_smp
= 1;
2742 int hd_color(hd_data_t
*hd_data
)
2748 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2750 hd
->base_class
.id
== bc_internal
&& hd
->sub_class
.id
== sc_int_prom
&&
2751 hd
->detail
&& hd
->detail
->type
== hd_detail_prom
&&
2752 (pt
= hd
->detail
->prom
.data
) &&
2760 #ifdef LIBHD_MEMCHECK
2763 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_color
, hd_data
), hd_data
);
2767 if(hd_data
->color_code
) return hd_data
->color_code
& 0xffff;
2773 int hd_mac_color(hd_data_t
*hd_data
)
2775 #ifdef LIBHD_MEMCHECK
2778 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_mac_color
, hd_data
), hd_data
);
2782 return hd_color(hd_data
);
2786 unsigned hd_display_adapter(hd_data_t
*hd_data
)
2790 unsigned disp
, disp_sbus
, disp_pci
, disp_any
, disp_di
;
2791 unsigned disp_cnt
, disp_any_cnt
;
2793 #ifdef LIBHD_MEMCHECK
2796 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_display_adapter
, hd_data
), hd_data
);
2800 /* if we know exactly where our primary display is, return it */
2801 if(hd_get_device_by_idx(hd_data
, hd_data
->display
)) return hd_data
->display
;
2803 disp
= disp_sbus
= disp_pci
= disp_any
= disp_di
= 0;
2804 disp_cnt
= disp_any_cnt
= 0;
2806 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2807 if(hd
->base_class
.id
== bc_display
) {
2809 if(!disp_any
) disp_any
= hd
->idx
;
2810 if(hd
->sub_class
.id
== sc_dis_vga
) {
2812 if(!disp
) disp
= hd
->idx
;
2813 if(hd
->bus
.id
== bus_pci
&& !disp_pci
) disp_pci
= hd
->idx
;
2814 if(hd
->bus
.id
== bus_sbus
&& !disp_sbus
) disp_sbus
= hd
->idx
;
2817 if(!(di
= hd
->driver_info
)) {
2818 hddb_add_info(hd_data
, hd
);
2819 di
= hd
->driver_info
;
2821 if(di
&& di
->any
.type
== di_x11
&& di
->x11
.server
) {
2828 /* if there's only one display adapter, return it */
2829 if(disp_any_cnt
== 1) return disp_any
;
2831 /* if there's only one vga compatible adapter, return it */
2832 if(disp_cnt
== 1) return disp
;
2834 /* return 1st (vga compatible) sbus card */
2835 /* note: the sbus code enters display cards as 'vga compatible' */
2836 if(disp_sbus
) return disp_sbus
;
2838 /* return 1st display adapter that has some x11 info */
2839 if(disp_di
) return disp_di
;
2841 /* return 1st vga compatible pci card */
2842 if(disp_pci
) return disp_pci
;
2844 /* return 1st vga compatible card */
2845 if(disp
) return disp
;
2847 /* return 1st display adapter */
2848 if(disp_any
) return disp_any
;
2850 /* there were none... */
2855 enum cpu_arch
hd_cpu_arch(hd_data_t
*hd_data
)
2859 #ifdef LIBHD_MEMCHECK
2862 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_cpu_arch
, hd_data
), hd_data
);
2866 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2868 hd
->base_class
.id
== bc_internal
&&
2869 hd
->sub_class
.id
== sc_int_cpu
&&
2871 hd
->detail
->type
== hd_detail_cpu
&&
2872 hd
->detail
->cpu
.data
2874 return hd
->detail
->cpu
.data
->architecture
;
2902 return arch_unknown
;
2914 enum boot_arch
hd_boot_arch(hd_data_t
*hd_data
)
2916 #ifdef LIBHD_MEMCHECK
2919 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_boot_arch
, hd_data
), hd_data
);
2923 return hd_data
->boot
;
2927 int hd_is_uml(hd_data_t
*hd_data
)
2933 unsigned saved_mod
= hd_data
->module
;
2934 unsigned char probe_save
[sizeof hd_data
->probe
];
2936 u
= hd_data
->flags
.internal
;
2937 hd_data
->flags
.internal
= 1;
2938 hd
= hd_list(hd_data
, hw_cpu
, 0, NULL
);
2940 /* Do *not* run hd_list(,, 1,) here! */
2941 memcpy(probe_save
, hd_data
->probe
, sizeof probe_save
);
2942 hd_set_probe_feature(hd_data
, pr_cpu
);
2943 hd_scan_cpu(hd_data
);
2944 memcpy(hd_data
->probe
, probe_save
, sizeof hd_data
->probe
);
2945 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
2946 if(hd
->base_class
.id
== bc_internal
&& hd
->sub_class
.id
== sc_int_cpu
) break;
2949 hd_data
->flags
.internal
= u
;
2954 hd
->detail
->type
== hd_detail_cpu
&&
2955 (ct
= hd
->detail
->cpu
.data
) &&
2957 !strcmp(ct
->model_name
, "UML")
2962 hd
= hd_free_hd_list(hd
);
2964 hd_data
->module
= saved_mod
;
2970 int hd_is_sgi_altix(hd_data_t
*hd_data
)
2974 return stat("/proc/sgi_sn", &sbuf
) ? 0 : 1;
2978 int hd_is_iseries(hd_data_t
*hd_data
)
2982 return stat(PROC_ISERIES
, &sbuf
) ? 0 : 1;
2987 * makes a (shallow) copy; does some magic fixes
2989 void hd_copy(hd_t
*dst
, hd_t
*src
)
3004 /* needed to keep in sync with the real device tree */
3007 dst
->detail
->type
== hd_detail_devtree
3009 dst
->detail
= NULL
; /* ??? was: free_mem(dst->detail); */
3014 hd_t
*hd_list(hd_data_t
*hd_data
, hd_hw_item_t item
, int rescan
, hd_t
*hd_old
)
3016 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3017 unsigned char probe_save
[sizeof hd_data
->probe
];
3020 #ifdef LIBHD_MEMCHECK
3024 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
);
3030 memcpy(probe_save
, hd_data
->probe
, sizeof probe_save
);
3031 fast_save
= hd_data
->flags
.fast
;
3032 hd_clear_probe_feature(hd_data
, pr_all
);
3034 hd_set_probe_feature(hd_data
, pr_sys
);
3037 hd_set_probe_feature_hw(hd_data
, item
);
3039 memcpy(hd_data
->probe
, probe_save
, sizeof hd_data
->probe
);
3040 hd_data
->flags
.fast
= fast_save
;
3043 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3044 if(!hd_report_this(hd_data
, hd
)) continue;
3048 item
== hw_manual
|| hd_is_hw_class(hd
, item
)
3051 /* with LIBHD_TINY hd->status is not maintained (cf. manual.c) */
3053 hd
->status
.available
== status_yes
||
3054 hd
->status
.available
== status_unknown
||
3055 item
== hw_manual
||
3056 hd_data
->flags
.list_all
3060 // if(hd->is.softraiddisk) continue; /* don't report them */
3062 /* don't report old entries again */
3063 for(hd1
= hd_old
; hd1
; hd1
= hd1
->next
) {
3064 if(!cmp_hd(hd1
, hd
)) break;
3067 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3073 if(item
== hw_manual
) {
3074 for(hd
= hd_list
; hd
; hd
= hd
->next
) {
3075 hd
->status
.available
= hd
->status
.available_orig
;
3083 hd_t
*hd_list_with_status(hd_data_t
*hd_data
, hd_hw_item_t item
, hd_status_t status
)
3085 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3086 unsigned char probe_save
[sizeof hd_data
->probe
];
3088 #ifdef LIBHD_MEMCHECK
3092 fprintf(libhd_log
, "; %s\t%p\t%p\t%u\n", __FUNCTION__
, CALLED_FROM(hd_list_with_status
, hd_data
), hd_data
, item
);
3097 memcpy(probe_save
, hd_data
->probe
, sizeof probe_save
);
3098 hd_clear_probe_feature(hd_data
, pr_all
);
3099 hd_set_probe_feature(hd_data
, pr_manual
);
3101 memcpy(hd_data
->probe
, probe_save
, sizeof hd_data
->probe
);
3103 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3104 if(hd_is_hw_class(hd
, item
)) {
3106 (status
.configured
== 0 || status
.configured
== hd
->status
.configured
) &&
3107 (status
.available
== 0 || status
.available
== hd
->status
.available
) &&
3108 (status
.needed
== 0 || status
.needed
== hd
->status
.needed
) &&
3109 (status
.reconfig
== 0 || status
.reconfig
== hd
->status
.reconfig
)
3111 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3121 /* check if item is in items */
3122 int has_item(hd_hw_item_t
*items
, hd_hw_item_t item
)
3124 while(*items
) if(*items
++ == item
) return 1;
3130 /* check if one of items is in hw_class */
3131 int has_hw_class(hd_t
*hd
, hd_hw_item_t
*items
)
3133 while(*items
) if(hd_is_hw_class(hd
, *items
++)) return 1;
3140 * items must be a 0 terminated list
3142 hd_t
*hd_list2(hd_data_t
*hd_data
, hd_hw_item_t
*items
, int rescan
)
3144 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3145 unsigned char probe_save
[sizeof hd_data
->probe
];
3147 hd_hw_item_t
*item_ptr
;
3150 if(!items
) return NULL
;
3152 is_manual
= has_item(items
, hw_manual
);
3155 memcpy(probe_save
, hd_data
->probe
, sizeof probe_save
);
3156 fast_save
= hd_data
->flags
.fast
;
3157 hd_clear_probe_feature(hd_data
, pr_all
);
3159 hd_set_probe_feature(hd_data
, pr_sys
);
3162 for(item_ptr
= items
; *item_ptr
; item_ptr
++) {
3163 hd_set_probe_feature_hw(hd_data
, *item_ptr
);
3166 memcpy(hd_data
->probe
, probe_save
, sizeof hd_data
->probe
);
3167 hd_data
->flags
.fast
= fast_save
;
3170 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3171 if(!hd_report_this(hd_data
, hd
)) continue;
3174 is_manual
|| has_hw_class(hd
, items
)
3177 /* with LIBHD_TINY hd->status is not maintained (cf. manual.c) */
3179 hd
->status
.available
== status_yes
||
3180 hd
->status
.available
== status_unknown
||
3182 hd_data
->flags
.list_all
3186 // if(hd->is.softraiddisk) continue; /* don't report them */
3188 /* don't report old entries again */
3189 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3195 for(hd
= hd_list
; hd
; hd
= hd
->next
) {
3196 hd
->status
.available
= hd
->status
.available_orig
;
3205 * items must be a 0 terminated list
3207 hd_t
*hd_list_with_status2(hd_data_t
*hd_data
, hd_hw_item_t
*items
, hd_status_t status
)
3209 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3210 unsigned char probe_save
[sizeof hd_data
->probe
];
3212 if(!items
) return NULL
;
3214 memcpy(probe_save
, hd_data
->probe
, sizeof probe_save
);
3215 hd_clear_probe_feature(hd_data
, pr_all
);
3216 hd_set_probe_feature(hd_data
, pr_manual
);
3218 memcpy(hd_data
->probe
, probe_save
, sizeof hd_data
->probe
);
3220 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3221 if(has_hw_class(hd
, items
)) {
3223 (status
.configured
== 0 || status
.configured
== hd
->status
.configured
) &&
3224 (status
.available
== 0 || status
.available
== hd
->status
.available
) &&
3225 (status
.needed
== 0 || status
.needed
== hd
->status
.needed
) &&
3226 (status
.reconfig
== 0 || status
.reconfig
== hd
->status
.reconfig
)
3228 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3238 hd_t
*hd_base_class_list(hd_data_t
*hd_data
, unsigned base_class
)
3240 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3243 #ifdef LIBHD_MEMCHECK
3246 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_base_class_list
, hd_data
), hd_data
);
3250 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3253 /* ###### fix later: card bus magic */
3254 if((bridge_hd
= hd_get_device_by_idx(hd_data
, hd
->attached_to
))) {
3256 bridge_hd
->base_class
.id
== bc_bridge
&&
3257 bridge_hd
->sub_class
.id
== sc_bridge_cardbus
3262 /* add multimedia/sc_multi_video to display */
3264 hd
->base_class
.id
== base_class
||
3266 base_class
== bc_display
&&
3267 hd
->base_class
.id
== bc_multimedia
&&
3268 hd
->sub_class
.id
== sc_multi_video
3271 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3279 hd_t
*hd_sub_class_list(hd_data_t
*hd_data
, unsigned base_class
, unsigned sub_class
)
3281 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3283 #ifdef LIBHD_MEMCHECK
3286 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_sub_class_list
, hd_data
), hd_data
);
3290 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3291 if(hd
->base_class
.id
== base_class
&& hd
->sub_class
.id
== sub_class
) {
3292 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3300 hd_t
*hd_bus_list(hd_data_t
*hd_data
, unsigned bus
)
3302 hd_t
*hd
, *hd1
, *hd_list
= NULL
;
3304 #ifdef LIBHD_MEMCHECK
3307 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_bus_list
, hd_data
), hd_data
);
3311 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3312 if(hd
->bus
.id
== bus
) {
3313 hd1
= add_hd_entry2(&hd_list
, new_mem(sizeof *hd_list
));
3321 /* Convert libhd bus IDs to hwcfg bus names */
3322 const char* hd_busid_to_hwcfg(int busid
)
3324 const char* const ids1
[]={"none","isa","eisa","mc","pci","pcmcia","nubus","cardbus","other"};
3325 const char* const ids2
[]={"ps2","serial","parallel","floppy","scsi","ide","usb","adb","raid","sbus","i2o","vio","ccw","iucv"};
3328 else if(busid
>=0x80 && busid
<0x8e)
3329 return ids2
[busid
-0x80];
3335 * Check if the execution of (*func)() takes longer than timeout seconds.
3336 * This is useful to work around long kernel-timeouts as in the floppy
3337 * detection and ps/2 mouse detection.
3339 int hd_timeout(void(*func
)(void *), void *arg
, int timeout
)
3345 if(child1
== -1) return -1;
3348 if(waitpid(child1
, &status
, 0) == -1) return -1;
3349 // fprintf(stderr, ">child1 status: 0x%x\n", status);
3351 if(WIFEXITED(status
)) {
3352 status
= WEXITSTATUS(status
);
3353 // fprintf(stderr, ">normal child1 status: 0x%x\n", status);
3354 /* != 0 if we timed out */
3363 #ifdef LIBHD_MEMCHECK
3364 /* stop logging in child process */
3365 if(libhd_log
) fclose(libhd_log
);
3370 if(child2
== -1) return -1;
3373 // fprintf(stderr, ">signal\n");
3374 signal(SIGALRM
, timeout_alarm_handler
);
3376 if(waitpid(child2
, &status
, 0) == -1) return -1;
3377 // fprintf(stderr, ">child2 status: 0x%x\n", status);
3386 return status
? 1 : 0;
3389 void timeout_alarm_handler(int signal
)
3396 * Return list of loaded modules. Converts '-' to '_'.
3398 str_list_t
*read_kmods(hd_data_t
*hd_data
)
3400 str_list_t
*sl
, *sl0
, *sl1
= NULL
;
3403 if(!hd_data
->kmods
|| hd_data
->flags
.keep_kmods
!= 2) {
3404 hd_data
->kmods
= free_str_list(hd_data
->kmods
);
3405 if(!(sl0
= read_file(PROC_MODULES
, 0, 0))) return NULL
;
3406 hd_data
->kmods
= sl0
;
3407 if(hd_data
->flags
.keep_kmods
== 1) hd_data
->flags
.keep_kmods
= 2;
3410 for(sl
= hd_data
->kmods
; sl
; sl
= sl
->next
) {
3412 add_str_list(&sl1
, strsep(&s
, " \t"));
3415 for(sl
= sl1
; sl
; sl
= sl
->next
) {
3416 for(s
= sl
->str
; *s
; s
++) if(*s
== '-') *s
= '_';
3423 str_list_t
*get_cmdline(hd_data_t
*hd_data
, char *key
)
3425 str_list_t
*sl0
, *sl1
, *cmd
= NULL
;
3427 int i
, l
= strlen(key
);
3429 if(!hd_data
->cmd_line
) {
3430 sl0
= read_file(PROC_CMDLINE
, 0, 1);
3431 sl1
= read_file(LIB_CMDLINE
, 0, 1);
3434 i
= strlen(sl0
->str
);
3435 if(i
&& sl0
->str
[i
- 1] == '\n') sl0
->str
[i
- 1] = 0;
3436 hd_data
->cmd_line
= new_str(sl0
->str
);
3437 if(hd_data
->debug
) {
3438 ADD2LOG("----- " PROC_CMDLINE
" -----\n");
3439 ADD2LOG(" %s\n", sl0
->str
);
3440 ADD2LOG("----- " PROC_CMDLINE
" end -----\n");
3444 i
= strlen(sl1
->str
);
3445 if(i
&& sl1
->str
[i
- 1] == '\n') sl1
->str
[i
- 1] = 0;
3446 str_printf(&hd_data
->cmd_line
, -1, " %s", sl1
->str
);
3447 if(hd_data
->debug
) {
3448 ADD2LOG("----- " LIB_CMDLINE
" -----\n");
3449 ADD2LOG(" %s\n", sl1
->str
);
3450 ADD2LOG("----- " LIB_CMDLINE
" end -----\n");
3458 if(!hd_data
->cmd_line
) return NULL
;
3460 t
= t0
= new_str(hd_data
->cmd_line
);
3461 while((s
= strsep(&t
, " "))) {
3463 if(!strncmp(s
, key
, l
) && s
[l
] == '=') {
3464 add_str_list(&cmd
, s
+ l
+ 1);
3475 * Return field 'field' (starting with 0) from the 'SuSE='
3476 * kernel cmd line parameter.
3478 char *get_cmd_param(hd_data_t
*hd_data
, int field
)
3483 if(!(cmd
= get_cmdline(hd_data
, "SuSE"))) return NULL
;
3490 for(; field
; field
--) {
3491 if(!(s
= strchr(s
, ','))) break;
3495 if(s
&& (t
= strchr(s
, ','))) *t
= 0;
3506 unsigned get_disk_crc(unsigned char *data
, unsigned len
)
3511 for(i
= 0; i
< len
; i
++) {
3519 disk_t
*add_disk_entry(disk_t
**dl
, disk_t
*new_dl
)
3521 while(*dl
) dl
= &(*dl
)->next
;
3522 return *dl
= new_dl
;
3525 disk_t
*free_disk_list(disk_t
*dl
)
3529 for(; dl
; dl
= (l
= dl
)->next
, free_mem(l
));
3534 int dev_name_duplicate(disk_t
*dl
, char *dev_name
)
3536 for(; dl
; dl
= dl
->next
) {
3537 if(!strcmp(dl
->dev_name
, dev_name
)) return 1;
3543 unsigned hd_boot_disk(hd_data_t
*hd_data
, int *matches
)
3546 unsigned crc
, hd_idx
= 0;
3549 disk_t
*dl
, *dl0
= NULL
, *dl1
= NULL
;
3551 #ifdef LIBHD_MEMCHECK
3554 fprintf(libhd_log
, "; %s\t%p\t%p\n", __FUNCTION__
, CALLED_FROM(hd_boot_disk
, hd_data
), hd_data
);
3558 if(matches
) *matches
= 0;
3560 if(!(s
= get_cmd_param(hd_data
, 2))) return 0;
3574 if((hd_data
->debug
& HD_DEB_BOOT
)) {
3575 ADD2LOG(" boot dev crc 0x%x\n", crc
);
3578 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3580 hd
->base_class
.id
== bc_storage_device
&&
3581 hd
->sub_class
.id
== sc_sdev_disk
&&
3584 if(dev_name_duplicate(dl0
, hd
->unix_dev_name
)) continue;
3585 dl
= add_disk_entry(&dl0
, new_mem(sizeof *dl0
));
3586 dl
->dev_name
= hd
->unix_dev_name
;
3587 dl
->hd_idx
= hd
->idx
;
3588 dl
->crc
= get_disk_crc(dl
->data
= hd
->block0
, 512);
3594 if((hd_data
->debug
& HD_DEB_BOOT
)) {
3595 for(dl
= dl0
; dl
; dl
= dl
->next
) {
3596 ADD2LOG(" crc %s 0x%08x\n", dl
->dev_name
, dl
->crc
);
3600 for(i
= 0, dl
= dl0
; dl
; dl
= dl
->next
) {
3601 if(crc
== dl
->crc
) {
3604 if(!i
++) hd_idx
= dl
->hd_idx
;
3608 if(i
== 1 && dl1
&& (hd_data
->debug
& HD_DEB_BOOT
)) {
3609 ADD2LOG("----- MBR -----\n");
3610 for(j
= 0; j
< 512; j
+= 0x10) {
3611 ADD2LOG(" %03x ", j
);
3612 hexdump(&hd_data
->log
, 1, 0x10, dl1
->data
+ j
);
3615 ADD2LOG("----- MBR end -----\n");
3618 free_disk_list(dl0
);
3620 if(matches
) *matches
= i
;
3622 hd_data
->debug
&= ~HD_DEB_BOOT
;
3627 void update_irq_usage(hd_data_t
*hd_data
)
3636 mi
= hd_data
->misc
->irq
;
3637 for(u
= 0; u
< hd_data
->misc
->irq_len
; u
++) {
3643 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3644 for(res
= hd
->res
; res
; res
= res
->next
) {
3645 if(res
->any
.type
== res_irq
) {
3646 irqs
|= 1ull << res
->irq
.base
;
3651 hd_data
->used_irqs
= irqs
;
3654 int run_cmd(hd_data_t
*hd_data
, char *cmd
)
3657 str_list_t
*sl
, *sl0
;
3659 ADD2LOG("----- exec: \"%s\" -----\n", cmd
);
3662 str_printf(&xcmd
, 0, "|%s 2>&1", cmd
);
3663 sl0
= read_file(xcmd
, 0, 0);
3664 for(sl
= sl0
; sl
; sl
= sl
->next
) ADD2LOG(" %s", sl
->str
);
3665 sl0
= free_str_list(sl0
);
3668 ADD2LOG("----- return code: ? -----\n");
3675 int probe_module(hd_data_t
*hd_data
, char *module
)
3681 if(hd_module_is_active(hd_data
, module
)) return 0;
3683 if(stat(PROG_MODPROBE
, &sbuf
)) return 127;
3685 str_printf(&cmd
, 0, PROG_MODPROBE
" %s", module
);
3687 i
= run_cmd(hd_data
, cmd
);
3694 int load_module_with_params(hd_data_t
*hd_data
, char *module
, char *params
)
3700 if(hd_module_is_active(hd_data
, module
)) return 0;
3702 if(stat(PROG_MODPROBE
, &sbuf
)) return 127;
3704 str_printf(&cmd
, 0, PROG_MODPROBE
" %s %s", module
, params
? params
: "");
3706 i
= run_cmd(hd_data
, cmd
);
3713 int load_module(hd_data_t
*hd_data
, char *module
)
3715 return load_module_with_params(hd_data
, module
, NULL
);
3718 int unload_module(hd_data_t
*hd_data
, char *module
)
3723 if(!hd_module_is_active(hd_data
, module
)) return 0;
3725 str_printf(&cmd
, 0, PROG_RMMOD
" %s", module
);
3727 i
= run_cmd(hd_data
, cmd
);
3735 * Compare two hd entries and return 0 if they are identical.
3737 int cmp_hd(hd_t
*hd1
, hd_t
*hd2
)
3739 if(!hd1
|| !hd2
) return 1;
3742 hd1
->bus
.id
!= hd2
->bus
.id
||
3743 hd1
->slot
!= hd2
->slot
||
3744 hd1
->func
!= hd2
->func
||
3745 hd1
->base_class
.id
!= hd2
->base_class
.id
||
3746 hd1
->sub_class
.id
!= hd2
->sub_class
.id
||
3747 hd1
->prog_if
.id
!= hd2
->prog_if
.id
||
3748 hd1
->device
.id
!= hd2
->device
.id
||
3749 hd1
->vendor
.id
!= hd2
->vendor
.id
||
3750 hd1
->sub_vendor
.id
!= hd2
->sub_vendor
.id
||
3751 hd1
->revision
.id
!= hd2
->revision
.id
||
3752 hd1
->compat_device
.id
!= hd2
->compat_device
.id
||
3753 hd1
->compat_vendor
.id
!= hd2
->compat_vendor
.id
||
3755 hd1
->module
!= hd2
->module
||
3756 hd1
->line
!= hd2
->line
3761 if(hd1
->unix_dev_name
|| hd2
->unix_dev_name
) {
3762 if(hd1
->unix_dev_name
&& hd2
->unix_dev_name
) {
3763 if(strcmp(hd1
->unix_dev_name
, hd2
->unix_dev_name
)) return 1;
3774 void get_probe_env(hd_data_t
*hd_data
)
3777 str_list_t
*cmd
= NULL
;
3781 env
= getenv("hwprobe");
3783 cmd
= get_cmdline(hd_data
, "hwprobe");
3784 if(cmd
) env
= cmd
->str
;
3786 s
= env
= new_str(env
);
3792 hd_data
->xtra_hd
= free_str_list(hd_data
->xtra_hd
);
3794 while((t
= strsep(&s
, ","))) {
3798 else if(*t
== '-') {
3803 // ADD2LOG("hwprobe: +/- missing before \"%s\"\n", t);
3807 if((j
= hd_probe_feature_by_name(t
))) {
3808 set_probe_feature(hd_data
, j
, k
? 1 : 0);
3810 else if(sscanf(t
, "%8[^:]:%8[^:]:%8[^:]", buf
, buf
, buf
) == 3) {
3811 add_str_list(&hd_data
->xtra_hd
, t
- (k
== 2 ? 0 : 1));
3814 if(*t
) ADD2LOG("hwprobe: what is \"%s\"?\n", t
);
3822 void hd_scan_xtra(hd_data_t
*hd_data
)
3826 unsigned u0
, u1
, u2
, tag
;
3828 char buf0
[10], buf1
[10], buf2
[10], buf3
[64], *s
, k
;
3830 hd_data
->module
= mod_xtra
;
3832 remove_hd_entries(hd_data
);
3834 for(sl
= hd_data
->xtra_hd
; sl
; sl
= sl
->next
) {
3838 case '+': k
= 1; s
++; break;
3839 case '-': k
= 0; s
++; break;
3843 (i
= sscanf(s
, "%8[^:]:%8[^:]:%8[^:]:%60s", buf0
, buf1
, buf2
, buf3
)) >= 3
3845 if(i
< 4) *buf3
= 0;
3847 u0
= strtoul(buf0
, &s
, 16);
3849 if(strlen(buf1
) == 3) {
3850 u1
= name2eisa_id(buf1
);
3856 case 'p': tag
= TAG_PCI
; s
++; break;
3857 case 'r': tag
= 0; s
++; break;
3858 case 's': tag
= TAG_SPECIAL
; s
++; break;
3859 case 'u': tag
= TAG_USB
; s
++; break;
3860 case 'P': tag
= TAG_PCMCIA
; s
++; break;
3862 u1
= strtoul(s
, &s
, 16);
3864 u1
= MAKE_ID(tag
, u1
);
3866 u2
= strtoul(buf2
, &s
, 16);
3868 u2
= MAKE_ID(ID_TAG(u1
), ID_VALUE(u2
));
3869 if((err
& 1) && !strcmp(buf0
, "*")) {
3873 if((err
& 2) && !strcmp(buf1
, "*")) {
3877 if((err
& 4) && !strcmp(buf2
, "*")) {
3885 hd_tmp
= hd_data
->hd
;
3887 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
3892 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
3894 hd
->base_class
.id
= u0
>> 8;
3895 hd
->sub_class
.id
= u0
& 0xff;
3898 if(ID_TAG(hd
->vendor
.id
) == TAG_PCI
) hd
->bus
.id
= bus_pci
;
3899 if(ID_TAG(hd
->vendor
.id
) == TAG_USB
) hd
->bus
.id
= bus_usb
;
3900 if(ID_TAG(hd
->vendor
.id
) == TAG_PCMCIA
) {
3901 hd
->bus
.id
= bus_pcmcia
;
3902 hd
->hotplug
= hp_pcmcia
;
3904 if(*buf3
) hd
->unix_dev_name
= new_str(buf3
);
3905 hd
->status
.available
= status_yes
;
3906 hd
->status
.configured
= status_new
;
3907 hd
->status
.needed
= status_no
;
3910 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
3913 hd
->base_class
.id
== (u0
>> 8) &&
3914 hd
->sub_class
.id
== (u0
& 0xff)
3916 (u1
== 0 || hd
->vendor
.id
== u1
) &&
3917 (u2
== 0 || hd
->device
.id
== u2
) &&
3919 hd
->unix_dev_name
&&
3920 !strcmp(hd
->unix_dev_name
, buf3
)
3926 remove_tagged_hd_entries(hd_data
);
3933 unsigned has_something_attached(hd_data_t
*hd_data
, hd_t
*hd
)
3937 for(hd1
= hd_data
->hd
; hd1
; hd1
= hd1
->next
) {
3938 if(hd1
->attached_to
== hd
->idx
) return hd1
->idx
;
3945 /* ##### FIX: replace with a real crc later ##### */
3946 void crc64(uint64_t *id
, void *p
, int len
)
3950 for(; len
; len
--, p
++) {
3951 uc
= *(unsigned char *) p
;
3952 *id
+= uc
+ ((uc
+ 57) << 27);
3958 char *numid2str(uint64_t id
, int len
)
3960 static char buf
[32];
3962 #ifdef NUMERIC_UNIQUE_ID
3965 if(len
< (sizeof id
<< 3)) id
&= ~(-1LL << len
);
3966 sprintf(buf
, "%0*"PRIx64
, len
>> 2, id
);
3974 memset(buf
, 0, sizeof buf
);
3975 for(i
= 0; len
> 0 && i
< (int) sizeof buf
- 1; i
++, len
-= 6, id
>>= 6) {
3978 u
+= '0'; /* 0..9 */
3980 else if(u
< 10 + 26) {
3981 u
+= 'A' - 10; /* A..Z */
3983 else if(u
< 10 + 26 + 26) {
3984 u
+= 'a' - 10 - 26; /* a..z */
4001 * calculate unique ids
4003 #define INT_CRC(a, b) crc64(&a, &hd->b, sizeof hd->b);
4004 #define STR_CRC(a, b) if(hd->b) crc64(&a, hd->b, strlen(hd->b) + 1);
4008 void hd_add_old_id(hd_t
*hd
)
4010 uint64_t id0
= 0, id1
= 0;
4012 if(hd
->unique_id
) return;
4014 INT_CRC(id0
, bus
.id
);
4017 INT_CRC(id0
, base_class
.id
);
4018 INT_CRC(id0
, sub_class
.id
);
4019 INT_CRC(id0
, prog_if
.id
);
4020 STR_CRC(id0
, unix_dev_name
);
4021 STR_CRC(id0
, rom_id
);
4023 INT_CRC(id1
, base_class
.id
);
4024 INT_CRC(id1
, sub_class
.id
);
4025 INT_CRC(id1
, prog_if
.id
);
4026 INT_CRC(id1
, device
.id
);
4027 INT_CRC(id1
, vendor
.id
);
4028 INT_CRC(id1
, sub_device
.id
);
4029 INT_CRC(id1
, sub_vendor
.id
);
4030 INT_CRC(id1
, revision
.id
);
4031 INT_CRC(id1
, compat_device
.id
);
4032 INT_CRC(id1
, compat_vendor
.id
);
4033 STR_CRC(id1
, device
.name
);
4034 STR_CRC(id1
, vendor
.name
);
4035 STR_CRC(id1
, sub_device
.name
);
4036 STR_CRC(id1
, sub_vendor
.name
);
4037 STR_CRC(id1
, revision
.name
);
4038 STR_CRC(id1
, serial
);
4041 str_printf(&hd
->unique_id
, 0, "%s", numid2str(id0
, 24));
4042 str_printf(&hd
->unique_id
, -1, ".%s", numid2str(id1
, 64));
4045 void hd_add_id(hd_data_t
*hd_data
, hd_t
*hd
)
4047 uint64_t id0
= 0, id1
= 0;
4049 if(hd
->unique_id
) return;
4052 hd
->old_unique_id
= hd
->unique_id
;
4053 hd
->unique_id
= NULL
;
4055 INT_CRC(id1
, base_class
.id
);
4056 INT_CRC(id1
, sub_class
.id
);
4057 INT_CRC(id1
, prog_if
.id
);
4058 INT_CRC(id1
, device
.id
);
4059 INT_CRC(id1
, vendor
.id
);
4060 INT_CRC(id1
, sub_device
.id
);
4061 INT_CRC(id1
, sub_vendor
.id
);
4062 INT_CRC(id1
, revision
.id
);
4065 hd
->detail
->type
== hd_detail_ccw
&&
4066 hd
->detail
->ccw
.data
4067 ) INT_CRC(id1
, detail
->ccw
.data
->cu_model
);
4068 INT_CRC(id1
, compat_device
.id
);
4069 INT_CRC(id1
, compat_vendor
.id
);
4070 // make sure we get the same id even if, say, the pci name list changes
4071 if(!hd
->device
.id
) STR_CRC(id1
, device
.name
);
4072 if(!hd
->vendor
.id
) STR_CRC(id1
, vendor
.name
);
4073 if(!hd
->sub_device
.name
) STR_CRC(id1
, sub_device
.name
);
4074 if(!hd
->sub_vendor
.name
) STR_CRC(id1
, sub_vendor
.name
);
4075 if(!hd
->revision
.name
) STR_CRC(id1
, revision
.name
);
4076 STR_CRC(id1
, serial
);
4078 hd
->unique_id1
= new_str(numid2str(id1
, 64));
4080 INT_CRC(id0
, bus
.id
);
4083 (hd
->bus
.id
== bus_usb
||
4084 hd
->bus
.id
== bus_ccw
) &&
4087 STR_CRC(id0
, sysfs_bus_id
);
4090 hd
->bus
.id
!= bus_usb
&&
4091 hd
->bus
.id
!= bus_pci
&&
4094 STR_CRC(id0
, sysfs_id
);
4096 else if(hd
->unix_dev_name
) {
4097 STR_CRC(id0
, unix_dev_name
);
4104 STR_CRC(id0
, rom_id
);
4108 str_printf(&hd
->unique_id
, 0, "%s.%s", numid2str(id0
, 24), hd
->unique_id1
);
4114 devtree_t
*free_devtree(hd_data_t
*hd_data
)
4117 devtree_t
*dt
, *next
;
4120 * first, remove all references in the current device tree
4121 * (refs in hd_old can remain)
4123 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
4124 if(hd
->detail
&& hd
->detail
->type
== hd_detail_devtree
) {
4125 hd
->detail
= free_mem(hd
->detail
);
4129 for(dt
= hd_data
->devtree
; dt
; dt
= next
) {
4133 free_mem(dt
->filename
);
4135 free_mem(dt
->model
);
4136 free_mem(dt
->device_type
);
4137 free_mem(dt
->compatible
);
4143 return hd_data
->devtree
= NULL
;
4147 void test_read_block0_open(void *arg
)
4149 open((char *) arg
, O_RDONLY
);
4152 unsigned char *read_block0(hd_data_t
*hd_data
, char *dev
, int *timeout
)
4154 int fd
, len
, buf_size
= 512, k
, sel
;
4155 unsigned char *buf
= NULL
;
4159 if(hd_timeout(test_read_block0_open
, dev
, *timeout
) > 0) {
4160 ADD2LOG(" read_block0: open(%s) timed out\n", dev
);
4165 fd
= open(dev
, O_RDONLY
);
4166 if(fd
< 0) ADD2LOG(" read_block0: open(%s) failed\n", dev
);
4169 buf
= new_mem(buf_size
);
4175 to
.tv_sec
= *timeout
; to
.tv_usec
= 0;
4178 if((sel
= select(fd
+ 1, &set
, NULL
, NULL
, &to
)) > 0) {
4179 if((k
= read(fd
, buf
+ len
, buf_size
- len
)) > 0) len
+= k
;
4180 ADD2LOG(" read_block0: %d bytes (%ds, %dus)\n", k
, (int) to
.tv_sec
, (int) to
.tv_usec
);
4181 if(k
<= 0 || buf_size
== len
) break;
4184 *timeout
= -2; break;
4189 ADD2LOG(" read_block0: read error(%s, %d, %d): errno %d\n", dev
, len
, buf_size
- len
, errno
);
4190 buf
= free_mem(buf
);
4199 void get_kernel_version(hd_data_t
*hd_data
)
4204 if(hd_data
->kernel_version
) return;
4206 hd_data
->kernel_version
= KERNEL_24
;
4208 sl
= read_file(PROC_VERSION
, 0, 1);
4210 if(!sl
|| !sl
->str
) return;
4212 if(sscanf(sl
->str
, "Linux version %u.%u.", &u1
, &u2
) == 2) {
4213 if(hd_data
->debug
) {
4214 ADD2LOG("kernel version is %u.%u\n", u1
, u2
);
4216 u1
= (u1
<< 16) + (u2
<< 8);
4218 if(u1
<= KERNEL_22
) {
4219 hd_data
->kernel_version
= KERNEL_22
;
4221 else if(u1
<= KERNEL_24
) {
4222 hd_data
->kernel_version
= KERNEL_24
;
4224 else if(u1
<= KERNEL_26
) {
4225 hd_data
->kernel_version
= KERNEL_26
;
4233 char *vend_id2str(unsigned vend
)
4235 static char buf
[32];
4240 if(ID_TAG(vend
) == TAG_EISA
) {
4241 strcpy(s
, eisa_vendor_str(vend
));
4244 if(ID_TAG(vend
) == TAG_USB
) *s
++ = 'u', *s
= 0;
4245 if(ID_TAG(vend
) == TAG_SPECIAL
) *s
++ = 's', *s
= 0;
4246 if(ID_TAG(vend
) == TAG_PCMCIA
) *s
++ = 'P', *s
= 0;
4247 sprintf(s
, "%04x", ID_VALUE(vend
));
4254 int is_modem(hd_data_t
*hd_data
, hd_t
*hd
)
4257 hd
->base_class
.id
== bc_modem
||
4259 hd
->base_class
.id
== bc_comm
&&
4260 hd
->sub_class
.id
== sc_com_modem
4268 int is_audio(hd_data_t
*hd_data
, hd_t
*hd
)
4270 /* ISA-PnP sound cards: just one entry per card */
4272 hd
->bus
.id
== bus_isa
&&
4278 hd
->base_class
.id
== bc_multimedia
&&
4280 hd
->sub_class
.id
== sc_multi_audio
||
4281 hd
->sub_class
.id
== 3
4289 void assign_hw_class(hd_data_t
*hd_data
, hd_t
*hd
)
4291 int sc
; /* compare sub_class too */
4292 unsigned base_class
, sub_class
;
4294 int (*test_func
)(hd_data_t
*, hd_t
*);
4298 // ###### FIXME: maybe just return here?
4299 if(!hd
->hw_class
) { /* skip if we've already done it */
4300 for(item
= 1; item
< hw_all
; item
++) {
4310 base_class
= bc_storage_device
;
4311 sub_class
= sc_sdev_cdrom
;
4316 base_class
= bc_storage_device
;
4317 sub_class
= sc_sdev_floppy
;
4322 base_class
= bc_storage_device
;
4323 sub_class
= sc_sdev_disk
;
4328 base_class
= bc_network_interface
;
4332 base_class
= bc_display
;
4336 base_class
= bc_monitor
;
4340 base_class
= bc_mouse
;
4344 base_class
= bc_joystick
;
4348 base_class
= bc_keyboard
;
4352 base_class
= bc_camera
;
4355 case hw_framebuffer
:
4356 base_class
= bc_framebuffer
;
4360 base_class
= bc_chipcard
;
4364 test_func
= is_audio
;
4368 base_class
= bc_isdn
;
4372 base_class
= bc_dsl
;
4376 test_func
= is_modem
;
4379 case hw_storage_ctrl
:
4380 base_class
= bc_storage
;
4383 case hw_network_ctrl
:
4384 base_class
= bc_network
;
4388 base_class
= bc_printer
;
4396 base_class
= bc_dvb
;
4400 base_class
= bc_scanner
;
4404 base_class
= bc_braille
;
4408 base_class
= bc_internal
;
4409 sub_class
= sc_int_sys
;
4414 base_class
= bc_internal
;
4415 sub_class
= sc_int_cpu
;
4420 base_class
= bc_internal
;
4421 sub_class
= sc_int_bios
;
4426 base_class
= bc_serial
;
4427 sub_class
= sc_ser_usb
;
4432 base_class
= bc_bridge
;
4436 base_class
= bc_hub
;
4440 base_class
= bc_internal
;
4441 sub_class
= sc_int_main_mem
;
4445 case hw_ieee1394_ctrl
:
4446 base_class
= bc_serial
;
4447 sub_class
= sc_ser_fire
;
4451 case hw_pcmcia_ctrl
:
4452 test_func
= is_pcmcia_ctrl
;
4456 base_class
= bc_network_interface
;
4460 base_class
= bc_partition
;
4464 base_class
= bc_bluetooth
;
4475 case hw_manual
: /* special */
4484 case hw_pcmcia
: /* special */
4486 case hw_ieee1394
: /* not handled */
4487 case hw_hotplug
: /* not handled */
4488 case hw_hotplug_ctrl
: /* not handled */
4489 case hw_zip
: /* not handled */
4495 if(test_func(hd_data
, hd
)) {
4496 hd
->hw_class
= item
;
4502 hd
->base_class
.id
== base_class
&&
4503 (sc
== 0 || hd
->sub_class
.id
== sub_class
)
4506 ( /* list other display adapters, too */
4507 base_class
== bc_display
&&
4508 hd
->base_class
.id
== bc_multimedia
&&
4509 hd
->sub_class
.id
== sc_multi_video
4512 ( /* make i2o storage controllers */
4513 item
== hw_storage_ctrl
&&
4514 hd
->base_class
.id
== bc_i2o
4517 ( /* add fibre channel to storage ctrl list */
4518 item
== hw_storage_ctrl
&&
4519 hd
->base_class
.id
== bc_serial
&&
4520 hd
->sub_class
.id
== sc_ser_fiber
4523 hd
->hw_class
= item
;
4528 if(!hd
->hw_class
) hd
->hw_class
= hw_unknown
;
4531 hd_set_hw_class(hd
, hd
->hw_class
);
4533 if(hd
->bus
.id
== bus_usb
) {
4534 hd_set_hw_class(hd
, hw_usb
);
4536 else if(hd
->bus
.id
== bus_pci
) {
4537 hd_set_hw_class(hd
, hw_pci
);
4539 else if(hd
->bus
.id
== bus_scsi
) {
4540 hd_set_hw_class(hd
, hw_scsi
);
4542 else if(hd
->bus
.id
== bus_ide
) {
4543 hd_set_hw_class(hd
, hw_ide
);
4545 else if(hd
->bus
.id
== bus_isa
&& hd
->is
.isapnp
) {
4546 hd_set_hw_class(hd
, hw_isapnp
);
4549 if(hd
->hw_class
== hw_network
&& hd
->is
.pppoe
) {
4550 hd_set_hw_class(hd
, hw_pppoe
);
4554 hd_set_hw_class(hd
, hw_usb
); // ###### maybe only if(hd->bus.id == bus_scsi)?
4557 if(hd
->hotplug
== hp_pcmcia
|| hd
->hotplug
== hp_cardbus
) {
4558 hd_set_hw_class(hd
, hw_pcmcia
);
4562 hd_set_hw_class(hd
, hw_wlan
);
4565 if(hd_is_hw_class(hd
, hw_bios
)) {
4566 hd_set_hw_class(hd
, hw_vbe
);
4570 hd
->base_class
.id
== bc_storage_device
||
4571 hd
->base_class
.id
== bc_partition
4573 hd_set_hw_class(hd
, hw_block
);
4577 hd
->base_class
.id
== bc_storage_device
&&
4578 hd
->sub_class
.id
== sc_sdev_tape
4580 hd_set_hw_class(hd
, hw_tape
);
4584 hd
->base_class
.id
== bc_storage_device
&&
4585 hd
->sub_class
.id
== sc_sdev_disk
4587 hd_set_hw_class(hd
, hw_redasd
);
4592 void short_vendor(char *vendor
)
4594 static char *remove
[] = {
4595 ".", ",", "-", "&", " inc", "corporation", " corp", " system",
4596 " systems", "technology", "technologies", "multimedia", "communications",
4597 "computer", " ltd", "(formerly ncr)", " group", " labs", "research",
4598 "equipment", " ag", "personal", " canada", "data", "products",
4599 " america", " co", " of", "solutions", " as", "publishing", "(old)",
4600 " usa", " gmbh", "electronic", "components", "(matsushita)", " ab",
4601 " pte", " north", " japan", "limited", "microcomputer", " kg",
4602 "incorporated", "semiconductor", "sem", "graphics"
4605 int len
, len1
, len2
;
4609 len2
= strlen(vendor
);
4615 for(i
= 0; (unsigned) i
< sizeof remove
/ sizeof *remove
; i
++) {
4616 len1
= strlen(remove
[i
]);
4617 if(len
> len1
&& !strcasecmp(vendor
+ len
- len1
, remove
[i
])) {
4618 vendor
[j
= len
- len1
] = 0;
4619 for(j
--; j
>= 0; vendor
[j
--] = 0) {
4620 if(!isspace(vendor
[j
])) break;
4624 len2
= strlen(vendor
);
4625 } while(len2
!= len
);
4630 void create_model_name(hd_data_t
*hd_data
, hd_t
*hd
)
4633 char *compat
, *dev_class
, *hw_class
;
4634 char *part1
, *part2
;
4638 if(!hd
|| hd
->model
) return;
4640 part1
= part2
= NULL
;
4642 vend
= dev
= compat
= dev_class
= hw_class
= NULL
;
4645 hd
->hw_class
== hw_cpu
&&
4647 hd
->detail
->type
== hd_detail_cpu
&&
4648 (ct
= hd
->detail
->cpu
.data
) &&
4653 part1
= new_str(ct
->model_name
);
4654 if(ct
->clock
) str_printf(&part1
, -1, ", %u MHz", ct
->clock
);
4659 vend
= new_str(hd
->sub_vendor
.name
);
4661 dev
= new_str(hd
->sub_device
.name
);
4663 if(!vend
) vend
= new_str(hd
->vendor
.name
);
4665 if(!dev
) dev
= new_str(hd
->device
.name
);
4669 part1
= vend
; part2
= dev
;
4676 if(!part1
&& !part2
) {
4677 compat
= new_str(hd
->compat_device
.name
);
4679 dev_class
= new_str(hd
->sub_class
.name
?: hd
->base_class
.name
);
4681 hw_class
= new_str(hd_hw_item_name(hd
->hw_class
));
4685 part1
= vend
; part2
= compat
;
4687 else if(dev_class
) {
4688 part1
= vend
; part2
= dev_class
;
4695 hd
->base_class
.id
!= bc_internal
/* avoid things like 'Notebook *System*' */
4697 part1
= compat
; part2
= dev_class
;
4702 else if(dev_class
) {
4704 if(hw_class
&& !strchr(part1
, ' ') && strchr(hw_class
, ' ')) {
4712 if(part1
&& part2
) {
4713 short_vendor(part1
);
4716 if(part1
&& !strcasecmp(part1
, "unknown")) {
4721 if(part1
&& part2
) {
4722 /* maybe the vendor name is already part of the device name... */
4723 if(strstr(part2
, part1
) || !strcasecmp(part1
, part2
)) {
4729 if(!part1
&& !part2
&& hw_class
) {
4730 str_printf(&part1
, 0, "unknown %s", hw_class
);
4731 if(strchr(hw_class
, ' ')) {
4732 str_printf(&part1
, -1, " hardware");
4736 str_printf(&hd
->model
, 0, "%s%s%s", part1
, part2
? " " : "", part2
? part2
: "");
4741 free_mem(dev_class
);
4747 int hd_change_status(const char *id
, hd_status_t status
, const char *config_string
)
4753 hd_data
= new_mem(sizeof *hd_data
);
4755 entry
= hd_manual_read_entry(hd_data
, (char *) id
);
4757 if(!entry
|| status
.invalid
) return 1;
4759 if(status
.configured
) entry
->status
.configured
= status
.configured
;
4760 if(status
.available
) entry
->status
.available
= status
.available
;
4761 if(status
.needed
) entry
->status
.needed
= status
.needed
;
4762 entry
->status
.invalid
= status
.invalid
;
4765 free_mem(entry
->config_string
);
4766 entry
->config_string
= new_str(config_string
);
4769 i
= hd_manual_write_entry(hd_data
, entry
);
4771 hd_free_manual(entry
);
4773 hd_free_hd_data(hd_data
);
4780 #endif /* !defined(LIBHD_TINY) */
4783 int hd_getdisksize(hd_data_t
*hd_data
, char *dev
, int fd
, hd_res_t
**geo
, hd_res_t
**size
)
4787 struct hd_geometry geo_s
;
4788 #ifdef HDIO_GETGEO_BIG
4789 struct hd_big_geometry big_geo_s
;
4791 unsigned long secs32
;
4792 uint64_t secs
, secs0
;
4797 *geo
= *size
= NULL
;
4799 ADD2LOG(" dev = %s, fd = %d\n", dev
, fd
);
4803 fd
= open(dev
, O_RDONLY
| O_NONBLOCK
);
4805 if(fd
< 0) return 0;
4808 ADD2LOG(" open ok, fd = %d\n", fd
);
4813 #ifdef HDIO_GETGEO_BIG
4814 if(!ioctl(fd
, HDIO_GETGEO_BIG
, &big_geo_s
)) {
4815 if(dev
) ADD2LOG("%s: ioctl(big geo) ok\n", dev
);
4816 res
= add_res_entry(geo
, new_mem(sizeof *res
));
4817 res
->disk_geo
.type
= res_disk_geo
;
4818 res
->disk_geo
.cyls
= big_geo_s
.cylinders
;
4819 res
->disk_geo
.heads
= big_geo_s
.heads
;
4820 res
->disk_geo
.sectors
= big_geo_s
.sectors
;
4821 res
->disk_geo
.geotype
= geo_logical
;
4822 secs0
= (uint64_t) res
->disk_geo
.cyls
* res
->disk_geo
.heads
* res
->disk_geo
.sectors
;
4826 ADD2LOG(" big geo failed: %s\n", strerror(errno
));
4830 if(!ioctl(fd
, HDIO_GETGEO
, &geo_s
)) {
4831 if(dev
) ADD2LOG("%s: ioctl(geo) ok\n", dev
);
4832 res
= add_res_entry(geo
, new_mem(sizeof *res
));
4833 res
->disk_geo
.type
= res_disk_geo
;
4834 res
->disk_geo
.cyls
= geo_s
.cylinders
;
4835 res
->disk_geo
.heads
= geo_s
.heads
;
4836 res
->disk_geo
.sectors
= geo_s
.sectors
;
4837 res
->disk_geo
.geotype
= geo_logical
;
4838 secs0
= (uint64_t) res
->disk_geo
.cyls
* res
->disk_geo
.heads
* res
->disk_geo
.sectors
;
4841 ADD2LOG(" geo failed: %s\n", strerror(errno
));
4845 /* ##### maybe always BLKSZGET or always 0x200? */
4846 if(!ioctl(fd
, BLKSSZGET
, &sec_size
)) {
4847 if(dev
) ADD2LOG("%s: ioctl(block size) ok\n", dev
);
4848 if(!sec_size
) sec_size
= 0x200;
4856 #if defined(__s390__) || defined(__s390x__)
4857 if(res
&& res
->disk_geo
.sectors
== 0)
4858 { /* This seems to be an unformatted DASD -> fake the formatted geometry */
4859 res
->disk_geo
.sectors
=12;
4861 secs
= (uint64_t) res
->disk_geo
.cyls
* res
->disk_geo
.heads
* res
->disk_geo
.sectors
;
4867 if(!ioctl(fd
, BLKGETSIZE64
, &secs
)) {
4868 if(dev
) ADD2LOG("%s: ioctl(disk size) ok\n", dev
);
4871 else if(!ioctl(fd
, BLKGETSIZE
, &secs32
)) {
4872 if(dev
) ADD2LOG("%s: ioctl(disk size32) ok\n", dev
);
4878 #if defined(__s390__) || defined(__s390x__)
4882 if(!got_big
&& secs0
&& res
) {
4883 /* fix cylinder value */
4884 res
->disk_geo
.cyls
= secs
/ (res
->disk_geo
.heads
* res
->disk_geo
.sectors
);
4888 res
= add_res_entry(size
, new_mem(sizeof *res
));
4889 res
->size
.type
= res_size
;
4890 res
->size
.unit
= size_unit_sectors
;
4891 res
->size
.val1
= secs
;
4892 res
->size
.val2
= sec_size
;
4895 // ADD2LOG(" geo = %p, size = %p\n", *geo, *size);
4897 if(close_fd
) close(fd
);
4903 str_list_t
*hd_split(char del
, char *str
)
4906 str_list_t
*sl
= NULL
;
4908 if(!str
) return NULL
;
4910 for(s
= str
= new_str(str
); (t
= strchr(s
, del
)); s
= t
+ 1) {
4912 add_str_list(&sl
, s
);
4914 add_str_list(&sl
, s
);
4922 char *hd_join(char *del
, str_list_t
*str
)
4926 int len
= 0, del_len
= 0;
4928 if(del
) del_len
= strlen(del
);
4930 for(str0
= str
; str0
; str0
= str0
->next
) {
4931 if(str0
->str
) len
+= strlen(str0
->str
);
4932 if(str0
->next
) len
+= del_len
;
4935 if(!len
) return NULL
;
4941 for(; str
; str
= str
->next
) {
4942 if(str
->str
) strcat(s
, str
->str
);
4943 if(str
->next
&& del
) strcat(s
, del
);
4951 * cf. pcmcia-cs-*:cardmgr/pcic_probe.c
4953 int is_pcmcia_ctrl(hd_data_t
*hd_data
, hd_t
*hd
)
4956 static unsigned ids
[][2] = {
5002 hd
->base_class
.id
== bc_bridge
&&
5003 (hd
->sub_class
.id
== sc_bridge_pcmcia
|| hd
->sub_class
.id
== sc_bridge_cardbus
)
5006 /* just in case... */
5007 if(hd
->bus
.id
== bus_pci
) {
5008 for(i
= 0; (unsigned) i
< sizeof ids
/ sizeof *ids
; i
++) {
5010 ID_VALUE(hd
->vendor
.id
) == ids
[i
][0] &&
5011 ID_VALUE(hd
->device
.id
) == ids
[i
][1]
5019 void hd_set_hw_class(hd_t
*hd
, hd_hw_item_t hw_class
)
5023 ofs
= (unsigned) hw_class
>> 3;
5024 bit
= (unsigned) hw_class
& 7;
5026 if(ofs
< sizeof hd
->hw_class_list
/ sizeof *hd
->hw_class_list
) {
5027 hd
->hw_class_list
[ofs
] |= 1 << bit
;
5032 int hd_is_hw_class(hd_t
*hd
, hd_hw_item_t hw_class
)
5036 if(hw_class
== hw_all
) return 1;
5038 ofs
= (unsigned) hw_class
>> 3;
5039 bit
= (unsigned) hw_class
& 7;
5041 if(ofs
< sizeof hd
->hw_class_list
/ sizeof *hd
->hw_class_list
) {
5042 return hd
->hw_class_list
[ofs
] & (1 << bit
) ? 1 : 0;
5050 * Start subprocess for dangerous things.
5052 * Stop it after total_timeout seconds or if nothing happens for
5055 void hd_fork(hd_data_t
*hd_data
, int timeout
, int total_timeout
)
5057 void (*old_sigchld_handler
)(int);
5058 struct timespec wait_time
;
5059 int i
, j
, sleep_intr
= 1;
5060 hd_data_t
*hd_data_shm
;
5062 int updated
, rem_time
;
5063 sigset_t new_set
, old_set
;
5065 if(hd_data
->flags
.forked
) return;
5067 if(hd_data
->flags
.nofork
) {
5068 hd_data
->flags
.forked
= 1;
5072 hd_data_shm
= hd_data
->shm
.data
;
5074 stop_time
= time(NULL
) + total_timeout
;
5075 rem_time
= total_timeout
;
5077 child_id
= child
= 0;
5079 sigemptyset(&new_set
);
5080 sigaddset(&new_set
, SIGCHLD
);
5081 sigprocmask(SIG_BLOCK
, &new_set
, &old_set
);
5083 old_sigchld_handler
= signal(SIGCHLD
, sigchld_handler
);
5085 wait_time
.tv_sec
= timeout
;
5086 wait_time
.tv_nsec
= 0;
5088 updated
= hd_data_shm
->shm
.updated
;
5092 sigprocmask(SIG_SETMASK
, &old_set
, NULL
);
5097 "****** started child process %d (%ds/%ds) ******\n",
5098 (int) child
, timeout
, total_timeout
5101 while(child_id
!= child
&& sleep_intr
) {
5102 sleep_intr
= nanosleep(&wait_time
, &wait_time
);
5103 // fprintf(stderr, "woke up %d\n", sleep_intr);
5104 rem_time
= stop_time
- time(NULL
);
5105 if(updated
!= hd_data_shm
->shm
.updated
&& rem_time
>= 0) {
5106 /* reset time if there was some progress and we've got some time left */
5108 wait_time
.tv_sec
= rem_time
> timeout
? timeout
: rem_time
;
5109 wait_time
.tv_nsec
= 0;
5113 updated
= hd_data_shm
->shm
.updated
;
5116 if(child_id
!= child
) {
5117 ADD2LOG("****** killed child process %d (%ds) ******\n", (int) child
, rem_time
);
5118 kill(child
, SIGKILL
);
5119 for(i
= 10; i
&& !waitpid(child
, NULL
, WNOHANG
); i
--) {
5120 wait_time
.tv_sec
= 0;
5121 wait_time
.tv_nsec
= 10*1000000;
5122 nanosleep(&wait_time
, NULL
);
5126 i
= hd_data
->log
? strlen(hd_data
->log
) : 0;
5128 if(hd_data_shm
->log
) {
5129 j
= strlen(hd_data_shm
->log
);
5130 hd_data
->log
= resize_mem(hd_data
->log
, i
+ j
+ 1);
5131 memcpy(hd_data
->log
+ i
, hd_data_shm
->log
, j
+ 1);
5134 ADD2LOG("****** stopped child process %d (%ds) ******\n", (int) child
, rem_time
);
5137 #ifdef LIBHD_MEMCHECK
5138 /* stop logging in child process */
5139 if(libhd_log
) fclose(libhd_log
);
5142 hd_data
->log
= free_mem(hd_data
->log
);
5144 hd_data
->flags
.forked
= 1;
5148 signal(SIGCHLD
, old_sigchld_handler
);
5155 void hd_fork_done(hd_data_t
*hd_data
)
5159 hd_data_t
*hd_data_shm
;
5161 if(!hd_data
->flags
.forked
|| hd_data
->flags
.nofork
) return;
5163 hd_data_shm
= hd_data
->shm
.data
;
5166 len
= strlen(hd_data
->log
) + 1;
5167 p
= hd_shm_add(hd_data
, hd_data
->log
, len
);
5168 hd_data_shm
->log
= p
;
5176 * SIGCHLD handler while we're waiting for our child.
5178 void sigchld_handler(int num
)
5180 pid_t p
= waitpid(child
, NULL
, WNOHANG
);
5182 if(p
&& p
== child
) child_id
= p
;
5187 * Get a sufficiently large shm segment.
5189 void hd_shm_init(hd_data_t
*hd_data
)
5193 if(hd_data
->shm
.ok
|| hd_data
->flags
.nofork
) return;
5195 memset(&hd_data
->shm
, 0, sizeof hd_data
->shm
);
5197 hd_data
->shm
.size
= 256*1024;
5199 hd_data
->shm
.id
= shmget(IPC_PRIVATE
, hd_data
->shm
.size
, IPC_CREAT
| 0600);
5201 if(hd_data
->shm
.id
== -1) {
5202 ADD2LOG("shm: shmget failed (errno %d)\n", errno
);
5206 p
= shmat(hd_data
->shm
.id
, NULL
, 0);
5208 if(p
== (void *) -1) {
5209 ADD2LOG("shm: shmat for segment %d failed (errno %d)\n", hd_data
->shm
.id
, errno
);
5212 shmctl(hd_data
->shm
.id
, IPC_RMID
, NULL
);
5214 if(p
== (void *) -1) return;
5216 hd_data
->shm
.data
= p
;
5218 ADD2LOG("shm: attached segment %d at %p\n", hd_data
->shm
.id
, hd_data
->shm
.data
);
5220 hd_data
->shm
.ok
= 1;
5222 hd_shm_clean(hd_data
);
5227 * Reset shm usage, remove references to shm area.
5229 void hd_shm_clean(hd_data_t
*hd_data
)
5231 hd_data_t
*hd_data_shm
;
5233 if(!hd_data
->shm
.ok
) return;
5235 if(hd_is_shm_ptr(hd_data
, hd_data
->ser_mouse
)) hd_data
->ser_mouse
= NULL
;
5236 if(hd_is_shm_ptr(hd_data
, hd_data
->ser_modem
)) hd_data
->ser_modem
= NULL
;
5239 hd_data
->shm
.used
= sizeof *hd_data
;
5240 hd_data
->shm
.updated
= 0;
5242 memcpy(hd_data_shm
= hd_data
->shm
.data
, hd_data
, sizeof *hd_data
);
5244 hd_data_shm
->log
= NULL
;
5249 * Release shm segment.
5251 void hd_shm_done(hd_data_t
*hd_data
)
5253 if(!hd_data
->shm
.ok
) return;
5255 shmdt(hd_data
->shm
.data
);
5257 hd_data
->shm
.ok
= 0;
5262 * Copy into shm area. If ptr is NULL return a shm area of size len.
5264 void *hd_shm_add(hd_data_t
*hd_data
, void *ptr
, unsigned len
)
5266 if(!hd_data
->shm
.ok
|| !len
) return NULL
;
5268 hd_data
= hd_data
->shm
.data
;
5270 if(hd_data
->shm
.size
- hd_data
->shm
.used
< len
) return NULL
;
5273 ptr
= memcpy(hd_data
->shm
.data
+ hd_data
->shm
.used
, ptr
, len
);
5276 ptr
= memset(hd_data
->shm
.data
+ hd_data
->shm
.used
, 0, len
);
5279 hd_data
->shm
.used
+= len
;
5286 * Check if ptr points to a valid shm address.
5288 int hd_is_shm_ptr(hd_data_t
*hd_data
, void *ptr
)
5290 if(!hd_data
->shm
.ok
|| !ptr
) return 0;
5292 hd_data
= hd_data
->shm
.data
;
5295 ptr
< hd_data
->shm
.data
||
5296 ptr
>= hd_data
->shm
.data
+ hd_data
->shm
.used
5303 char *hd_shm_add_str(hd_data_t
*hd_data
, char *str
)
5305 return hd_shm_add(hd_data
, str
, str
? strlen(str
) + 1 : 0);
5309 str_list_t
*hd_shm_add_str_list(hd_data_t
*hd_data
, str_list_t
*sl
)
5311 str_list_t
*sl0
= NULL
, **sl_shm
;
5313 for(sl_shm
= &sl0
; sl
; sl
= sl
->next
, sl_shm
= &(*sl_shm
)->next
) {
5314 *sl_shm
= hd_shm_add(hd_data
, NULL
, sizeof **sl_shm
);
5315 (*sl_shm
)->str
= hd_shm_add_str(hd_data
, sl
->str
);
5322 void hd_move_to_shm(hd_data_t
*hd_data
)
5324 hd_data_t
*hd_data_shm
;
5325 ser_device_t
*ser
, **ser_shm
;
5327 ser_device_t
**src
, **dst
;
5331 if(!hd_data
->shm
.ok
) return;
5333 hd_data_shm
= hd_data
->shm
.data
;
5335 ser_dev
[0].src
= &hd_data
->ser_mouse
;
5336 ser_dev
[0].dst
= &hd_data_shm
->ser_mouse
;
5337 ser_dev
[1].src
= &hd_data
->ser_modem
;
5338 ser_dev
[1].dst
= &hd_data_shm
->ser_modem
;
5340 for(u
= 0; u
< sizeof ser_dev
/ sizeof *ser_dev
; u
++) {
5341 if(*ser_dev
[u
].src
) {
5342 /* copy serial mouse data */
5344 ser
= *ser_dev
[u
].src
, ser_shm
= ser_dev
[u
].dst
;
5346 ser
= ser
->next
, ser_shm
= &(*ser_shm
)->next
5348 *ser_shm
= hd_shm_add(hd_data
, ser
, sizeof *ser
);
5351 for(ser
= *ser_dev
[u
].dst
; ser
; ser
= ser
->next
) {
5352 ser
->dev_name
= hd_shm_add_str(hd_data
, ser
->dev_name
);
5353 ser
->serial
= hd_shm_add_str(hd_data
, ser
->serial
);
5354 ser
->class_name
= hd_shm_add_str(hd_data
, ser
->class_name
);
5355 ser
->dev_id
= hd_shm_add_str(hd_data
, ser
->dev_id
);
5356 ser
->user_name
= hd_shm_add_str(hd_data
, ser
->user_name
);
5357 ser
->vend
= hd_shm_add_str(hd_data
, ser
->vend
);
5358 ser
->init_string1
= hd_shm_add_str(hd_data
, ser
->init_string1
);
5359 ser
->init_string2
= hd_shm_add_str(hd_data
, ser
->init_string2
);
5360 ser
->pppd_option
= hd_shm_add_str(hd_data
, ser
->pppd_option
);
5362 ser
->at_resp
= hd_shm_add_str_list(hd_data
, ser
->at_resp
);
5370 hd_udevinfo_t
*hd_free_udevinfo(hd_udevinfo_t
*ui
)
5372 hd_udevinfo_t
*next
;
5374 for(; ui
; ui
= next
) {
5377 free_mem(ui
->sysfs
);
5379 free_str_list(ui
->links
);
5388 void read_udevinfo(hd_data_t
*hd_data
)
5390 str_list_t
*sl
, *udevinfo
, *sl0
, *sl1
, *dir_list
;
5391 hd_udevinfo_t
**uip
, *ui
;
5397 if((dir_list
= read_dir("/dev/.udevdb", 'r'))) {
5400 for(sl
= dir_list
; sl
; sl
= sl
->next
) {
5401 str_printf(&s
, 0, "/dev/.udevdb/%s", sl
->str
);
5402 sl0
= read_file(s
, 0, 0);
5406 while(sl0
->next
) sl0
= sl0
->next
;
5412 free_str_list(dir_list
);
5415 udevinfo
= read_file("| " PROG_UDEVINFO
" -d 2>/dev/null", 0, 0);
5418 ADD2LOG("----- udevinfo -----\n");
5419 for(sl
= udevinfo
; sl
; sl
= sl
->next
) {
5420 ADD2LOG(" %s", sl
->str
);
5422 ADD2LOG("----- udevinfo end -----\n");
5424 hd_data
->udevinfo
= hd_free_udevinfo(hd_data
->udevinfo
);
5426 uip
= &hd_data
->udevinfo
;
5428 for(ui
= NULL
, sl
= udevinfo
; sl
; sl
= sl
->next
) {
5429 if(sscanf(sl
->str
, "P: %255s", buf
) == 1) {
5430 ui
= *uip
= new_mem(sizeof **uip
);
5431 uip
= &(*uip
)->next
;
5432 ui
->sysfs
= new_str(buf
);
5437 if(sscanf(sl
->str
, "T: %255s", buf
) == 1) {
5443 if(sscanf(sl
->str
, "N: %255s", buf
) == 1) {
5445 ui
->name
= new_str(buf
);
5450 if(!strncmp(sl
->str
, "S:", 2)) {
5452 while(*s
== ' ') s
++;
5454 while(l
> 0 && isspace(s
[l
-1])) s
[--l
] = 0;
5456 sl0
= hd_split(' ', s
);
5457 for(sl1
= sl0
; sl1
; sl1
= sl1
->next
) {
5458 add_str_list(&ui
->links
, sl1
->str
);
5467 for(ui
= hd_data
->udevinfo
; ui
; ui
= ui
->next
) {
5468 ADD2LOG("%s\n", ui
->sysfs
);
5469 if(ui
->name
) ADD2LOG(" name: %s\n", ui
->name
);
5471 s
= hd_join(", ", ui
->links
);
5472 ADD2LOG(" links: %s\n", s
);
5477 free_str_list(udevinfo
);
5482 * Return libhd version.
5486 return HD_VERSION_STRING
;
5490 hd_t
*hd_find_sysfs_id(hd_data_t
*hd_data
, char *id
)
5495 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
5496 if(hd
->sysfs_id
&& !strcmp(hd
->sysfs_id
, id
)) return hd
;
5504 hd_sysfsdrv_t
*hd_free_sysfsdrv(hd_sysfsdrv_t
*sf
)
5506 hd_sysfsdrv_t
*next
;
5508 for(; sf
; sf
= next
) {
5511 free_mem(sf
->driver
);
5512 free_mem(sf
->device
);
5521 void hd_sysfs_driver_list(hd_data_t
*hd_data
)
5524 hd_sysfsdrv_t
**sfp
, *sf
;
5525 str_list_t
*sl
, *sl0
;
5528 struct sysfs_bus
*sf_bus
;
5529 struct sysfs_driver
*sf_drv
;
5530 struct sysfs_device
*sf_dev
;
5532 struct dlist
*sf_subsys
;
5533 struct dlist
*sf_drv_list
;
5534 struct dlist
*sf_dev_list
;
5537 for(sl
= sl0
= read_file(PROC_MODULES
, 0, 0); sl
; sl
= sl
->next
) {
5538 crc64(&id
, sl
->str
, strlen(sl
->str
) + 1);
5542 if(id
!= hd_data
->sysfsdrv_id
) {
5543 hd_data
->sysfsdrv
= hd_free_sysfsdrv(hd_data
->sysfsdrv
);
5546 if(hd_data
->sysfsdrv
) return;
5548 hd_data
->sysfsdrv_id
= id
;
5550 sfp
= &hd_data
->sysfsdrv
;
5552 ADD2LOG("----- sysfs driver list (id 0x%016"PRIx64
") -----\n", id
);
5554 sf_subsys
= sysfs_open_subsystem_list("bus");
5556 if(sf_subsys
) dlist_for_each_data(sf_subsys
, bus
, char) {
5557 sf_bus
= sysfs_open_bus(bus
);
5560 sf_drv_list
= sysfs_get_bus_drivers(sf_bus
);
5561 if(sf_drv_list
) dlist_for_each_data(sf_drv_list
, sf_drv
, struct sysfs_driver
) {
5562 sf_dev_list
= sysfs_get_driver_devices(sf_drv
);
5563 if(sf_dev_list
) dlist_for_each_data(sf_dev_list
, sf_dev
, struct sysfs_device
) {
5564 sf
= *sfp
= new_mem(sizeof **sfp
);
5565 sfp
= &(*sfp
)->next
;
5566 sf
->driver
= new_str(sf_drv
->name
);
5567 sf
->device
= new_str(hd_sysfs_id(sf_dev
->path
));
5568 ADD2LOG("%16s: %s\n", sf
->driver
, sf
->device
);
5572 sysfs_close_bus(sf_bus
);
5576 sysfs_close_list(sf_subsys
);
5578 ADD2LOG("----- sysfs driver list end -----\n");
5582 int hd_report_this(hd_data_t
*hd_data
, hd_t
*hd
)
5584 if(!hd_data
->only
) return 1;
5586 if(search_str_list(hd_data
->only
, hd
->sysfs_id
)) return 1;
5588 return search_str_list(hd_data
->only
, hd
->unix_dev_name
) ? 1 : 0;
5592 str_list_t
*hd_module_list(hd_data_t
*hd_data
, unsigned id
)
5595 str_list_t
*drivers
= NULL
, *sl
;
5598 hd
= new_mem(sizeof *hd
);
5601 hd
->vendor
.id
= MAKE_ID(TAG_SPECIAL
, 0xf000);
5602 hd
->device
.id
= MAKE_ID(TAG_SPECIAL
, id
);
5604 hddb_add_info(hd_data
, hd
);
5606 for(di
= hd
->driver_info
; di
; di
= di
->next
) {
5607 if(di
->any
.type
== di_module
&& di
->module
.modprobe
) {
5608 for(sl
= di
->module
.names
; sl
; sl
= sl
->next
) {
5609 add_str_list(&drivers
, sl
->str
);
5614 hd_free_hd_list(hd
);
5621 * Read using mmap().
5623 int hd_read_mmap(hd_data_t
*hd_data
, char *name
, unsigned char *buf
, off_t start
, unsigned size
)
5625 off_t map_start
, xofs
;
5626 int psize
= getpagesize(), fd
;
5631 if(!size
|| !name
) return 0;
5633 memset(buf
, 0, size
);
5635 map_start
= start
& -psize
;
5636 xofs
= start
- map_start
;
5638 map_size
= (xofs
+ size
+ psize
- 1) & -psize
;
5640 fd
= open(name
, O_RDONLY
);
5642 if(fd
== -1) return 0;
5644 if(!fstat(fd
, &sbuf
) && S_ISREG(sbuf
.st_mode
)) {
5645 if(sbuf
.st_size
< start
+ size
) {
5646 if(sbuf
.st_size
> start
) {
5647 size
= sbuf
.st_size
- start
;
5660 p
= mmap(NULL
, map_size
, PROT_READ
, MAP_PRIVATE
, fd
, map_start
);
5662 if(p
== MAP_FAILED
) {
5663 if(hd_data
) ADD2LOG(
5664 "%s[0x%x, %u]: mmap(, %u,,,, 0x%x) failed: %s\n",
5665 name
, (unsigned) start
, size
, map_size
, (unsigned) map_start
, strerror(errno
)
5670 if(hd_data
) ADD2LOG(
5671 "%s[0x%x, %u]: mmap(, %u,,,, 0x%x) ok\n",
5672 name
, (unsigned) start
, size
, map_size
, (unsigned) map_start
5675 memcpy(buf
, p
+ xofs
, size
);
5677 munmap(p
, map_size
);