]>
git.ipfire.org Git - people/trikolon/ipfire-2.x.git/blob - src/hwinfo/src/hd/misc.c
10 #include <linux/hdreg.h>
17 static void read_ioports(misc_t
*m
);
18 static void read_dmas(misc_t
*m
);
19 static void read_irqs(misc_t
*m
);
20 static int active_vga_card(hd_t
*);
22 static void dump_misc_proc_data(hd_data_t
*hd_data
);
23 static void dump_misc_data(hd_data_t
*hd_data
);
25 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
31 void hd_scan_misc(hd_data_t
*hd_data
)
37 bios_info_t
*bt
= NULL
;
38 char par
[] = "parport0";
41 if(!hd_probe_feature(hd_data
, pr_misc
)) return;
43 hd_data
->module
= mod_misc
;
46 remove_hd_entries(hd_data
);
47 hd_data
->misc
= free_misc(hd_data
->misc
);
49 PROGRESS(9, 0, "kernel log");
51 if((hd_data
->debug
& HD_DEB_MISC
)) dump_klog(hd_data
);
53 PROGRESS(1, 0, "misc data");
54 hd_data
->misc
= new_mem(sizeof *hd_data
->misc
);
56 /* this is enough to load the module */
57 fd_ser0
= fd_ser1
= -1;
59 #if !defined(__sparc__)
60 /* On sparc, the close needs too long */
61 if(hd_probe_feature(hd_data
, pr_misc_serial
)) {
62 PROGRESS(1, 1, "open serial");
63 fd_ser0
= open("/dev/ttyS0", O_RDONLY
| O_NONBLOCK
);
64 fd_ser1
= open("/dev/ttyS1", O_RDONLY
| O_NONBLOCK
);
65 /* keep the devices open until the resources have been read */
69 /* this is enough to load the module */
70 if(!hd_data
->flags
.no_parport
&& hd_probe_feature(hd_data
, pr_misc_par
)) {
71 PROGRESS(1, 2, "open parallel");
72 /* what can the BIOS tell us? */
73 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
75 hd
->base_class
.id
== bc_internal
&&
76 hd
->sub_class
.id
== sc_int_bios
&&
78 hd
->detail
->type
== hd_detail_bios
&&
83 bt
= hd
->detail
->bios
.data
;
85 str_printf(&s
, 0, "io=0x%x", bt
->par_port0
);
87 str_printf(&s
, -1, ",0x%x", bt
->par_port1
);
88 if(bt
->par_port2
) str_printf(&s
, -1, ",0x%x", bt
->par_port2
);
90 str_printf(&s
, -1, " irq=none,none,none");
92 unload_module(hd_data
, "parport_probe");
93 unload_module(hd_data
, "lp");
94 unload_module(hd_data
, "parport_pc");
95 unload_module(hd_data
, "parport");
97 /* now load it with the right io */
98 load_module(hd_data
, "parport");
99 load_module_with_params(hd_data
, "parport_pc", s
);
102 /* now load the rest of the modules */
103 fd
= open("/dev/lp0", O_RDONLY
| O_NONBLOCK
);
104 if(fd
>= 0) close(fd
);
108 * floppy driver resources are allocated only temporarily,
109 * so we access it just before we read the resources
111 if(hd_probe_feature(hd_data
, pr_misc_floppy
)) {
112 /* look for a floppy *device* entry... */
113 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
115 hd
->base_class
.id
== bc_storage_device
&&
116 hd
->sub_class
.id
== sc_sdev_floppy
&&
118 !strncmp(hd
->unix_dev_name
, "/dev/fd", sizeof "/dev/fd" - 1)
121 PROGRESS(1, 3, "read floppy");
123 hd
->block0
= read_block0(hd_data
, hd
->unix_dev_name
, &i
);
124 hd
->is
.notready
= hd
->block0
? 0 : 1;
127 ADD2LOG("misc.floppy: removing floppy entry %u (timed out)\n", hd
->idx
);
130 if(!hd
->is
.notready
) {
131 struct hd_geometry geo
;
133 unsigned size
, blk_size
= 0x200;
135 fd
= open(hd
->unix_dev_name
, O_RDONLY
| O_NONBLOCK
);
137 if(!ioctl(fd
, HDIO_GETGEO
, &geo
)) {
138 ADD2LOG("floppy ioctl(geo) ok\n");
139 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
140 res
->disk_geo
.type
= res_disk_geo
;
141 res
->disk_geo
.cyls
= geo
.cylinders
;
142 res
->disk_geo
.heads
= geo
.heads
;
143 res
->disk_geo
.sectors
= geo
.sectors
;
144 res
->disk_geo
.geotype
= geo_logical
;
145 size
= geo
.cylinders
* geo
.heads
* geo
.sectors
;
146 for(res
= hd
->res
; res
; res
= res
->next
) {
147 if(res
->any
.type
== res_size
&& res
->size
.unit
== size_unit_sectors
) {
148 res
->size
.val1
= size
; res
->size
.val2
= blk_size
;
153 res
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
154 res
->size
.type
= res_size
;
155 res
->size
.unit
= size_unit_sectors
;
156 res
->size
.val1
= size
; res
->size
.val2
= blk_size
;
166 remove_tagged_hd_entries(hd_data
);
169 PROGRESS(2, 1, "io");
170 read_ioports(hd_data
->misc
);
172 PROGRESS(2, 2, "dma");
173 read_dmas(hd_data
->misc
);
175 PROGRESS(2, 3, "irq");
176 read_irqs(hd_data
->misc
);
178 if((hd_data
->debug
& HD_DEB_MISC
)) dump_misc_proc_data(hd_data
);
180 if(fd_ser0
>= 0) close(fd_ser0
);
181 if(fd_ser1
>= 0) close(fd_ser1
);
183 /* now create some system generic entries */
186 PROGRESS(3, 0, "FPU");
188 gather_resources(hd_data
->misc
, &res
, "fpu", 0);
190 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
191 hd
->base_class
.id
= bc_internal
;
192 hd
->sub_class
.id
= sc_int_fpu
;
197 PROGRESS(3, 1, "DMA");
199 gather_resources(hd_data
->misc
, &res
, "dma1", 0);
200 gather_resources(hd_data
->misc
, &res
, "dma2", 0);
201 gather_resources(hd_data
->misc
, &res
, "dma page reg", 0);
202 gather_resources(hd_data
->misc
, &res
, "cascade", W_DMA
);
204 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
205 hd
->base_class
.id
= bc_system
;
206 hd
->sub_class
.id
= sc_sys_dma
;
211 PROGRESS(3, 2, "PIC");
213 gather_resources(hd_data
->misc
, &res
, "pic1", 0);
214 gather_resources(hd_data
->misc
, &res
, "pic2", 0);
215 gather_resources(hd_data
->misc
, &res
, "cascade", W_IRQ
);
217 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
218 hd
->base_class
.id
= bc_system
;
219 hd
->sub_class
.id
= sc_sys_pic
;
224 PROGRESS(3, 3, "timer");
226 gather_resources(hd_data
->misc
, &res
, "timer", 0);
228 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
229 hd
->base_class
.id
= bc_system
;
230 hd
->sub_class
.id
= sc_sys_timer
;
234 /* real time clock */
235 PROGRESS(3, 4, "RTC");
237 gather_resources(hd_data
->misc
, &res
, "rtc", 0);
239 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
240 hd
->base_class
.id
= bc_system
;
241 hd
->sub_class
.id
= sc_sys_rtc
;
247 gather_resources(hd_data
->misc
, &res
, "keyboard", 0);
249 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
250 hd
->base_class
.id
= bc_input
;
251 hd
->sub_class
.id
= sc_inp_keyb
;
256 for(i
= 0; i
< 1; i
++, par
[sizeof par
- 2]++) {
258 gather_resources(hd_data
->misc
, &res
, par
, 0);
260 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
261 hd
->base_class
.id
= bc_comm
;
262 hd
->sub_class
.id
= sc_com_par
;
263 str_printf(&hd
->unix_dev_name
, 0, "/dev/lp%d", i
);
268 /* floppy controller */
270 gather_resources(hd_data
->misc
, &res
, "floppy", 0);
271 gather_resources(hd_data
->misc
, &res
, "floppy DIR", 0);
273 /* look for an existing entry */
274 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
275 if(hd
->base_class
.id
== bc_storage
&& hd
->sub_class
.id
== sc_sto_floppy
) break;
278 /* missing, so create one */
280 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
281 hd
->base_class
.id
= bc_storage
;
282 hd
->sub_class
.id
= sc_sto_floppy
;
291 * The catch is, that sometimes /dev/psaux is accessible only for root,
292 * so the open() may fail but there are irq events registered.
295 fd
= open(DEV_PSAUX
, O_RDONLY
| O_NONBLOCK
);
296 if(fd
>= 0) close(fd
);
299 gather_resources(hd_data
->misc
, &res
, "PS/2 Mouse", 0);
302 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
303 hd
->base_class
.id
= bc_ps2
;
312 void hd_scan_misc2(hd_data_t
*hd_data
)
316 hd_res_t
*res
, *res1
, *res2
;
319 if(!hd_probe_feature(hd_data
, pr_misc
)) return;
321 hd_data
->module
= mod_misc
;
323 PROGRESS(5, 0, "misc data");
325 /* create some more system generic entries */
329 // ###### add special ide detail to hd_t!!!
331 gather_resources(hd_data
->misc
, &res
, "ide0", 0);
332 gather_resources(hd_data
->misc
, &res
, "ide1", 0);
333 gather_resources(hd_data
->misc
, &res
, "ide2", 0);
334 gather_resources(hd_data
->misc
, &res
, "ide3", 0);
336 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
338 hd
->base_class
.id
== bc_storage
&&
339 hd
->sub_class
.id
== sc_sto_ide
&&
340 have_common_res(hd
->res
, res
)
344 /* eg. non-PCI IDE controller */
345 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
346 hd
->base_class
.id
= bc_storage
;
347 hd
->sub_class
.id
= sc_sto_ide
;
348 /* use join_res to join the i/o ranges of ide0/1 */
349 join_res_io(&hd
->res
, res
);
350 join_res_irq(&hd
->res
, res
);
351 join_res_dma(&hd
->res
, res
);
355 /* eg. PCI IDE controller, add resources */
356 join_res_io(&hd
->res
, res
);
357 join_res_irq(&hd
->res
, res
);
358 join_res_dma(&hd
->res
, res
);
365 gather_resources(hd_data
->misc
, &res
, "vga+", 0);
366 gather_resources(hd_data
->misc
, &res
, "vesafb", 0);
368 for(i
= 0, hd1
= NULL
, hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
369 if(hd
->base_class
.id
== bc_display
&& hd
->sub_class
.id
== sc_dis_vga
) {
375 /* non-PCI VGA card ??? - really, we shouldn't care... */
376 /* FIX THIS !!! ############### */
380 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
381 hd
->base_class
.id
= bc_display
;
382 hd
->sub_class
.id
= sc_dis_vga
;
387 /* 1 PCI vga card, add resources */
388 join_res_io(&hd1
->res
, res
);
389 join_res_irq(&hd1
->res
, res
);
390 join_res_dma(&hd1
->res
, res
);
392 hd_data
->display
= hd1
->idx
;
395 /* more than 1: look again, now only 'active' cards */
396 for(i
= 0, hd1
= NULL
, hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
398 hd
->base_class
.id
== bc_display
&&
399 hd
->sub_class
.id
== sc_dis_vga
&&
407 /* 'the' active PCI vga card, add resources */
408 join_res_io(&hd1
->res
, res
);
409 join_res_irq(&hd1
->res
, res
);
410 join_res_dma(&hd1
->res
, res
);
411 hd_data
->display
= hd1
->idx
;
415 ADD2LOG("Oopy, could not figure out *the* active display adapter!\n");
423 gather_resources(hd_data
->misc
, &res
, "serial(auto)", 0);
424 gather_resources(hd_data
->misc
, &res
, "serial(set)", 0);
425 gather_resources(hd_data
->misc
, &res
, "serial", 0);
426 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
427 if(hd
->base_class
.id
== bc_comm
&& hd
->sub_class
.id
== sc_com_ser
) {
428 for(res1
= hd
->res
; res1
; res1
= res1
->next
) {
429 for(res2
= res
; res2
; res2
= res2
->next
) {
430 if(res1
->any
.type
== res2
->any
.type
) {
431 switch(res1
->any
.type
) {
433 if(res1
->irq
.base
== res2
->irq
.base
) {
434 res2
->any
.type
= res_any
;
439 res1
->io
.base
== res2
->io
.base
&&
440 (!res1
->io
.range
|| res1
->io
.range
== res2
->io
.range
)
442 res1
->io
.range
= res2
->io
.range
;
443 res2
->any
.type
= res_any
;
446 default: /* gcc -Wall */
455 /* if any of the serial resources are unaccounted for, make an extra entry */
456 for(res2
= res
; res2
; res2
= res2
->next
) {
457 if(res2
->any
.type
!= res_any
) {
458 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
459 hd
->base_class
.id
= bc_comm
;
460 hd
->sub_class
.id
= sc_com_ser
;
461 hd
->prog_if
.id
= 0x80;
462 for(; res2
; res2
= res2
->next
) {
463 if(res2
->any
.type
!= res_any
) {
464 res1
= add_res_entry(&hd
->res
, new_mem(sizeof *res
));
474 /* go through our list and assign event counts to irq entries */
476 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
477 for(res
= hd
->res
; res
; res
= res
->next
) {
478 if(res
->irq
.type
== res_irq
) {
479 for(i
= 0; (unsigned) i
< m
->irq_len
; i
++) {
480 if(res
->irq
.base
== m
->irq
[i
].irq
) {
481 res
->irq
.triggered
= m
->irq
[i
].events
;
489 /* look for entries with matching start address */
491 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
492 for(res
= hd
->res
; res
; res
= res
->next
) {
493 if(res
->io
.type
== res_io
) {
494 for(i
= 0; (unsigned) i
< m
->io_len
; i
++) {
495 if(res
->io
.base
== m
->io
[i
].addr
&& res
->io
.range
< m
->io
[i
].size
) {
496 res
->io
.range
= m
->io
[i
].size
;
504 if((hd_data
->debug
& HD_DEB_MISC
)) dump_misc_data(hd_data
);
511 void read_ioports(misc_t
*m
)
518 if(!(m
->proc_io
= read_file(PROC_IOPORTS
, 0, 0))) return;
520 for(sl
= m
->proc_io
; sl
; sl
= sl
->next
) {
521 if(sscanf(sl
->str
, " %"PRIx64
" - %"PRIx64
" : %99[^\n]", &u
, &v
, buf
) == 3) {
522 m
->io
= add_mem(m
->io
, sizeof *m
->io
, m
->io_len
);
523 r
= m
->io
+ m
->io_len
++;
525 r
->size
= v
>= u
? v
- u
+ 1 : 0;
526 r
->dev
= new_str(buf
);
534 void read_dmas(misc_t
*m
)
541 if(!(m
->proc_dma
= read_file(PROC_DMA
, 0, 0))) return;
543 for(sl
= m
->proc_dma
; sl
; sl
= sl
->next
) {
544 if(sscanf(sl
->str
, " %u : %99[^\n]", &u
, buf
) == 2) {
545 m
->dma
= add_mem(m
->dma
, sizeof *m
->dma
, m
->dma_len
);
546 d
= m
->dma
+ m
->dma_len
++;
548 d
->dev
= new_str(buf
);
555 * read /proc/interrupts
557 * This is somewhat more tricky, as the irq event counts are done separately
558 * per cpu *and* there may be irq sharing.
560 void read_irqs(misc_t
*m
)
562 char buf
[100], buf2
[100], *s
;
568 if(!(m
->proc_irq
= read_file(PROC_INTERRUPTS
, 1, 0))) return;
570 for(sl
= m
->proc_irq
; sl
; sl
= sl
->next
) {
573 if(sscanf(sl
->str
, " %u: %n", &u
, &i
) < 1) continue;
576 /* add up all event counters */
577 while(j
< (int) strlen(sl
->str
) && sscanf(sl
->str
+ j
, " %u %n", &k
, &i
) >= 1) {
582 /* device driver name string */
585 sscanf(sl
->str
+ j
, " %*s Edge %99[^\n]", buf
) == 1 ||
586 sscanf(sl
->str
+ j
, " %*s Level %99[^\n]", buf
) == 1 ||
587 sscanf(sl
->str
+ j
, " %*s %99[^\n]", buf
) == 1
590 #if defined(__alpha__) || defined(__sparc__)
591 if(sscanf(sl
->str
+ j
, " %99[^\n]", buf
) == 1) {
592 #else /* __i386__ || __x86_64__ || __ia64__ */
593 if(sscanf(sl
->str
+ j
, " %*s %99[^\n]", buf
) == 1) {
596 m
->irq
= add_mem(m
->irq
, sizeof *m
->irq
, m
->irq_len
);
597 ir
= m
->irq
+ m
->irq_len
++;
601 /* split device driver names (separated by ',') */
603 while(*s
&& sscanf(s
, " %99[^,] %n", buf2
, &j
) >= 1) {
604 ir
->dev
= add_mem(ir
->dev
, sizeof *ir
->dev
, ir
->devs
);
605 ir
->dev
[ir
->devs
++] = new_str(buf2
);
607 if(*s
) s
++; /* skip ',' */
613 void gather_resources(misc_t
*m
, hd_res_t
**r
, char *name
, unsigned which
)
620 if(!which
) which
= W_IO
| W_DMA
| W_IRQ
;
622 if((which
& W_IO
)) for(i
= 0; (unsigned) i
< m
->io_len
; i
++) {
623 if(!strcmp(name
, m
->io
[i
].dev
)) {
624 res
= add_res_entry(r
, new_mem(sizeof **r
));
625 res
->io
.type
= res_io
;
627 res
->io
.base
= m
->io
[i
].addr
;
628 res
->io
.range
= m
->io
[i
].size
;
629 res
->io
.access
= acc_rw
;
634 if((which
& W_DMA
)) for(i
= 0; (unsigned) i
< m
->dma_len
; i
++) {
635 if(!strcmp(name
, m
->dma
[i
].dev
)) {
636 res
= add_res_entry(r
, new_mem(sizeof **r
));
637 res
->dma
.type
= res_dma
;
638 res
->dma
.enabled
= 1;
639 res
->dma
.base
= m
->dma
[i
].channel
;
644 if((which
& W_IRQ
)) for(i
= 0; (unsigned) i
< m
->irq_len
; i
++) {
645 for(j
= 0; j
< m
->irq
[i
].devs
; j
++) {
646 if(!strcmp(name
, m
->irq
[i
].dev
[j
])) {
647 res
= add_res_entry(r
, new_mem(sizeof **r
));
648 res
->irq
.type
= res_irq
;
649 res
->irq
.enabled
= 1;
650 res
->irq
.base
= m
->irq
[i
].irq
;
651 res
->irq
.triggered
= m
->irq
[i
].events
;
659 int active_vga_card(hd_t
*hd
)
663 if(hd
->bus
.id
!= bus_pci
) return 1;
665 for(res
= hd
->res
; res
; res
= res
->next
) {
667 (res
->mem
.type
== res_mem
&& res
->mem
.enabled
) ||
668 (res
->io
.type
== res_io
&& res
->io
.enabled
)
677 * Add some proc info to the global log.
679 void dump_misc_proc_data(hd_data_t
*hd_data
)
683 ADD2LOG("----- /proc/ioports -----\n");
684 for(sl
= hd_data
->misc
->proc_io
; sl
; sl
= sl
->next
) {
685 ADD2LOG(" %s", sl
->str
);
687 ADD2LOG("----- /proc/ioports end -----\n");
689 ADD2LOG("----- /proc/interrupts -----\n");
690 for(sl
= hd_data
->misc
->proc_irq
; sl
; sl
= sl
->next
) {
691 ADD2LOG(" %s", sl
->str
);
693 ADD2LOG("----- /proc/interrupts end -----\n");
695 ADD2LOG("----- /proc/dma -----\n");
696 for(sl
= hd_data
->misc
->proc_dma
; sl
; sl
= sl
->next
) {
697 ADD2LOG(" %s", sl
->str
);
699 ADD2LOG("----- /proc/dma end -----\n");
705 * Add the resource usage to the global log.
707 void dump_misc_data(hd_data_t
*hd_data
)
709 misc_t
*m
= hd_data
->misc
;
712 ADD2LOG("----- misc resources -----\n");
714 for(i
= 0; (unsigned) i
< m
->io_len
; i
++) {
716 "i/o:%u 0x%04"PRIx64
" - 0x%04"PRIx64
" (0x%02"PRIx64
") \"%s\"\n",
718 m
->io
[i
].addr
, m
->io
[i
].addr
+ m
->io
[i
].size
- 1,
719 m
->io
[i
].size
, m
->io
[i
].dev
723 for(i
= 0; (unsigned) i
< m
->irq_len
; i
++) {
726 m
->irq
[i
].tag
, m
->irq
[i
].irq
, m
->irq
[i
].events
728 for(j
= 0; j
< m
->irq
[i
].devs
; j
++) {
729 ADD2LOG(" \"%s\"", m
->irq
[i
].dev
[j
]);
734 for(i
= 0; (unsigned) i
< m
->dma_len
; i
++) {
736 "dma:%u %u \"%s\"\n",
737 m
->dma
[i
].tag
, m
->dma
[i
].channel
, m
->dma
[i
].dev
741 ADD2LOG("----- misc resources end -----\n");