patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / i386 / kernel / dmi_scan.c
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/module.h>
7 #include <linux/apm_bios.h>
8 #include <linux/slab.h>
9 #include <asm/acpi.h>
10 #include <asm/io.h>
11 #include <linux/pm.h>
12 #include <asm/system.h>
13 #include <linux/bootmem.h>
14
15 unsigned long dmi_broken;
16 EXPORT_SYMBOL(dmi_broken);
17
18 int is_sony_vaio_laptop;
19 int is_unsafe_smbus;
20 int es7000_plat = 0;
21
22 struct dmi_header
23 {
24         u8      type;
25         u8      length;
26         u16     handle;
27 };
28
29 #undef DMI_DEBUG
30
31 #ifdef DMI_DEBUG
32 #define dmi_printk(x) printk x
33 #else
34 #define dmi_printk(x)
35 #endif
36
37 static char * __init dmi_string(struct dmi_header *dm, u8 s)
38 {
39         u8 *bp=(u8 *)dm;
40         bp+=dm->length;
41         if(!s)
42                 return "";
43         s--;
44         while(s>0 && *bp)
45         {
46                 bp+=strlen(bp);
47                 bp++;
48                 s--;
49         }
50         return bp;
51 }
52
53 /*
54  *      We have to be cautious here. We have seen BIOSes with DMI pointers
55  *      pointing to completely the wrong place for example
56  */
57  
58 static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
59 {
60         u8 *buf;
61         struct dmi_header *dm;
62         u8 *data;
63         int i=0;
64                 
65         buf = bt_ioremap(base, len);
66         if(buf==NULL)
67                 return -1;
68
69         data = buf;
70
71         /*
72          *      Stop when we see all the items the table claimed to have
73          *      OR we run off the end of the table (also happens)
74          */
75  
76         while(i<num && data-buf+sizeof(struct dmi_header)<=len)
77         {
78                 dm=(struct dmi_header *)data;
79                 /*
80                  *  We want to know the total length (formated area and strings)
81                  *  before decoding to make sure we won't run off the table in
82                  *  dmi_decode or dmi_string
83                  */
84                 data+=dm->length;
85                 while(data-buf<len-1 && (data[0] || data[1]))
86                         data++;
87                 if(data-buf<len-1)
88                         decode(dm);
89                 data+=2;
90                 i++;
91         }
92         bt_iounmap(buf, len);
93         return 0;
94 }
95
96
97 inline static int __init dmi_checksum(u8 *buf)
98 {
99         u8 sum=0;
100         int a;
101         
102         for(a=0; a<15; a++)
103                 sum+=buf[a];
104         return (sum==0);
105 }
106
107 static int __init dmi_iterate(void (*decode)(struct dmi_header *))
108 {
109         u8 buf[15];
110         u32 fp=0xF0000;
111
112         while (fp < 0xFFFFF)
113         {
114                 isa_memcpy_fromio(buf, fp, 15);
115                 if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
116                 {
117                         u16 num=buf[13]<<8|buf[12];
118                         u16 len=buf[7]<<8|buf[6];
119                         u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
120
121                         /*
122                          * DMI version 0.0 means that the real version is taken from
123                          * the SMBIOS version, which we don't know at this point.
124                          */
125                         if(buf[14]!=0)
126                                 printk(KERN_INFO "DMI %d.%d present.\n",
127                                         buf[14]>>4, buf[14]&0x0F);
128                         else
129                                 printk(KERN_INFO "DMI present.\n");
130                         dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
131                                 num, len));
132                         dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
133                                 base));
134                         if(dmi_table(base,len, num, decode)==0)
135                                 return 0;
136                 }
137                 fp+=16;
138         }
139         return -1;
140 }
141
142
143 enum
144 {
145         DMI_BIOS_VENDOR,
146         DMI_BIOS_VERSION,
147         DMI_BIOS_DATE,
148         DMI_SYS_VENDOR,
149         DMI_PRODUCT_NAME,
150         DMI_PRODUCT_VERSION,
151         DMI_BOARD_VENDOR,
152         DMI_BOARD_NAME,
153         DMI_BOARD_VERSION,
154         DMI_STRING_MAX
155 };
156
157 static char *dmi_ident[DMI_STRING_MAX];
158
159 /*
160  *      Save a DMI string
161  */
162  
163 static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
164 {
165         char *d = (char*)dm;
166         char *p = dmi_string(dm, d[string]);
167         if(p==NULL || *p == 0)
168                 return;
169         if (dmi_ident[slot])
170                 return;
171         dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
172         if(dmi_ident[slot])
173                 strcpy(dmi_ident[slot], p);
174         else
175                 printk(KERN_ERR "dmi_save_ident: out of memory.\n");
176 }
177
178 /*
179  *      DMI callbacks for problem boards
180  */
181
182 struct dmi_strmatch
183 {
184         u8 slot;
185         char *substr;
186 };
187
188 #define NONE    255
189
190 struct dmi_blacklist
191 {
192         int (*callback)(struct dmi_blacklist *);
193         char *ident;
194         struct dmi_strmatch matches[4];
195 };
196
197 #define NO_MATCH        { NONE, NULL}
198 #define MATCH(a,b)      { a, b }
199
200 /* 
201  * Reboot options and system auto-detection code provided by
202  * Dell Inc. so their systems "just work". :-)
203  */
204
205 /* 
206  * Some machines require the "reboot=b"  commandline option, this quirk makes that automatic.
207  */
208 static __init int set_bios_reboot(struct dmi_blacklist *d)
209 {
210         extern int reboot_thru_bios;
211         if (reboot_thru_bios == 0)
212         {
213                 reboot_thru_bios = 1;
214                 printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
215         }
216         return 0;
217 }
218
219 /*
220  * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
221  */
222 static __init int set_smp_reboot(struct dmi_blacklist *d)
223 {
224 #ifdef CONFIG_SMP
225         extern int reboot_smp;
226         if (reboot_smp == 0)
227         {
228                 reboot_smp = 1;
229                 printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
230         }
231 #endif
232         return 0;
233 }
234
235 /*
236  * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
237  */
238 static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
239 {
240         set_smp_reboot(d);
241         set_bios_reboot(d);
242         return 0;
243 }
244
245 /*
246  * Some bioses have a broken protected mode poweroff and need to use realmode
247  */
248
249 static __init int set_realmode_power_off(struct dmi_blacklist *d)
250 {
251        if (apm_info.realmode_power_off == 0)
252        {
253                apm_info.realmode_power_off = 1;
254                printk(KERN_INFO "%s bios detected. Using realmode poweroff only.\n", d->ident);
255        }
256        return 0;
257 }
258
259
260 /* 
261  * Some laptops require interrupts to be enabled during APM calls 
262  */
263
264 static __init int set_apm_ints(struct dmi_blacklist *d)
265 {
266         if (apm_info.allow_ints == 0)
267         {
268                 apm_info.allow_ints = 1;
269                 printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.\n", d->ident);
270         }
271         return 0;
272 }
273
274 /* 
275  * Some APM bioses corrupt memory or just plain do not work
276  */
277
278 static __init int apm_is_horked(struct dmi_blacklist *d)
279 {
280         if (apm_info.disabled == 0)
281         {
282                 apm_info.disabled = 1;
283                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
284         }
285         return 0;
286 }
287
288 static __init int apm_is_horked_d850md(struct dmi_blacklist *d)
289 {
290         if (apm_info.disabled == 0) {
291                 apm_info.disabled = 1;
292                 printk(KERN_INFO "%s machine detected. Disabling APM.\n", d->ident);
293                 printk(KERN_INFO "This bug is fixed in bios P15 which is available for \n");
294                 printk(KERN_INFO "download from support.intel.com \n");
295         }
296         return 0;
297 }
298
299 /* 
300  * Some APM bioses hang on APM idle calls
301  */
302
303 static __init int apm_likes_to_melt(struct dmi_blacklist *d)
304 {
305         if (apm_info.forbid_idle == 0) {
306                 apm_info.forbid_idle = 1;
307                 printk(KERN_INFO "%s machine detected. Disabling APM idle calls.\n", d->ident);
308         }
309         return 0;
310 }
311
312 /*
313  * Some machines, usually laptops, can't handle an enabled local APIC.
314  * The symptoms include hangs or reboots when suspending or resuming,
315  * attaching or detaching the power cord, or entering BIOS setup screens
316  * through magic key sequences.
317  */
318 static int __init local_apic_kills_bios(struct dmi_blacklist *d)
319 {
320 #ifdef CONFIG_X86_LOCAL_APIC
321         extern int enable_local_apic;
322         if (enable_local_apic == 0) {
323                 enable_local_apic = -1;
324                 printk(KERN_WARNING "%s with broken BIOS detected. "
325                        "Refusing to enable the local APIC.\n",
326                        d->ident);
327         }
328 #endif
329         return 0;
330 }
331
332 /* 
333  * Don't access SMBus on IBM systems which get corrupted eeproms 
334  */
335
336 static __init int disable_smbus(struct dmi_blacklist *d)
337 {   
338         if (is_unsafe_smbus == 0) {
339                 is_unsafe_smbus = 1;
340                 printk(KERN_INFO "%s machine detected. Disabling SMBus accesses.\n", d->ident);
341         }
342         return 0;
343 }
344
345 /*
346  * Work around broken HP Pavilion Notebooks which assign USB to
347  * IRQ 9 even though it is actually wired to IRQ 11
348  */
349 static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
350 {
351 #ifdef CONFIG_PCI
352         extern int broken_hp_bios_irq9;
353         if (broken_hp_bios_irq9 == 0)
354         {
355                 broken_hp_bios_irq9 = 1;
356                 printk(KERN_INFO "%s detected - fixing broken IRQ routing\n", d->ident);
357         }
358 #endif
359         return 0;
360 }
361
362 /*
363  *  Check for clue free BIOS implementations who use
364  *  the following QA technique
365  *
366  *      [ Write BIOS Code ]<------
367  *               |                ^
368  *      < Does it Compile >----N--
369  *               |Y               ^
370  *      < Does it Boot Win98 >-N--
371  *               |Y
372  *           [Ship It]
373  *
374  *      Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
375  *      Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
376  */
377
378 static __init int broken_apm_power(struct dmi_blacklist *d)
379 {
380         apm_info.get_power_status_broken = 1;
381         printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n");
382         return 0;
383 }               
384
385 /*
386  * Check for a Sony Vaio system
387  *
388  * On a Sony system we want to enable the use of the sonypi
389  * driver for Sony-specific goodies like the camera and jogdial.
390  * We also want to avoid using certain functions of the PnP BIOS.
391  */
392
393 static __init int sony_vaio_laptop(struct dmi_blacklist *d)
394 {
395         if (is_sony_vaio_laptop == 0)
396         {
397                 is_sony_vaio_laptop = 1;
398                 printk(KERN_INFO "%s laptop detected.\n", d->ident);
399         }
400         return 0;
401 }
402
403 /*
404  * This bios swaps the APM minute reporting bytes over (Many sony laptops
405  * have this problem).
406  */
407  
408 static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
409 {
410         apm_info.get_power_status_swabinminutes = 1;
411         printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.\n");
412         return 0;
413 }
414
415 /*
416  * ASUS K7V-RM has broken ACPI table defining sleep modes
417  */
418
419 static __init int broken_acpi_Sx(struct dmi_blacklist *d)
420 {
421         printk(KERN_WARNING "Detected ASUS mainboard with broken ACPI sleep table\n");
422         dmi_broken |= BROKEN_ACPI_Sx;
423         return 0;
424 }
425
426 /*
427  * Toshiba keyboard likes to repeat keys when they are not repeated.
428  */
429
430 static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
431 {
432         printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n");
433         return 0;
434 }
435
436 /*
437  * Toshiba fails to preserve interrupts over S1
438  */
439
440 static __init int init_ints_after_s1(struct dmi_blacklist *d)
441 {
442         printk(KERN_WARNING "Toshiba with broken S1 detected.\n");
443         dmi_broken |= BROKEN_INIT_AFTER_S1;
444         return 0;
445 }
446
447 #ifdef CONFIG_ACPI_SLEEP
448 static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
449 {
450         /* See acpi_wakeup.S */
451         extern long acpi_video_flags;
452         acpi_video_flags |= 2;
453         return 0;
454 }
455 #endif
456
457 /*
458  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it was
459  * disabled before the suspend. Linux used to get terribly confused by that.
460  */
461
462 static __init int broken_ps2_resume(struct dmi_blacklist *d)
463 {
464         printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround hopefully not needed.\n", d->ident);
465         return 0;
466 }
467
468 /*
469  *      Exploding PnPBIOS. Don't yet know if its the BIOS or us for
470  *      some entries
471  */
472
473 static __init int exploding_pnp_bios(struct dmi_blacklist *d)
474 {
475         printk(KERN_WARNING "%s detected. Disabling PnPBIOS\n", d->ident);
476         dmi_broken |= BROKEN_PNP_BIOS;
477         return 0;
478 }
479
480 static __init int acer_cpufreq_pst(struct dmi_blacklist *d)
481 {
482         printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident);
483         printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
484         printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n");
485         dmi_broken |= BROKEN_CPUFREQ;
486         return 0;
487 }
488
489
490 /*
491  *      Simple "print if true" callback
492  */
493  
494 static __init int print_if_true(struct dmi_blacklist *d)
495 {
496         printk("%s\n", d->ident);
497         return 0;
498 }
499
500
501 #ifdef  CONFIG_ACPI_BOOT
502 extern int acpi_force;
503
504 static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) 
505
506         if (!acpi_force) { 
507                 printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
508                 disable_acpi();
509         } else { 
510                 printk(KERN_NOTICE 
511                        "Warning: DMI blacklist says broken, but acpi forced\n"); 
512         }
513         return 0;
514
515
516 /*
517  * Limit ACPI to CPU enumeration for HT
518  */
519 static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) 
520
521         if (!acpi_force) { 
522                 printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); 
523                 disable_acpi();
524                 acpi_ht = 1; 
525         } else { 
526                 printk(KERN_NOTICE 
527                        "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); 
528         }
529         return 0;
530
531
532 /*
533  * early nForce2 reference BIOS shipped with a
534  * bogus ACPI IRQ0 -> pin2 interrupt override -- ignore it
535  */
536 static __init int ignore_timer_override(struct dmi_blacklist *d)
537 {
538         extern int acpi_skip_timer_override;
539         printk(KERN_NOTICE "%s detected: BIOS IRQ0 pin2 override"
540                 " will be ignored\n", d->ident);        
541
542         acpi_skip_timer_override = 1;
543         return 0;
544 }
545 #endif
546
547 #ifdef  CONFIG_ACPI_PCI
548 static __init int disable_acpi_irq(struct dmi_blacklist *d) 
549
550         printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n", d->ident);         
551         acpi_noirq_set();
552         return 0;
553 }
554 static __init int disable_acpi_pci(struct dmi_blacklist *d) 
555
556         printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n", d->ident);         
557         acpi_disable_pci();
558         return 0;
559 }  
560 #endif
561
562 /*
563  *      Process the DMI blacklists
564  */
565  
566
567 /*
568  *      This will be expanded over time to force things like the APM 
569  *      interrupt mask settings according to the laptop
570  */
571  
572 static __initdata struct dmi_blacklist dmi_blacklist[]={
573         { broken_ps2_resume, "Dell Latitude C600", {    /* Handle problems with APM on the C600 */
574                         MATCH(DMI_SYS_VENDOR, "Dell"),
575                         MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
576                         NO_MATCH, NO_MATCH
577                         } },
578         { set_apm_ints, "Dell Latitude", {  /* Allow interrupts during suspend on Dell Latitude laptops*/
579                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
580                         MATCH(DMI_PRODUCT_NAME, "Latitude C510"),
581                         NO_MATCH, NO_MATCH
582                         } },
583         { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
584                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
585                         MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
586                         MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
587                         MATCH(DMI_BIOS_VERSION,"A11")
588                         } },
589         { set_apm_ints, "Dell Inspiron", {      /* Allow interrupts during suspend on Dell Inspiron laptops*/
590                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
591                         MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
592                         NO_MATCH, NO_MATCH
593                         } },
594         { broken_apm_power, "Dell Inspiron 5000e", {    /* Handle problems with APM on Inspiron 5000e */
595                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
596                         MATCH(DMI_BIOS_VERSION, "A04"),
597                         MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
598                         } },
599         { broken_apm_power, "Dell Inspiron 2500", {     /* Handle problems with APM on Inspiron 2500 */
600                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
601                         MATCH(DMI_BIOS_VERSION, "A12"),
602                         MATCH(DMI_BIOS_DATE, "02/04/2002"), NO_MATCH
603                         } },
604         { apm_is_horked, "Dell Dimension 4100", { /* APM crashes */
605                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
606                         MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
607                         MATCH(DMI_BIOS_VENDOR,"Intel Corp."),
608                         MATCH(DMI_BIOS_VERSION,"A11")
609                         } },
610         { set_realmode_power_off, "Award Software v4.60 PGMA", {        /* broken PM poweroff bios */
611                         MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
612                         MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
613                         MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
614                         } },
615         { set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */
616                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
617                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
618                         NO_MATCH, NO_MATCH
619                         } },
620         { set_bios_reboot, "Dell PowerEdge 300", {      /* Handle problems with rebooting on Dell 300's */
621                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
622                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
623                         NO_MATCH, NO_MATCH
624                         } },
625         { set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 2400's */
626                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
627                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
628                         NO_MATCH, NO_MATCH
629                         } },
630         { set_apm_ints, "Compaq 12XL125", {     /* Allow interrupts during suspend on Compaq Laptops*/
631                         MATCH(DMI_SYS_VENDOR, "Compaq"),
632                         MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
633                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
634                         MATCH(DMI_BIOS_VERSION,"4.06")
635                         } },
636         { set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
637                         MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
638                         MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
639                         NO_MATCH, NO_MATCH
640                         } },                                    
641         { apm_is_horked, "ABIT KX7-333[R]", { /* APM blows on shutdown */
642                         MATCH(DMI_BOARD_VENDOR, "ABIT"),
643                         MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"),
644                         NO_MATCH, NO_MATCH,
645                         } },
646         { apm_is_horked, "Trigem Delhi3", { /* APM crashes */
647                         MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
648                         MATCH(DMI_PRODUCT_NAME, "Delhi3"),
649                         NO_MATCH, NO_MATCH,
650                         } },
651         { apm_is_horked, "Fujitsu-Siemens", { /* APM crashes */
652                         MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
653                         MATCH(DMI_BIOS_VERSION, "Version1.01"),
654                         NO_MATCH, NO_MATCH,
655                         } },
656         { apm_is_horked_d850md, "Intel D850MD", { /* APM crashes */
657                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
658                         MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"),
659                         NO_MATCH, NO_MATCH,
660                         } },
661         { apm_is_horked, "Intel D810EMO", { /* APM crashes */
662                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
663                         MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"),
664                         NO_MATCH, NO_MATCH,
665                         } },
666         { apm_is_horked, "Dell XPS-Z", { /* APM crashes */
667                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
668                         MATCH(DMI_BIOS_VERSION, "A11"),
669                         MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
670                         NO_MATCH,
671                         } },
672         { apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
673                         MATCH(DMI_SYS_VENDOR, "SHARP"),
674                         MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
675                         MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
676                         MATCH(DMI_BIOS_VERSION,"Version R2.08")
677                         } },
678         { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
679                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
680                         MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
681                         MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
682                         MATCH(DMI_BIOS_VERSION,"A11")
683                         } },
684         { apm_likes_to_melt, "Jabil AMD", { /* APM idle hangs */
685                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
686                         MATCH(DMI_BIOS_VERSION, "0AASNP06"),
687                         NO_MATCH, NO_MATCH,
688                         } },
689         { apm_likes_to_melt, "AMI Bios", { /* APM idle hangs */
690                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
691                         MATCH(DMI_BIOS_VERSION, "0AASNP05"), 
692                         NO_MATCH, NO_MATCH,
693                         } },
694         { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
695                         MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
696                         MATCH(DMI_PRODUCT_NAME, "PCG-"),
697                         NO_MATCH, NO_MATCH,
698                         } },
699         { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
700                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
701                         MATCH(DMI_BIOS_VERSION, "R0206H"),
702                         MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
703                         } },
704
705         { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
706                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
707                         MATCH(DMI_BIOS_VERSION, "W2K06H0"),
708                         MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
709                         } },
710                         
711         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-XG29 */
712                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
713                         MATCH(DMI_BIOS_VERSION, "R0117A0"),
714                         MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
715                         } },
716
717         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600NE */
718                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
719                         MATCH(DMI_BIOS_VERSION, "R0121Z1"),
720                         MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
721                         } },
722
723         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600NE */
724                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
725                         MATCH(DMI_BIOS_VERSION, "WME01Z1"),
726                         MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
727                         } },
728
729         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
730                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
731                         MATCH(DMI_BIOS_VERSION, "R0206Z3"),
732                         MATCH(DMI_BIOS_DATE, "12/25/00"), NO_MATCH
733                         } },
734
735         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS */
736                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
737                         MATCH(DMI_BIOS_VERSION, "R0203D0"),
738                         MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
739                         } },
740
741         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS */
742                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
743                         MATCH(DMI_BIOS_VERSION, "R0203Z3"),
744                         MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
745                         } },
746         
747         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
748                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
749                         MATCH(DMI_BIOS_VERSION, "R0209Z3"),
750                         MATCH(DMI_BIOS_DATE, "05/12/01"), NO_MATCH
751                         } },
752
753         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-F104K */
754                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
755                         MATCH(DMI_BIOS_VERSION, "R0204K2"),
756                         MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
757                         } },
758
759         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
760                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
761                         MATCH(DMI_BIOS_VERSION, "R0208P1"),
762                         MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
763                         } },
764
765         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-C1VE */
766                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
767                         MATCH(DMI_BIOS_VERSION, "R0204P1"),
768                         MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
769                         } },
770
771         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-C1VE */
772                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
773                         MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
774                         MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH
775                         } },
776                         
777         { exploding_pnp_bios, "Higraded P14H", {        /* PnPBIOS GPF on boot */
778                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
779                         MATCH(DMI_BIOS_VERSION, "07.00T"),
780                         MATCH(DMI_SYS_VENDOR, "Higraded"),
781                         MATCH(DMI_PRODUCT_NAME, "P14H")
782                         } },
783         { exploding_pnp_bios, "ASUS P4P800", {  /* PnPBIOS GPF on boot */
784                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
785                         MATCH(DMI_BOARD_NAME, "P4P800"),
786                         NO_MATCH, NO_MATCH
787                         } },
788
789         /* Machines which have problems handling enabled local APICs */
790
791         { local_apic_kills_bios, "Dell Inspiron", {
792                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
793                         MATCH(DMI_PRODUCT_NAME, "Inspiron"),
794                         NO_MATCH, NO_MATCH
795                         } },
796
797         { local_apic_kills_bios, "Dell Latitude", {
798                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
799                         MATCH(DMI_PRODUCT_NAME, "Latitude"),
800                         NO_MATCH, NO_MATCH
801                         } },
802
803         { local_apic_kills_bios, "IBM Thinkpad T20", {
804                         MATCH(DMI_BOARD_VENDOR, "IBM"),
805                         MATCH(DMI_BOARD_NAME, "264741U"),
806                         NO_MATCH, NO_MATCH
807                         } },
808
809         { local_apic_kills_bios, "ASUS L3C", {
810                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
811                         MATCH(DMI_BOARD_NAME, "P4_L3C"),
812                         NO_MATCH, NO_MATCH
813                         } },
814
815         { broken_acpi_Sx, "ASUS K7V-RM", {              /* Bad ACPI Sx table */
816                         MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
817                         MATCH(DMI_BOARD_NAME, "<K7V-RM>"),
818                         NO_MATCH, NO_MATCH
819                         } },
820
821         { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
822                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
823                         NO_MATCH, NO_MATCH, NO_MATCH
824                         } },
825         { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
826                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
827                         NO_MATCH, NO_MATCH, NO_MATCH
828                         } },
829 #ifdef CONFIG_ACPI_SLEEP
830         { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
831                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
832                         NO_MATCH, NO_MATCH, NO_MATCH
833                         } },
834 #endif
835
836         { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
837                         MATCH(DMI_SYS_VENDOR, "IBM"),
838                         MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
839                         NO_MATCH, NO_MATCH
840                         } },
841          
842         { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
843                         MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
844                         MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
845                         MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
846                         MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
847                         } },
848  
849
850         /*
851          *      Generic per vendor APM settings
852          */
853          
854         { set_apm_ints, "IBM", {        /* Allow interrupts during suspend on IBM laptops */
855                         MATCH(DMI_SYS_VENDOR, "IBM"),
856                         NO_MATCH, NO_MATCH, NO_MATCH
857                         } },
858
859         /*
860          *      SMBus / sensors settings
861          */
862          
863         { disable_smbus, "IBM", {
864                         MATCH(DMI_SYS_VENDOR, "IBM"),
865                         NO_MATCH, NO_MATCH, NO_MATCH
866                         } },
867
868         /*
869          * Some Athlon laptops have really fucked PST tables.
870          * A BIOS update is all that can save them.
871          * Mention this, and disable cpufreq.
872          */
873         { acer_cpufreq_pst, "Acer Aspire", {
874                         MATCH(DMI_SYS_VENDOR, "Insyde Software"),
875                         MATCH(DMI_BIOS_VERSION, "3A71"),
876                         NO_MATCH, NO_MATCH,
877                         } },
878
879 #ifdef  CONFIG_ACPI_BOOT
880         /*
881          * If your system is blacklisted here, but you find that acpi=force
882          * works for you, please contact acpi-devel@sourceforge.net
883          */
884
885         /*
886          *      Boxes that need ACPI disabled
887          */
888
889         { dmi_disable_acpi, "IBM Thinkpad", {
890                         MATCH(DMI_BOARD_VENDOR, "IBM"),
891                         MATCH(DMI_BOARD_NAME, "2629H1G"),
892                         NO_MATCH, NO_MATCH }},
893
894         /*
895          *      Boxes that need acpi=ht 
896          */
897
898         { force_acpi_ht, "FSC Primergy T850", {
899                         MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
900                         MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
901                         NO_MATCH, NO_MATCH }},
902
903         { force_acpi_ht, "DELL GX240", {
904                         MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
905                         MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
906                         NO_MATCH, NO_MATCH }},
907
908         { force_acpi_ht, "HP VISUALIZE NT Workstation", {
909                         MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
910                         MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
911                         NO_MATCH, NO_MATCH }},
912
913         { force_acpi_ht, "Compaq ProLiant DL380 G2", {
914                         MATCH(DMI_SYS_VENDOR, "Compaq"),
915                         MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"),
916                         NO_MATCH, NO_MATCH }},
917
918         { force_acpi_ht, "Compaq ProLiant ML530 G2", {
919                         MATCH(DMI_SYS_VENDOR, "Compaq"),
920                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"),
921                         NO_MATCH, NO_MATCH }},
922
923         { force_acpi_ht, "Compaq ProLiant ML350 G3", {
924                         MATCH(DMI_SYS_VENDOR, "Compaq"),
925                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"),
926                         NO_MATCH, NO_MATCH }},
927
928         { force_acpi_ht, "Compaq Workstation W8000", {
929                         MATCH(DMI_SYS_VENDOR, "Compaq"),
930                         MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
931                         NO_MATCH, NO_MATCH }},
932
933         { force_acpi_ht, "ASUS P4B266", {
934                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
935                         MATCH(DMI_BOARD_NAME, "P4B266"),
936                         NO_MATCH, NO_MATCH }},
937
938         { force_acpi_ht, "ASUS P2B-DS", {
939                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
940                         MATCH(DMI_BOARD_NAME, "P2B-DS"),
941                         NO_MATCH, NO_MATCH }},
942
943         { force_acpi_ht, "ASUS CUR-DLS", {
944                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
945                         MATCH(DMI_BOARD_NAME, "CUR-DLS"),
946                         NO_MATCH, NO_MATCH }},
947
948         { force_acpi_ht, "ABIT i440BX-W83977", {
949                         MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
950                         MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
951                         NO_MATCH, NO_MATCH }},
952
953         { force_acpi_ht, "IBM Bladecenter", {
954                         MATCH(DMI_BOARD_VENDOR, "IBM"),
955                         MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
956                         NO_MATCH, NO_MATCH }},
957
958         { force_acpi_ht, "IBM eServer xSeries 360", {
959                         MATCH(DMI_BOARD_VENDOR, "IBM"),
960                         MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
961                         NO_MATCH, NO_MATCH }},
962
963         { force_acpi_ht, "IBM eserver xSeries 330", {
964                         MATCH(DMI_BOARD_VENDOR, "IBM"),
965                         MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
966                         NO_MATCH, NO_MATCH }},
967
968         { force_acpi_ht, "IBM eserver xSeries 440", {
969                         MATCH(DMI_BOARD_VENDOR, "IBM"),
970                         MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
971                         NO_MATCH, NO_MATCH }},
972
973         /*
974          * Systems with nForce2 BIOS timer override bug
975          * nVidia claims all nForce have timer on pin0,
976          * and applying this workaround is a NOP on fixed BIOS,
977          * so prospects are good for replacing these entries
978          * with something to key of chipset PCI-ID.
979          */
980         { ignore_timer_override, "Abit NF7-S v2", {
981                         MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
982                         MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
983                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
984                         MATCH(DMI_BIOS_DATE, "03/24/2004") }},
985
986         { ignore_timer_override, "Asus A7N8X v2", {
987                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
988                         MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
989                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
990                         MATCH(DMI_BIOS_DATE, "10/06/2003") }},
991
992         { ignore_timer_override, "Asus A7N8X-X", {
993                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
994                         MATCH(DMI_BOARD_NAME, "A7N8X-X"),
995                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"),
996                         MATCH(DMI_BIOS_DATE, "2/3/2004") }},
997
998         { ignore_timer_override, "MSI K7N2-Delta", {
999                         MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
1000                         MATCH(DMI_BOARD_NAME, "MS-6570"),
1001                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1002                         MATCH(DMI_BIOS_DATE, "03/29/2004") }},
1003
1004         { ignore_timer_override, "Shuttle SN41G2", {
1005                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
1006                         MATCH(DMI_BOARD_NAME, "FN41"),
1007                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1008                         MATCH(DMI_BIOS_DATE, "01/14/2004") }},
1009
1010         { ignore_timer_override, "Shuttle AN35N", {
1011                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
1012                         MATCH(DMI_BOARD_NAME, "AN35"),
1013                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1014                         MATCH(DMI_BIOS_DATE, "12/05/2003") }},
1015 #endif  // CONFIG_ACPI_BOOT
1016
1017 #ifdef  CONFIG_ACPI_PCI
1018         /*
1019          *      Boxes that need ACPI PCI IRQ routing disabled
1020          */
1021
1022         { disable_acpi_irq, "ASUS A7V", {
1023                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
1024                         MATCH(DMI_BOARD_NAME, "<A7V>"),
1025                         /* newer BIOS, Revision 1011, does work */
1026                         MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
1027                         NO_MATCH }},
1028
1029         /*
1030          *      Boxes that need ACPI PCI IRQ routing and PCI scan disabled
1031          */
1032         { disable_acpi_pci, "ASUS PR-DLS", {    /* _BBN 0 bug */
1033                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
1034                         MATCH(DMI_BOARD_NAME, "PR-DLS"),
1035                         MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
1036                         MATCH(DMI_BIOS_DATE, "03/21/2003") }},
1037 #endif
1038
1039         { NULL, }
1040 };
1041         
1042         
1043 /*
1044  *      Walk the blacklist table running matching functions until someone 
1045  *      returns 1 or we hit the end.
1046  */
1047  
1048
1049 static __init void dmi_check_blacklist(void)
1050 {
1051         struct dmi_blacklist *d;
1052         int i;
1053                 
1054 #ifdef  CONFIG_ACPI_BOOT
1055 #define ACPI_BLACKLIST_CUTOFF_YEAR      2001
1056
1057         if (dmi_ident[DMI_BIOS_DATE]) { 
1058                 char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
1059                 if (s) { 
1060                         int year, disable = 0;
1061                         s++; 
1062                         year = simple_strtoul(s,NULL,0); 
1063                         if (year >= 1000) 
1064                                 disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
1065                         else if (year < 1 || (year > 90 && year <= 99))
1066                                 disable = 1; 
1067                         if (disable && !acpi_force) { 
1068                                 printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
1069                                 printk(KERN_NOTICE "You can enable it with acpi=force\n");
1070                                 disable_acpi();
1071                         } 
1072                 }
1073         }
1074 #endif
1075
1076         d=&dmi_blacklist[0];
1077         while(d->callback)
1078         {
1079                 for(i=0;i<4;i++)
1080                 {
1081                         int s = d->matches[i].slot;
1082                         if(s==NONE)
1083                                 continue;
1084                         if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
1085                                 continue;
1086                         /* No match */
1087                         goto fail;
1088                 }
1089                 if(d->callback(d))
1090                         return;
1091 fail:                   
1092                 d++;
1093         }
1094 }
1095
1096         
1097
1098 /*
1099  *      Process a DMI table entry. Right now all we care about are the BIOS
1100  *      and machine entries. For 2.5 we should pull the smbus controller info
1101  *      out of here.
1102  */
1103
1104 static void __init dmi_decode(struct dmi_header *dm)
1105 {
1106 #ifdef DMI_DEBUG
1107         u8 *data = (u8 *)dm;
1108 #endif
1109         
1110         switch(dm->type)
1111         {
1112                 case  0:
1113                         dmi_printk(("BIOS Vendor: %s\n",
1114                                 dmi_string(dm, data[4])));
1115                         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
1116                         dmi_printk(("BIOS Version: %s\n", 
1117                                 dmi_string(dm, data[5])));
1118                         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
1119                         dmi_printk(("BIOS Release: %s\n",
1120                                 dmi_string(dm, data[8])));
1121                         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
1122                         break;
1123                 case 1:
1124                         dmi_printk(("System Vendor: %s\n",
1125                                 dmi_string(dm, data[4])));
1126                         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
1127                         dmi_printk(("Product Name: %s\n",
1128                                 dmi_string(dm, data[5])));
1129                         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
1130                         dmi_printk(("Version: %s\n",
1131                                 dmi_string(dm, data[6])));
1132                         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
1133                         dmi_printk(("Serial Number: %s\n",
1134                                 dmi_string(dm, data[7])));
1135                         break;
1136                 case 2:
1137                         dmi_printk(("Board Vendor: %s\n",
1138                                 dmi_string(dm, data[4])));
1139                         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
1140                         dmi_printk(("Board Name: %s\n",
1141                                 dmi_string(dm, data[5])));
1142                         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
1143                         dmi_printk(("Board Version: %s\n",
1144                                 dmi_string(dm, data[6])));
1145                         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
1146                         break;
1147         }
1148 }
1149
1150 void __init dmi_scan_machine(void)
1151 {
1152         int err = dmi_iterate(dmi_decode);
1153         if(err == 0)
1154                 dmi_check_blacklist();
1155         else
1156                 printk(KERN_INFO "DMI not present.\n");
1157 }
1158
1159 EXPORT_SYMBOL(is_unsafe_smbus);