1#include <linux/config.h>
2#include <linux/types.h>
3#include <linux/kernel.h>
4#include <linux/string.h>
5#include <linux/init.h>
6#include <linux/apm_bios.h>
7#include <linux/slab.h>
8#include <asm/io.h>
9#include <linux/pm.h>
10#include <asm/keyboard.h>
11#include <asm/system.h>
12#include <linux/bootmem.h>
13
14#include "pci-i386.h"
15
16unsigned long dmi_broken;
17int is_sony_vaio_laptop;
18
19struct dmi_header
20{
21 u8 type;
22 u8 length;
23 u16 handle;
24};
25
26#define dmi_printk(x)
27
28
29static char * __init dmi_string(struct dmi_header *dm, u8 s)
30{
31 u8 *bp=(u8 *)dm;
32 bp+=dm->length;
33 if(!s)
34 return "";
35 s--;
36 while(s>0 && *bp)
37 {
38 bp+=strlen(bp);
39 bp++;
40 s--;
41 }
42 return bp;
43}
44
45
46
47
48
49
50static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
51{
52 u8 *buf;
53 struct dmi_header *dm;
54 u8 *data;
55 int i=0;
56
57 buf = bt_ioremap(base, len);
58 if(buf==NULL)
59 return -1;
60
61 data = buf;
62
63
64
65
66
67
68 while(i<num && data-buf+sizeof(struct dmi_header)<=len)
69 {
70 dm=(struct dmi_header *)data;
71
72
73
74
75
76 data+=dm->length;
77 while(data-buf<len-1 && (data[0] || data[1]))
78 data++;
79 if(data-buf<len-1)
80 decode(dm);
81 data+=2;
82 i++;
83 }
84 bt_iounmap(buf, len);
85 return 0;
86}
87
88
89inline static int __init dmi_checksum(u8 *buf)
90{
91 u8 sum=0;
92 int a;
93
94 for(a=0; a<15; a++)
95 sum+=buf[a];
96 return (sum==0);
97}
98
99static int __init dmi_iterate(void (*decode)(struct dmi_header *))
100{
101 u8 buf[15];
102 u32 fp=0xF0000;
103
104 while( fp < 0xFFFFF)
105 {
106 isa_memcpy_fromio(buf, fp, 15);
107 if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
108 {
109 u16 num=buf[13]<<8|buf[12];
110 u16 len=buf[7]<<8|buf[6];
111 u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
112
113
114
115
116
117 if(buf[14]!=0)
118 dmi_printk((KERN_INFO "DMI %d.%d present.\n",
119 buf[14]>>4, buf[14]&0x0F));
120 else
121 dmi_printk((KERN_INFO "DMI present.\n"));
122 dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
123 num, len));
124 dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
125 base));
126 if(dmi_table(base,len, num, decode)==0)
127 return 0;
128 }
129 fp+=16;
130 }
131 return -1;
132}
133
134
135enum
136{
137 DMI_BIOS_VENDOR,
138 DMI_BIOS_VERSION,
139 DMI_BIOS_DATE,
140 DMI_SYS_VENDOR,
141 DMI_PRODUCT_NAME,
142 DMI_PRODUCT_VERSION,
143 DMI_BOARD_VENDOR,
144 DMI_BOARD_NAME,
145 DMI_BOARD_VERSION,
146 DMI_STRING_MAX
147};
148
149static char *dmi_ident[DMI_STRING_MAX];
150
151
152
153
154
155static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
156{
157 char *d = (char*)dm;
158 char *p = dmi_string(dm, d[string]);
159 if(p==NULL || *p == 0)
160 return;
161 if (dmi_ident[slot])
162 return;
163 dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
164 if(dmi_ident[slot])
165 strcpy(dmi_ident[slot], p);
166 else
167 printk(KERN_ERR "dmi_save_ident: out of memory.\n");
168}
169
170
171
172
173
174struct dmi_strmatch
175{
176 u8 slot;
177 char *substr;
178};
179
180#define NONE 255
181
182struct dmi_blacklist
183{
184 int (*callback)(struct dmi_blacklist *);
185 char *ident;
186 struct dmi_strmatch matches[4];
187};
188
189#define NO_MATCH { NONE, NULL}
190#define MATCH(a,b) { a, b }
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220static __init int set_bios_reboot(struct dmi_blacklist *d)
221{
222 extern int reboot_thru_bios;
223 if (reboot_thru_bios == 0)
224 {
225 reboot_thru_bios = 1;
226 printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
227 }
228 return 0;
229}
230
231
232
233
234static __init int set_smp_reboot(struct dmi_blacklist *d)
235{
236#ifdef CONFIG_SMP
237 extern int reboot_smp;
238 if (reboot_smp == 0)
239 {
240 reboot_smp = 1;
241 printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
242 }
243#endif
244 return 0;
245}
246
247
248
249
250static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
251{
252 set_smp_reboot(d);
253 set_bios_reboot(d);
254 return 0;
255}
256
257
258
259
260
261static __init int set_realmode_power_off(struct dmi_blacklist *d)
262{
263 if (apm_info.realmode_power_off == 0)
264 {
265 apm_info.realmode_power_off = 1;
266 printk(KERN_INFO "%s bios detected. Using realmode poweroff only.\n", d->ident);
267 }
268 return 0;
269}
270
271
272
273
274
275
276static __init int set_apm_ints(struct dmi_blacklist *d)
277{
278 if (apm_info.allow_ints == 0)
279 {
280 apm_info.allow_ints = 1;
281 printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.\n", d->ident);
282 }
283 return 0;
284}
285
286
287
288
289
290static __init int apm_is_horked(struct dmi_blacklist *d)
291{
292 if (apm_info.disabled == 0)
293 {
294 apm_info.disabled = 1;
295 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
296 }
297 return 0;
298}
299
300
301
302
303
304
305
306static int __init local_apic_kills_bios(struct dmi_blacklist *d)
307{
308#ifdef CONFIG_X86_LOCAL_APIC
309 extern int dont_enable_local_apic;
310 if (!dont_enable_local_apic) {
311 dont_enable_local_apic = 1;
312 printk(KERN_WARNING "%s with broken BIOS detected. "
313 "Refusing to enable the local APIC.\n",
314 d->ident);
315 }
316#endif
317 return 0;
318}
319
320
321
322
323
324
325static int __init apm_kills_local_apic(struct dmi_blacklist *d)
326{
327#ifdef CONFIG_X86_LOCAL_APIC
328 extern int dont_enable_local_apic;
329 if (apm_info.bios.version && !dont_enable_local_apic) {
330 dont_enable_local_apic = 1;
331 printk(KERN_WARNING "%s with broken BIOS detected. "
332 "Refusing to enable the local APIC.\n",
333 d->ident);
334 }
335#endif
336 return 0;
337}
338
339
340
341
342
343static int __init apm_kills_local_apic_timer(struct dmi_blacklist *d)
344{
345#ifdef CONFIG_X86_LOCAL_APIC
346 extern int dont_use_local_apic_timer;
347 if (apm_info.bios.version && !dont_use_local_apic_timer) {
348 dont_use_local_apic_timer = 1;
349 printk(KERN_WARNING "%s with broken BIOS detected. "
350 "The local APIC timer will not be used.\n",
351 d->ident);
352 }
353#endif
354 return 0;
355}
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373static __init int broken_apm_power(struct dmi_blacklist *d)
374{
375 apm_info.get_power_status_broken = 1;
376 printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
377 return 0;
378}
379
380
381
382
383
384
385
386
387
388static __init int sony_vaio_laptop(struct dmi_blacklist *d)
389{
390 if (is_sony_vaio_laptop == 0)
391 {
392 is_sony_vaio_laptop = 1;
393 printk(KERN_INFO "%s laptop detected.\n", d->ident);
394 }
395 return 0;
396}
397
398
399
400
401
402
403static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
404{
405 apm_info.get_power_status_swabinminutes = 1;
406 printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
407 return 0;
408}
409
410
411
412
413
414
415
416
417extern int skip_ioapic_setup;
418extern int broken_440gx_bios;
419extern unsigned int pci_probe;
420static __init int broken_pirq(struct dmi_blacklist *d)
421{
422 printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)\n");
423 printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.\n");
424 printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at boot\n");
425 printk(KERN_INFO " *** contact your hardware vendor and ask about updates.\n");
426 printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.\n");
427#ifdef CONFIG_X86_IO_APIC
428 skip_ioapic_setup = 0;
429#endif
430#ifdef CONFIG_PCI
431 broken_440gx_bios = 1;
432 pci_probe |= PCI_BIOS_IRQ_SCAN;
433#endif
434
435 return 0;
436}
437
438
439
440
441
442static __init int init_ints_after_s1(struct dmi_blacklist *d)
443{
444 printk(KERN_WARNING "Toshiba with broken S1 detected.\n");
445 dmi_broken |= BROKEN_INIT_AFTER_S1;
446 return 0;
447}
448
449
450
451
452
453
454typedef void (pm_kbd_func) (void);
455
456static __init int broken_ps2_resume(struct dmi_blacklist *d)
457{
458#ifdef CONFIG_VT
459 if (pm_kbd_request_override == NULL)
460 {
461 pm_kbd_request_override = pckbd_pm_resume;
462 printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.\n", d->ident);
463 }
464#endif
465 return 0;
466}
467
468
469
470
471
472static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
473{
474#ifdef CONFIG_PCI
475 extern int broken_hp_bios_irq9;
476 if (broken_hp_bios_irq9 == 0)
477 {
478 broken_hp_bios_irq9 = 1;
479 printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
480 }
481#endif
482 return 0;
483}
484
485
486
487
488
489static __init int print_if_true(struct dmi_blacklist *d)
490{
491 printk("%s\n", d->ident);
492 return 0;
493}
494
495
496
497
498
499
500
501
502
503
504
505static __initdata struct dmi_blacklist dmi_blacklist[]={
506#if 0
507 { disable_ide_dma, "KT7", {
508 MATCH(DMI_PRODUCT_NAME, "KT7-RAID"),
509 NO_MATCH, NO_MATCH, NO_MATCH
510 } },
511#endif
512 { broken_ps2_resume, "Dell Latitude C600", {
513 MATCH(DMI_SYS_VENDOR, "Dell"),
514 MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
515 NO_MATCH, NO_MATCH
516 } },
517 { broken_apm_power, "Dell Inspiron 5000e", {
518 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
519 MATCH(DMI_BIOS_VERSION, "A04"),
520 MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
521 } },
522 { broken_apm_power, "Dell Inspiron 2500", {
523 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
524 MATCH(DMI_BIOS_VERSION, "A12"),
525 MATCH(DMI_BIOS_DATE, "02/04/2002"), NO_MATCH
526 } },
527 { set_realmode_power_off, "Award Software v4.60 PGMA", {
528 MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
529 MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
530 MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
531 } },
532 { set_smp_bios_reboot, "Dell PowerEdge 1300", {
533 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
534 MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
535 NO_MATCH, NO_MATCH
536 } },
537 { set_bios_reboot, "Dell PowerEdge 300", {
538 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
539 MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
540 NO_MATCH, NO_MATCH
541 } },
542 { set_bios_reboot, "Dell PowerEdge 2400", {
543 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
544 MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
545 NO_MATCH, NO_MATCH
546 } },
547 { set_apm_ints, "Dell Inspiron", {
548 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
549 MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
550 NO_MATCH, NO_MATCH
551 } },
552 { set_apm_ints, "Compaq 12XL125", {
553 MATCH(DMI_SYS_VENDOR, "Compaq"),
554 MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
555 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
556 MATCH(DMI_BIOS_VERSION,"4.06")
557 } },
558 { set_apm_ints, "ASUSTeK", {
559 MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
560 MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
561 NO_MATCH, NO_MATCH
562 } },
563 { apm_is_horked, "Trigem Delhi3", {
564 MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
565 MATCH(DMI_PRODUCT_NAME, "Delhi3"),
566 NO_MATCH, NO_MATCH,
567 } },
568 { apm_is_horked, "Fujitsu-Siemens", {
569 MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
570 MATCH(DMI_BIOS_VERSION, "Version1.01"),
571 NO_MATCH, NO_MATCH,
572 } },
573 { apm_is_horked, "Intel D850MD", {
574 MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
575 MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"),
576 NO_MATCH, NO_MATCH,
577 } },
578 { apm_is_horked, "Intel D810EMO", {
579 MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
580 MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"),
581 NO_MATCH, NO_MATCH,
582 } },
583 { apm_is_horked, "Dell XPS-Z", {
584 MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
585 MATCH(DMI_BIOS_VERSION, "A11"),
586 MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
587 NO_MATCH,
588 } },
589 { apm_is_horked, "Sharp PC-PJ/AX", {
590 MATCH(DMI_SYS_VENDOR, "SHARP"),
591 MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
592 MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
593 MATCH(DMI_BIOS_VERSION,"Version R2.08")
594 } },
595 { apm_is_horked, "Dell Inspiron 2500", {
596 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
597 MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
598 MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
599 MATCH(DMI_BIOS_VERSION,"A11")
600 } },
601 { sony_vaio_laptop, "Sony Vaio", {
602 MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
603 MATCH(DMI_PRODUCT_NAME, "PCG-"),
604 NO_MATCH, NO_MATCH,
605 } },
606 { swab_apm_power_in_minutes, "Sony VAIO", {
607 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
608 MATCH(DMI_BIOS_VERSION, "R0206H"),
609 MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
610 } },
611
612 { swab_apm_power_in_minutes, "Sony VAIO", {
613 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
614 MATCH(DMI_BIOS_VERSION, "W2K06H0"),
615 MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
616 } },
617
618 { swab_apm_power_in_minutes, "Sony VAIO", {
619 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
620 MATCH(DMI_BIOS_VERSION, "R0117A0"),
621 MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
622 } },
623
624 { swab_apm_power_in_minutes, "Sony VAIO", {
625 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
626 MATCH(DMI_BIOS_VERSION, "R0121Z1"),
627 MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
628 } },
629
630 { swab_apm_power_in_minutes, "Sony VAIO", {
631 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
632 MATCH(DMI_BIOS_VERSION, "WME01Z1"),
633 MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
634 } },
635
636 { swab_apm_power_in_minutes, "Sony VAIO", {
637 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
638 MATCH(DMI_BIOS_VERSION, "R0206Z3"),
639 MATCH(DMI_BIOS_DATE, "12/25/00"), NO_MATCH
640 } },
641
642 { swab_apm_power_in_minutes, "Sony VAIO", {
643 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
644 MATCH(DMI_BIOS_VERSION, "R0203D0"),
645 MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
646 } },
647
648 { swab_apm_power_in_minutes, "Sony VAIO", {
649 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
650 MATCH(DMI_BIOS_VERSION, "R0203Z3"),
651 MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
652 } },
653
654 { swab_apm_power_in_minutes, "Sony VAIO", {
655 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
656 MATCH(DMI_BIOS_VERSION, "R0209Z3"),
657 MATCH(DMI_BIOS_DATE, "05/12/01"), NO_MATCH
658 } },
659
660 { swab_apm_power_in_minutes, "Sony VAIO", {
661 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
662 MATCH(DMI_BIOS_VERSION, "WXP01Z3"),
663 MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH
664 } },
665
666 { swab_apm_power_in_minutes, "Sony VAIO", {
667 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
668 MATCH(DMI_BIOS_VERSION, "R0204K2"),
669 MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
670 } },
671
672 { swab_apm_power_in_minutes, "Sony VAIO", {
673 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
674 MATCH(DMI_BIOS_VERSION, "R0208P1"),
675 MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
676 } },
677 { swab_apm_power_in_minutes, "Sony VAIO", {
678 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
679 MATCH(DMI_BIOS_VERSION, "R0204P1"),
680 MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
681 } },
682
683 { swab_apm_power_in_minutes, "Sony VAIO", {
684 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
685 MATCH(DMI_BIOS_VERSION, "R0116Z1"),
686 NO_MATCH, NO_MATCH
687 } },
688
689 { swab_apm_power_in_minutes, "Sony VAIO", {
690 MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
691 MATCH(DMI_BIOS_VERSION, "RK116Z1"),
692 NO_MATCH, NO_MATCH
693 } },
694
695
696
697 { local_apic_kills_bios, "Dell Inspiron", {
698 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
699 MATCH(DMI_PRODUCT_NAME, "Inspiron"),
700 NO_MATCH, NO_MATCH
701 } },
702
703 { local_apic_kills_bios, "Dell Latitude", {
704 MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
705 MATCH(DMI_PRODUCT_NAME, "Latitude"),
706 NO_MATCH, NO_MATCH
707 } },
708
709 { local_apic_kills_bios, "IBM Thinkpad T20", {
710 MATCH(DMI_BOARD_VENDOR, "IBM"),
711 MATCH(DMI_BOARD_NAME, "264741U"),
712 NO_MATCH, NO_MATCH
713 } },
714
715 { apm_kills_local_apic, "Microstar 6163", {
716 MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
717 MATCH(DMI_BOARD_NAME, "MS-6163"),
718 NO_MATCH, NO_MATCH } },
719
720 { apm_kills_local_apic_timer, "Intel AL440LX", {
721 MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
722 MATCH(DMI_BOARD_NAME, "AL440LX"),
723 NO_MATCH, NO_MATCH } },
724
725
726
727 { broken_pirq, "SABR1 Bios", {
728 MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
729 MATCH(DMI_BIOS_VERSION,"SABR1"),
730 NO_MATCH, NO_MATCH
731 } },
732 { broken_pirq, "l44GX Bios", {
733 MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
734 MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
735 NO_MATCH, NO_MATCH
736 } },
737 { broken_pirq, "l44GX Bios", {
738 MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
739 MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0120.P12"),
740 NO_MATCH, NO_MATCH
741 } },
742 { broken_pirq, "l44GX Bios", {
743 MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
744 MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
745 NO_MATCH, NO_MATCH
746 } },
747 { broken_pirq, "l44GX Bios", {
748 MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
749 MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07.9906041405"),
750 NO_MATCH, NO_MATCH
751 } },
752
753
754
755 { broken_pirq, "Dell PowerEdge 8450", {
756 MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
757 NO_MATCH, NO_MATCH, NO_MATCH
758 } },
759
760 { init_ints_after_s1, "Toshiba Satellite 4030cdt", {
761 MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
762 NO_MATCH, NO_MATCH, NO_MATCH
763 } },
764
765 { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
766 MATCH(DMI_SYS_VENDOR, "IBM"),
767 MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
768 NO_MATCH, NO_MATCH
769 } },
770
771 { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
772 MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
773 MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
774 MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
775 MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
776 } },
777
778
779
780
781
782
783 { set_apm_ints, "IBM", {
784 MATCH(DMI_SYS_VENDOR, "IBM"),
785 NO_MATCH, NO_MATCH, NO_MATCH
786 } },
787
788 { NULL, }
789};
790
791
792
793
794
795
796
797static __init void dmi_check_blacklist(void)
798{
799 struct dmi_blacklist *d;
800 int i;
801
802 d=&dmi_blacklist[0];
803 while(d->callback)
804 {
805 for(i=0;i<4;i++)
806 {
807 int s = d->matches[i].slot;
808 if(s==NONE)
809 continue;
810 if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
811 continue;
812
813 goto fail;
814 }
815 if(d->callback(d))
816 return;
817fail:
818 d++;
819 }
820}
821
822
823
824
825
826
827
828
829
830static void __init dmi_decode(struct dmi_header *dm)
831{
832 u8 *data = (u8 *)dm;
833
834 switch(dm->type)
835 {
836 case 0:
837 dmi_printk(("BIOS Vendor: %s\n",
838 dmi_string(dm, data[4])));
839 dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
840 dmi_printk(("BIOS Version: %s\n",
841 dmi_string(dm, data[5])));
842 dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
843 dmi_printk(("BIOS Release: %s\n",
844 dmi_string(dm, data[8])));
845 dmi_save_ident(dm, DMI_BIOS_DATE, 8);
846 break;
847 case 1:
848 dmi_printk(("System Vendor: %s\n",
849 dmi_string(dm, data[4])));
850 dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
851 dmi_printk(("Product Name: %s\n",
852 dmi_string(dm, data[5])));
853 dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
854 dmi_printk(("Version: %s\n",
855 dmi_string(dm, data[6])));
856 dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
857 dmi_printk(("Serial Number: %s\n",
858 dmi_string(dm, data[7])));
859 break;
860 case 2:
861 dmi_printk(("Board Vendor: %s\n",
862 dmi_string(dm, data[4])));
863 dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
864 dmi_printk(("Board Name: %s\n",
865 dmi_string(dm, data[5])));
866 dmi_save_ident(dm, DMI_BOARD_NAME, 5);
867 dmi_printk(("Board Version: %s\n",
868 dmi_string(dm, data[6])));
869 dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
870 break;
871 }
872}
873
874void __init dmi_scan_machine(void)
875{
876 int err = dmi_iterate(dmi_decode);
877 if(err == 0)
878 dmi_check_blacklist();
879}
880