aafc78898f93e98c608271d6810b4374974a212d
[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         if (!acpi_force) {
551                 printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
552                        d->ident);       
553                 acpi_noirq_set();
554         }
555         return 0;
556 }
557 static __init int disable_acpi_pci(struct dmi_blacklist *d) 
558 {
559         if (!acpi_force) {
560                 printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
561                        d->ident);       
562                 acpi_disable_pci();
563         }
564         return 0;
565 }  
566 #endif
567
568 /*
569  *      Process the DMI blacklists
570  */
571  
572
573 /*
574  *      This will be expanded over time to force things like the APM 
575  *      interrupt mask settings according to the laptop
576  */
577  
578 static __initdata struct dmi_blacklist dmi_blacklist[]={
579         { broken_ps2_resume, "Dell Latitude C600", {    /* Handle problems with APM on the C600 */
580                         MATCH(DMI_SYS_VENDOR, "Dell"),
581                         MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
582                         NO_MATCH, NO_MATCH
583                         } },
584         { set_apm_ints, "Dell Latitude", {  /* Allow interrupts during suspend on Dell Latitude laptops*/
585                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
586                         MATCH(DMI_PRODUCT_NAME, "Latitude C510"),
587                         NO_MATCH, NO_MATCH
588                         } },
589         { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
590                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
591                         MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
592                         MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
593                         MATCH(DMI_BIOS_VERSION,"A11")
594                         } },
595         { set_apm_ints, "Dell Inspiron", {      /* Allow interrupts during suspend on Dell Inspiron laptops*/
596                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
597                         MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
598                         NO_MATCH, NO_MATCH
599                         } },
600         { broken_apm_power, "Dell Inspiron 5000e", {    /* Handle problems with APM on Inspiron 5000e */
601                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
602                         MATCH(DMI_BIOS_VERSION, "A04"),
603                         MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
604                         } },
605         { broken_apm_power, "Dell Inspiron 2500", {     /* Handle problems with APM on Inspiron 2500 */
606                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
607                         MATCH(DMI_BIOS_VERSION, "A12"),
608                         MATCH(DMI_BIOS_DATE, "02/04/2002"), NO_MATCH
609                         } },
610         { apm_is_horked, "Dell Dimension 4100", { /* APM crashes */
611                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
612                         MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
613                         MATCH(DMI_BIOS_VENDOR,"Intel Corp."),
614                         MATCH(DMI_BIOS_VERSION,"A11")
615                         } },
616         { set_realmode_power_off, "Award Software v4.60 PGMA", {        /* broken PM poweroff bios */
617                         MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
618                         MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
619                         MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
620                         } },
621         { set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */
622                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
623                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
624                         NO_MATCH, NO_MATCH
625                         } },
626         { set_bios_reboot, "Dell PowerEdge 300", {      /* Handle problems with rebooting on Dell 300's */
627                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
628                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
629                         NO_MATCH, NO_MATCH
630                         } },
631         { set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 2400's */
632                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
633                         MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
634                         NO_MATCH, NO_MATCH
635                         } },
636         { set_apm_ints, "Compaq 12XL125", {     /* Allow interrupts during suspend on Compaq Laptops*/
637                         MATCH(DMI_SYS_VENDOR, "Compaq"),
638                         MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
639                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
640                         MATCH(DMI_BIOS_VERSION,"4.06")
641                         } },
642         { set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
643                         MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
644                         MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
645                         NO_MATCH, NO_MATCH
646                         } },                                    
647         { apm_is_horked, "ABIT KX7-333[R]", { /* APM blows on shutdown */
648                         MATCH(DMI_BOARD_VENDOR, "ABIT"),
649                         MATCH(DMI_BOARD_NAME, "VT8367-8233A (KX7-333[R])"),
650                         NO_MATCH, NO_MATCH,
651                         } },
652         { apm_is_horked, "Trigem Delhi3", { /* APM crashes */
653                         MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
654                         MATCH(DMI_PRODUCT_NAME, "Delhi3"),
655                         NO_MATCH, NO_MATCH,
656                         } },
657         { apm_is_horked, "Fujitsu-Siemens", { /* APM crashes */
658                         MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
659                         MATCH(DMI_BIOS_VERSION, "Version1.01"),
660                         NO_MATCH, NO_MATCH,
661                         } },
662         { apm_is_horked_d850md, "Intel D850MD", { /* APM crashes */
663                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
664                         MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"),
665                         NO_MATCH, NO_MATCH,
666                         } },
667         { apm_is_horked, "Intel D810EMO", { /* APM crashes */
668                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
669                         MATCH(DMI_BIOS_VERSION, "MO81010A.86A.0008.P04.0004170800"),
670                         NO_MATCH, NO_MATCH,
671                         } },
672         { apm_is_horked, "Dell XPS-Z", { /* APM crashes */
673                         MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
674                         MATCH(DMI_BIOS_VERSION, "A11"),
675                         MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
676                         NO_MATCH,
677                         } },
678         { apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
679                         MATCH(DMI_SYS_VENDOR, "SHARP"),
680                         MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
681                         MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
682                         MATCH(DMI_BIOS_VERSION,"Version R2.08")
683                         } },
684         { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
685                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
686                         MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
687                         MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
688                         MATCH(DMI_BIOS_VERSION,"A11")
689                         } },
690         { apm_likes_to_melt, "Jabil AMD", { /* APM idle hangs */
691                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
692                         MATCH(DMI_BIOS_VERSION, "0AASNP06"),
693                         NO_MATCH, NO_MATCH,
694                         } },
695         { apm_likes_to_melt, "AMI Bios", { /* APM idle hangs */
696                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
697                         MATCH(DMI_BIOS_VERSION, "0AASNP05"), 
698                         NO_MATCH, NO_MATCH,
699                         } },
700         { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
701                         MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
702                         MATCH(DMI_PRODUCT_NAME, "PCG-"),
703                         NO_MATCH, NO_MATCH,
704                         } },
705         { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
706                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
707                         MATCH(DMI_BIOS_VERSION, "R0206H"),
708                         MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
709                         } },
710
711         { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
712                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
713                         MATCH(DMI_BIOS_VERSION, "W2K06H0"),
714                         MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
715                         } },
716                         
717         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-XG29 */
718                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
719                         MATCH(DMI_BIOS_VERSION, "R0117A0"),
720                         MATCH(DMI_BIOS_DATE, "04/25/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, "R0121Z1"),
726                         MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
727                         } },
728
729         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600NE */
730                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
731                         MATCH(DMI_BIOS_VERSION, "WME01Z1"),
732                         MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
733                         } },
734
735         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
736                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
737                         MATCH(DMI_BIOS_VERSION, "R0206Z3"),
738                         MATCH(DMI_BIOS_DATE, "12/25/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, "R0203D0"),
744                         MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
745                         } },
746
747         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS */
748                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
749                         MATCH(DMI_BIOS_VERSION, "R0203Z3"),
750                         MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
751                         } },
752         
753         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
754                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
755                         MATCH(DMI_BIOS_VERSION, "R0209Z3"),
756                         MATCH(DMI_BIOS_DATE, "05/12/01"), NO_MATCH
757                         } },
758
759         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-F104K */
760                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
761                         MATCH(DMI_BIOS_VERSION, "R0204K2"),
762                         MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
763                         } },
764
765         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
766                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
767                         MATCH(DMI_BIOS_VERSION, "R0208P1"),
768                         MATCH(DMI_BIOS_DATE, "11/09/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, "R0204P1"),
774                         MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
775                         } },
776
777         { swab_apm_power_in_minutes, "Sony VAIO", {     /* Handle problems with APM on Sony Vaio PCG-C1VE */
778                         MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
779                         MATCH(DMI_BIOS_VERSION, "WXPO1Z3"),
780                         MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH
781                         } },
782                         
783         { exploding_pnp_bios, "Higraded P14H", {        /* PnPBIOS GPF on boot */
784                         MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
785                         MATCH(DMI_BIOS_VERSION, "07.00T"),
786                         MATCH(DMI_SYS_VENDOR, "Higraded"),
787                         MATCH(DMI_PRODUCT_NAME, "P14H")
788                         } },
789         { exploding_pnp_bios, "ASUS P4P800", {  /* PnPBIOS GPF on boot */
790                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."),
791                         MATCH(DMI_BOARD_NAME, "P4P800"),
792                         NO_MATCH, NO_MATCH
793                         } },
794
795         /* Machines which have problems handling enabled local APICs */
796
797         { local_apic_kills_bios, "Dell Inspiron", {
798                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
799                         MATCH(DMI_PRODUCT_NAME, "Inspiron"),
800                         NO_MATCH, NO_MATCH
801                         } },
802
803         { local_apic_kills_bios, "Dell Latitude", {
804                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
805                         MATCH(DMI_PRODUCT_NAME, "Latitude"),
806                         NO_MATCH, NO_MATCH
807                         } },
808
809         { local_apic_kills_bios, "IBM Thinkpad T20", {
810                         MATCH(DMI_BOARD_VENDOR, "IBM"),
811                         MATCH(DMI_BOARD_NAME, "264741U"),
812                         NO_MATCH, NO_MATCH
813                         } },
814
815         { local_apic_kills_bios, "ASUS L3C", {
816                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
817                         MATCH(DMI_BOARD_NAME, "P4_L3C"),
818                         NO_MATCH, NO_MATCH
819                         } },
820
821         { broken_acpi_Sx, "ASUS K7V-RM", {              /* Bad ACPI Sx table */
822                         MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
823                         MATCH(DMI_BOARD_NAME, "<K7V-RM>"),
824                         NO_MATCH, NO_MATCH
825                         } },
826
827         { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
828                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
829                         NO_MATCH, NO_MATCH, NO_MATCH
830                         } },
831         { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
832                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
833                         NO_MATCH, NO_MATCH, NO_MATCH
834                         } },
835 #ifdef CONFIG_ACPI_SLEEP
836         { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
837                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
838                         NO_MATCH, NO_MATCH, NO_MATCH
839                         } },
840 #endif
841
842         { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
843                         MATCH(DMI_SYS_VENDOR, "IBM"),
844                         MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
845                         NO_MATCH, NO_MATCH
846                         } },
847          
848         { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
849                         MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
850                         MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
851                         MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
852                         MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
853                         } },
854  
855
856         /*
857          *      Generic per vendor APM settings
858          */
859          
860         { set_apm_ints, "IBM", {        /* Allow interrupts during suspend on IBM laptops */
861                         MATCH(DMI_SYS_VENDOR, "IBM"),
862                         NO_MATCH, NO_MATCH, NO_MATCH
863                         } },
864
865         /*
866          *      SMBus / sensors settings
867          */
868          
869         { disable_smbus, "IBM", {
870                         MATCH(DMI_SYS_VENDOR, "IBM"),
871                         NO_MATCH, NO_MATCH, NO_MATCH
872                         } },
873
874         /*
875          * Some Athlon laptops have really fucked PST tables.
876          * A BIOS update is all that can save them.
877          * Mention this, and disable cpufreq.
878          */
879         { acer_cpufreq_pst, "Acer Aspire", {
880                         MATCH(DMI_SYS_VENDOR, "Insyde Software"),
881                         MATCH(DMI_BIOS_VERSION, "3A71"),
882                         NO_MATCH, NO_MATCH,
883                         } },
884
885 #ifdef  CONFIG_ACPI_BOOT
886         /*
887          * If your system is blacklisted here, but you find that acpi=force
888          * works for you, please contact acpi-devel@sourceforge.net
889          */
890
891         /*
892          *      Boxes that need ACPI disabled
893          */
894
895         { dmi_disable_acpi, "IBM Thinkpad", {
896                         MATCH(DMI_BOARD_VENDOR, "IBM"),
897                         MATCH(DMI_BOARD_NAME, "2629H1G"),
898                         NO_MATCH, NO_MATCH }},
899
900         /*
901          *      Boxes that need acpi=ht 
902          */
903
904         { force_acpi_ht, "FSC Primergy T850", {
905                         MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
906                         MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
907                         NO_MATCH, NO_MATCH }},
908
909         { force_acpi_ht, "DELL GX240", {
910                         MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
911                         MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
912                         NO_MATCH, NO_MATCH }},
913
914         { force_acpi_ht, "HP VISUALIZE NT Workstation", {
915                         MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
916                         MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
917                         NO_MATCH, NO_MATCH }},
918
919         { force_acpi_ht, "Compaq ProLiant DL380 G2", {
920                         MATCH(DMI_SYS_VENDOR, "Compaq"),
921                         MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"),
922                         NO_MATCH, NO_MATCH }},
923
924         { force_acpi_ht, "Compaq ProLiant ML530 G2", {
925                         MATCH(DMI_SYS_VENDOR, "Compaq"),
926                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"),
927                         NO_MATCH, NO_MATCH }},
928
929         { force_acpi_ht, "Compaq ProLiant ML350 G3", {
930                         MATCH(DMI_SYS_VENDOR, "Compaq"),
931                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"),
932                         NO_MATCH, NO_MATCH }},
933
934         { force_acpi_ht, "Compaq Workstation W8000", {
935                         MATCH(DMI_SYS_VENDOR, "Compaq"),
936                         MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
937                         NO_MATCH, NO_MATCH }},
938
939         { force_acpi_ht, "ASUS P4B266", {
940                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
941                         MATCH(DMI_BOARD_NAME, "P4B266"),
942                         NO_MATCH, NO_MATCH }},
943
944         { force_acpi_ht, "ASUS P2B-DS", {
945                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
946                         MATCH(DMI_BOARD_NAME, "P2B-DS"),
947                         NO_MATCH, NO_MATCH }},
948
949         { force_acpi_ht, "ASUS CUR-DLS", {
950                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
951                         MATCH(DMI_BOARD_NAME, "CUR-DLS"),
952                         NO_MATCH, NO_MATCH }},
953
954         { force_acpi_ht, "ABIT i440BX-W83977", {
955                         MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
956                         MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
957                         NO_MATCH, NO_MATCH }},
958
959         { force_acpi_ht, "IBM Bladecenter", {
960                         MATCH(DMI_BOARD_VENDOR, "IBM"),
961                         MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
962                         NO_MATCH, NO_MATCH }},
963
964         { force_acpi_ht, "IBM eServer xSeries 360", {
965                         MATCH(DMI_BOARD_VENDOR, "IBM"),
966                         MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
967                         NO_MATCH, NO_MATCH }},
968
969         { force_acpi_ht, "IBM eserver xSeries 330", {
970                         MATCH(DMI_BOARD_VENDOR, "IBM"),
971                         MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
972                         NO_MATCH, NO_MATCH }},
973
974         { force_acpi_ht, "IBM eserver xSeries 440", {
975                         MATCH(DMI_BOARD_VENDOR, "IBM"),
976                         MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
977                         NO_MATCH, NO_MATCH }},
978
979         /*
980          * Systems with nForce2 BIOS timer override bug
981          * nVidia claims all nForce have timer on pin0,
982          * and applying this workaround is a NOP on fixed BIOS,
983          * so prospects are good for replacing these entries
984          * with something to key of chipset PCI-ID.
985          */
986         { ignore_timer_override, "Abit NF7-S v2", {
987                         MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
988                         MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
989                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
990                         MATCH(DMI_BIOS_DATE, "03/24/2004") }},
991
992         { ignore_timer_override, "Asus A7N8X v2", {
993                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
994                         MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
995                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
996                         MATCH(DMI_BIOS_DATE, "10/06/2003") }},
997
998         { ignore_timer_override, "Asus A7N8X-X", {
999                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
1000                         MATCH(DMI_BOARD_NAME, "A7N8X-X"),
1001                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"),
1002                         MATCH(DMI_BIOS_DATE, "2/3/2004") }},
1003
1004         { ignore_timer_override, "MSI K7N2-Delta", {
1005                         MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
1006                         MATCH(DMI_BOARD_NAME, "MS-6570"),
1007                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1008                         MATCH(DMI_BIOS_DATE, "03/29/2004") }},
1009
1010         { ignore_timer_override, "Shuttle SN41G2", {
1011                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
1012                         MATCH(DMI_BOARD_NAME, "FN41"),
1013                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1014                         MATCH(DMI_BIOS_DATE, "01/14/2004") }},
1015
1016         { ignore_timer_override, "Shuttle AN35N", {
1017                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
1018                         MATCH(DMI_BOARD_NAME, "AN35"),
1019                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
1020                         MATCH(DMI_BIOS_DATE, "12/05/2003") }},
1021 #endif  // CONFIG_ACPI_BOOT
1022
1023 #ifdef  CONFIG_ACPI_PCI
1024         /*
1025          *      Boxes that need ACPI PCI IRQ routing disabled
1026          */
1027
1028         { disable_acpi_irq, "ASUS A7V", {
1029                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
1030                         MATCH(DMI_BOARD_NAME, "<A7V>"),
1031                         /* newer BIOS, Revision 1011, does work */
1032                         MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
1033                         NO_MATCH }},
1034
1035         /*
1036          *      Boxes that need ACPI PCI IRQ routing and PCI scan disabled
1037          */
1038         { disable_acpi_pci, "ASUS PR-DLS", {    /* _BBN 0 bug */
1039                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
1040                         MATCH(DMI_BOARD_NAME, "PR-DLS"),
1041                         MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
1042                         MATCH(DMI_BIOS_DATE, "03/21/2003") }},
1043 #endif
1044
1045         { NULL, }
1046 };
1047         
1048         
1049 /*
1050  *      Walk the blacklist table running matching functions until someone 
1051  *      returns 1 or we hit the end.
1052  */
1053  
1054
1055 static __init void dmi_check_blacklist(void)
1056 {
1057         struct dmi_blacklist *d;
1058         int i;
1059                 
1060 #ifdef  CONFIG_ACPI_BOOT
1061 #define ACPI_BLACKLIST_CUTOFF_YEAR      2001
1062
1063         if (dmi_ident[DMI_BIOS_DATE]) { 
1064                 char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
1065                 if (s) { 
1066                         int year, disable = 0;
1067                         s++; 
1068                         year = simple_strtoul(s,NULL,0); 
1069                         if (year >= 1000) 
1070                                 disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
1071                         else if (year < 1 || (year > 90 && year <= 99))
1072                                 disable = 1; 
1073                         if (disable && !acpi_force) { 
1074                                 printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
1075                                 printk(KERN_NOTICE "You can enable it with acpi=force\n");
1076                                 disable_acpi();
1077                         } 
1078                 }
1079         }
1080 #endif
1081
1082         d=&dmi_blacklist[0];
1083         while(d->callback)
1084         {
1085                 for(i=0;i<4;i++)
1086                 {
1087                         int s = d->matches[i].slot;
1088                         if(s==NONE)
1089                                 continue;
1090                         if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
1091                                 continue;
1092                         /* No match */
1093                         goto fail;
1094                 }
1095                 if(d->callback(d))
1096                         return;
1097 fail:                   
1098                 d++;
1099         }
1100 }
1101
1102         
1103
1104 /*
1105  *      Process a DMI table entry. Right now all we care about are the BIOS
1106  *      and machine entries. For 2.5 we should pull the smbus controller info
1107  *      out of here.
1108  */
1109
1110 static void __init dmi_decode(struct dmi_header *dm)
1111 {
1112 #ifdef DMI_DEBUG
1113         u8 *data = (u8 *)dm;
1114 #endif
1115         
1116         switch(dm->type)
1117         {
1118                 case  0:
1119                         dmi_printk(("BIOS Vendor: %s\n",
1120                                 dmi_string(dm, data[4])));
1121                         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
1122                         dmi_printk(("BIOS Version: %s\n", 
1123                                 dmi_string(dm, data[5])));
1124                         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
1125                         dmi_printk(("BIOS Release: %s\n",
1126                                 dmi_string(dm, data[8])));
1127                         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
1128                         break;
1129                 case 1:
1130                         dmi_printk(("System Vendor: %s\n",
1131                                 dmi_string(dm, data[4])));
1132                         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
1133                         dmi_printk(("Product Name: %s\n",
1134                                 dmi_string(dm, data[5])));
1135                         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
1136                         dmi_printk(("Version: %s\n",
1137                                 dmi_string(dm, data[6])));
1138                         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
1139                         dmi_printk(("Serial Number: %s\n",
1140                                 dmi_string(dm, data[7])));
1141                         break;
1142                 case 2:
1143                         dmi_printk(("Board Vendor: %s\n",
1144                                 dmi_string(dm, data[4])));
1145                         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
1146                         dmi_printk(("Board Name: %s\n",
1147                                 dmi_string(dm, data[5])));
1148                         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
1149                         dmi_printk(("Board Version: %s\n",
1150                                 dmi_string(dm, data[6])));
1151                         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
1152                         break;
1153         }
1154 }
1155
1156 void __init dmi_scan_machine(void)
1157 {
1158         int err = dmi_iterate(dmi_decode);
1159         if(err == 0)
1160                 dmi_check_blacklist();
1161         else
1162                 printk(KERN_INFO "DMI not present.\n");
1163 }
1164
1165 EXPORT_SYMBOL(is_unsafe_smbus);