c6e9ba8aa74ec7f62251d0e9d1c3c6dfb98df902
[linux-flexiantxendom0-3.2.10.git] / arch / i386 / kernel / dmi_scan.c
1 #include <linux/types.h>
2 #include <linux/kernel.h>
3 #include <linux/string.h>
4 #include <linux/init.h>
5 #include <linux/module.h>
6 #include <linux/slab.h>
7 #include <asm/acpi.h>
8 #include <asm/io.h>
9 #include <linux/pm.h>
10 #include <asm/system.h>
11 #include <linux/dmi.h>
12 #include <linux/bootmem.h>
13
14
15 int es7000_plat = 0;
16
17 struct dmi_header
18 {
19         u8      type;
20         u8      length;
21         u16     handle;
22 };
23
24 #undef DMI_DEBUG
25
26 #ifdef DMI_DEBUG
27 #define dmi_printk(x) printk x
28 #else
29 #define dmi_printk(x)
30 #endif
31
32 static char * __init dmi_string(struct dmi_header *dm, u8 s)
33 {
34         u8 *bp=(u8 *)dm;
35         bp+=dm->length;
36         if(!s)
37                 return "";
38         s--;
39         while(s>0 && *bp)
40         {
41                 bp+=strlen(bp);
42                 bp++;
43                 s--;
44         }
45         return bp;
46 }
47
48 /*
49  *      We have to be cautious here. We have seen BIOSes with DMI pointers
50  *      pointing to completely the wrong place for example
51  */
52  
53 static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
54 {
55         u8 *buf;
56         struct dmi_header *dm;
57         u8 *data;
58         int i=0;
59                 
60         buf = bt_ioremap(base, len);
61         if(buf==NULL)
62                 return -1;
63
64         data = buf;
65
66         /*
67          *      Stop when we see all the items the table claimed to have
68          *      OR we run off the end of the table (also happens)
69          */
70  
71         while(i<num && data-buf+sizeof(struct dmi_header)<=len)
72         {
73                 dm=(struct dmi_header *)data;
74                 /*
75                  *  We want to know the total length (formated area and strings)
76                  *  before decoding to make sure we won't run off the table in
77                  *  dmi_decode or dmi_string
78                  */
79                 data+=dm->length;
80                 while(data-buf<len-1 && (data[0] || data[1]))
81                         data++;
82                 if(data-buf<len-1)
83                         decode(dm);
84                 data+=2;
85                 i++;
86         }
87         bt_iounmap(buf, len);
88         return 0;
89 }
90
91
92 inline static int __init dmi_checksum(u8 *buf)
93 {
94         u8 sum=0;
95         int a;
96         
97         for(a=0; a<15; a++)
98                 sum+=buf[a];
99         return (sum==0);
100 }
101
102 static int __init dmi_iterate(void (*decode)(struct dmi_header *))
103 {
104         u8 buf[15];
105         u32 fp=0xF0000;
106
107         while (fp < 0xFFFFF)
108         {
109                 isa_memcpy_fromio(buf, fp, 15);
110                 if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
111                 {
112                         u16 num=buf[13]<<8|buf[12];
113                         u16 len=buf[7]<<8|buf[6];
114                         u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
115
116                         /*
117                          * DMI version 0.0 means that the real version is taken from
118                          * the SMBIOS version, which we don't know at this point.
119                          */
120                         if(buf[14]!=0)
121                                 printk(KERN_INFO "DMI %d.%d present.\n",
122                                         buf[14]>>4, buf[14]&0x0F);
123                         else
124                                 printk(KERN_INFO "DMI present.\n");
125                         dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
126                                 num, len));
127                         dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
128                                 base));
129                         if(dmi_table(base,len, num, decode)==0)
130                                 return 0;
131                 }
132                 fp+=16;
133         }
134         return -1;
135 }
136
137 static char *dmi_ident[DMI_STRING_MAX];
138
139 /*
140  *      Save a DMI string
141  */
142  
143 static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
144 {
145         char *d = (char*)dm;
146         char *p = dmi_string(dm, d[string]);
147         if(p==NULL || *p == 0)
148                 return;
149         if (dmi_ident[slot])
150                 return;
151         dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
152         if(dmi_ident[slot])
153                 strcpy(dmi_ident[slot], p);
154         else
155                 printk(KERN_ERR "dmi_save_ident: out of memory.\n");
156 }
157
158 /*
159  * Ugly compatibility crap.
160  */
161 #define dmi_blacklist   dmi_system_id
162 #define NO_MATCH        { DMI_NONE, NULL}
163 #define MATCH           DMI_MATCH
164
165 /*
166  * Some machines, usually laptops, can't handle an enabled local APIC.
167  * The symptoms include hangs or reboots when suspending or resuming,
168  * attaching or detaching the power cord, or entering BIOS setup screens
169  * through magic key sequences.
170  */
171 static int __init local_apic_kills_bios(struct dmi_blacklist *d)
172 {
173 #ifdef CONFIG_X86_LOCAL_APIC
174         extern int enable_local_apic;
175         if (enable_local_apic == 0) {
176                 enable_local_apic = -1;
177                 printk(KERN_WARNING "%s with broken BIOS detected. "
178                        "Refusing to enable the local APIC.\n",
179                        d->ident);
180         }
181 #endif
182         return 0;
183 }
184
185
186 /*
187  * Toshiba keyboard likes to repeat keys when they are not repeated.
188  */
189
190 static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
191 {
192         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");
193         return 0;
194 }
195
196
197 #ifdef CONFIG_ACPI_SLEEP
198 static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
199 {
200         /* See acpi_wakeup.S */
201         extern long acpi_video_flags;
202         acpi_video_flags |= 2;
203         return 0;
204 }
205 #endif
206
207
208 #ifdef  CONFIG_ACPI_BOOT
209 extern int acpi_force;
210
211 static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) 
212
213         if (!acpi_force) { 
214                 printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
215                 disable_acpi();
216         } else { 
217                 printk(KERN_NOTICE 
218                        "Warning: DMI blacklist says broken, but acpi forced\n"); 
219         }
220         return 0;
221
222
223 /*
224  * Limit ACPI to CPU enumeration for HT
225  */
226 static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) 
227
228         if (!acpi_force) { 
229                 printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); 
230                 disable_acpi();
231                 acpi_ht = 1; 
232         } else { 
233                 printk(KERN_NOTICE 
234                        "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); 
235         }
236         return 0;
237
238
239 /*
240  * early nForce2 reference BIOS shipped with a
241  * bogus ACPI IRQ0 -> pin2 interrupt override -- ignore it
242  */
243 static __init int ignore_timer_override(struct dmi_blacklist *d)
244 {
245         extern int acpi_skip_timer_override;
246         printk(KERN_NOTICE "%s detected: BIOS IRQ0 pin2 override"
247                 " will be ignored\n", d->ident);        
248
249         acpi_skip_timer_override = 1;
250         return 0;
251 }
252 #endif
253
254 #ifdef  CONFIG_ACPI_PCI
255 static __init int disable_acpi_irq(struct dmi_blacklist *d) 
256 {
257         if (!acpi_force) {
258                 printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
259                        d->ident);       
260                 acpi_noirq_set();
261         }
262         return 0;
263 }
264 static __init int disable_acpi_pci(struct dmi_blacklist *d) 
265 {
266         if (!acpi_force) {
267                 printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
268                        d->ident);       
269                 acpi_disable_pci();
270         }
271         return 0;
272 }  
273 #endif
274
275 /*
276  *      Process the DMI blacklists
277  */
278  
279
280 /*
281  *      This will be expanded over time to force things like the APM 
282  *      interrupt mask settings according to the laptop
283  */
284  
285 static __initdata struct dmi_blacklist dmi_blacklist[]={
286
287         /* Machines which have problems handling enabled local APICs */
288
289         { local_apic_kills_bios, "Dell Inspiron", {
290                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
291                         MATCH(DMI_PRODUCT_NAME, "Inspiron"),
292                         NO_MATCH, NO_MATCH
293                         } },
294
295         { local_apic_kills_bios, "Dell Latitude", {
296                         MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
297                         MATCH(DMI_PRODUCT_NAME, "Latitude"),
298                         NO_MATCH, NO_MATCH
299                         } },
300
301         { local_apic_kills_bios, "IBM Thinkpad T20", {
302                         MATCH(DMI_BOARD_VENDOR, "IBM"),
303                         MATCH(DMI_BOARD_NAME, "264741U"),
304                         NO_MATCH, NO_MATCH
305                         } },
306
307         { local_apic_kills_bios, "ASUS L3C", {
308                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
309                         MATCH(DMI_BOARD_NAME, "P4_L3C"),
310                         NO_MATCH, NO_MATCH
311                         } },
312
313         { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
314                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
315                         NO_MATCH, NO_MATCH, NO_MATCH
316                         } },
317 #ifdef CONFIG_ACPI_SLEEP
318         { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
319                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
320                         NO_MATCH, NO_MATCH, NO_MATCH
321                         } },
322 #endif
323
324 #ifdef  CONFIG_ACPI_BOOT
325         /*
326          * If your system is blacklisted here, but you find that acpi=force
327          * works for you, please contact acpi-devel@sourceforge.net
328          */
329
330         /*
331          *      Boxes that need ACPI disabled
332          */
333
334         { dmi_disable_acpi, "IBM Thinkpad", {
335                         MATCH(DMI_BOARD_VENDOR, "IBM"),
336                         MATCH(DMI_BOARD_NAME, "2629H1G"),
337                         NO_MATCH, NO_MATCH }},
338
339         /*
340          *      Boxes that need acpi=ht 
341          */
342
343         { force_acpi_ht, "FSC Primergy T850", {
344                         MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
345                         MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
346                         NO_MATCH, NO_MATCH }},
347
348         { force_acpi_ht, "DELL GX240", {
349                         MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
350                         MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
351                         NO_MATCH, NO_MATCH }},
352
353         { force_acpi_ht, "HP VISUALIZE NT Workstation", {
354                         MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
355                         MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
356                         NO_MATCH, NO_MATCH }},
357
358         { force_acpi_ht, "Compaq Workstation W8000", {
359                         MATCH(DMI_SYS_VENDOR, "Compaq"),
360                         MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
361                         NO_MATCH, NO_MATCH }},
362
363         { force_acpi_ht, "ASUS P4B266", {
364                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
365                         MATCH(DMI_BOARD_NAME, "P4B266"),
366                         NO_MATCH, NO_MATCH }},
367
368         { force_acpi_ht, "ASUS P2B-DS", {
369                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
370                         MATCH(DMI_BOARD_NAME, "P2B-DS"),
371                         NO_MATCH, NO_MATCH }},
372
373         { force_acpi_ht, "ASUS CUR-DLS", {
374                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
375                         MATCH(DMI_BOARD_NAME, "CUR-DLS"),
376                         NO_MATCH, NO_MATCH }},
377
378         { force_acpi_ht, "ABIT i440BX-W83977", {
379                         MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
380                         MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
381                         NO_MATCH, NO_MATCH }},
382
383         { force_acpi_ht, "IBM Bladecenter", {
384                         MATCH(DMI_BOARD_VENDOR, "IBM"),
385                         MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
386                         NO_MATCH, NO_MATCH }},
387
388         { force_acpi_ht, "IBM eServer xSeries 360", {
389                         MATCH(DMI_BOARD_VENDOR, "IBM"),
390                         MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
391                         NO_MATCH, NO_MATCH }},
392
393         { force_acpi_ht, "IBM eserver xSeries 330", {
394                         MATCH(DMI_BOARD_VENDOR, "IBM"),
395                         MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
396                         NO_MATCH, NO_MATCH }},
397
398         { force_acpi_ht, "IBM eserver xSeries 440", {
399                         MATCH(DMI_BOARD_VENDOR, "IBM"),
400                         MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
401                         NO_MATCH, NO_MATCH }},
402
403         /*
404          * Systems with nForce2 BIOS timer override bug
405          * nVidia claims all nForce have timer on pin0,
406          * and applying this workaround is a NOP on fixed BIOS,
407          * so prospects are good for replacing these entries
408          * with something to key of chipset PCI-ID.
409          */
410         { ignore_timer_override, "Abit NF7-S v2", {
411                         MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
412                         MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
413                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
414                         MATCH(DMI_BIOS_DATE, "03/24/2004") }},
415
416         { ignore_timer_override, "Asus A7N8X v2", {
417                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
418                         MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
419                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
420                         MATCH(DMI_BIOS_DATE, "10/06/2003") }},
421
422         { ignore_timer_override, "Asus A7N8X-X", {
423                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
424                         MATCH(DMI_BOARD_NAME, "A7N8X-X"),
425                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"),
426                         MATCH(DMI_BIOS_DATE, "2/3/2004") }},
427
428         { ignore_timer_override, "MSI K7N2-Delta", {
429                         MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
430                         MATCH(DMI_BOARD_NAME, "MS-6570"),
431                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
432                         MATCH(DMI_BIOS_DATE, "03/29/2004") }},
433
434         { ignore_timer_override, "Shuttle SN41G2", {
435                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
436                         MATCH(DMI_BOARD_NAME, "FN41"),
437                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
438                         MATCH(DMI_BIOS_DATE, "01/14/2004") }},
439
440         { ignore_timer_override, "Shuttle AN35N", {
441                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
442                         MATCH(DMI_BOARD_NAME, "AN35"),
443                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
444                         MATCH(DMI_BIOS_DATE, "12/05/2003") }},
445 #endif  // CONFIG_ACPI_BOOT
446
447 #ifdef  CONFIG_ACPI_PCI
448         /*
449          *      Boxes that need ACPI PCI IRQ routing disabled
450          */
451
452         { disable_acpi_irq, "ASUS A7V", {
453                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
454                         MATCH(DMI_BOARD_NAME, "<A7V>"),
455                         /* newer BIOS, Revision 1011, does work */
456                         MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
457                         NO_MATCH }},
458
459         /*
460          *      Boxes that need ACPI PCI IRQ routing and PCI scan disabled
461          */
462         { disable_acpi_pci, "ASUS PR-DLS", {    /* _BBN 0 bug */
463                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
464                         MATCH(DMI_BOARD_NAME, "PR-DLS"),
465                         MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
466                         MATCH(DMI_BIOS_DATE, "03/21/2003") }},
467
468         { disable_acpi_pci, "Acer TravelMate 36x Laptop", {
469                         MATCH(DMI_SYS_VENDOR, "Acer"),
470                         MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
471                         NO_MATCH, NO_MATCH
472                         } },
473
474 #endif
475
476         { NULL, }
477 };
478         
479         
480 /*
481  *      Walk the blacklist table running matching functions until someone 
482  *      returns 1 or we hit the end.
483  */
484  
485
486 static __init void dmi_check_blacklist(void)
487 {
488 #ifdef  CONFIG_ACPI_BOOT
489 #define ACPI_BLACKLIST_CUTOFF_YEAR      2001
490
491         if (dmi_ident[DMI_BIOS_DATE]) { 
492                 char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
493                 if (s) { 
494                         int year, disable = 0;
495                         s++; 
496                         year = simple_strtoul(s,NULL,0); 
497                         if (year >= 1000) 
498                                 disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
499                         else if (year < 1 || (year > 90 && year <= 99))
500                                 disable = 1; 
501                         if (disable && !acpi_force) { 
502                                 printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
503                                 printk(KERN_NOTICE "You can enable it with acpi=force\n");
504                                 disable_acpi();
505                         } 
506                 }
507         }
508 #endif
509         dmi_check_system(dmi_blacklist);
510 }
511
512         
513
514 /*
515  *      Process a DMI table entry. Right now all we care about are the BIOS
516  *      and machine entries. For 2.5 we should pull the smbus controller info
517  *      out of here.
518  */
519
520 static void __init dmi_decode(struct dmi_header *dm)
521 {
522 #ifdef DMI_DEBUG
523         u8 *data = (u8 *)dm;
524 #endif
525         
526         switch(dm->type)
527         {
528                 case  0:
529                         dmi_printk(("BIOS Vendor: %s\n",
530                                 dmi_string(dm, data[4])));
531                         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
532                         dmi_printk(("BIOS Version: %s\n", 
533                                 dmi_string(dm, data[5])));
534                         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
535                         dmi_printk(("BIOS Release: %s\n",
536                                 dmi_string(dm, data[8])));
537                         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
538                         break;
539                 case 1:
540                         dmi_printk(("System Vendor: %s\n",
541                                 dmi_string(dm, data[4])));
542                         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
543                         dmi_printk(("Product Name: %s\n",
544                                 dmi_string(dm, data[5])));
545                         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
546                         dmi_printk(("Version: %s\n",
547                                 dmi_string(dm, data[6])));
548                         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
549                         dmi_printk(("Serial Number: %s\n",
550                                 dmi_string(dm, data[7])));
551                         break;
552                 case 2:
553                         dmi_printk(("Board Vendor: %s\n",
554                                 dmi_string(dm, data[4])));
555                         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
556                         dmi_printk(("Board Name: %s\n",
557                                 dmi_string(dm, data[5])));
558                         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
559                         dmi_printk(("Board Version: %s\n",
560                                 dmi_string(dm, data[6])));
561                         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
562                         break;
563         }
564 }
565
566 void __init dmi_scan_machine(void)
567 {
568         int err = dmi_iterate(dmi_decode);
569         if(err == 0)
570                 dmi_check_blacklist();
571         else
572                 printk(KERN_INFO "DMI not present.\n");
573 }
574
575
576 /**
577  *      dmi_check_system - check system DMI data
578  *      @list: array of dmi_system_id structures to match against
579  *
580  *      Walk the blacklist table running matching functions until someone
581  *      returns non zero or we hit the end. Callback function is called for
582  *      each successfull match. Returns the number of matches.
583  */
584 int dmi_check_system(struct dmi_system_id *list)
585 {
586         int i, count = 0;
587         struct dmi_system_id *d = list;
588
589         while (d->ident) {
590                 for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
591                         int s = d->matches[i].slot;
592                         if (s == DMI_NONE)
593                                 continue;
594                         if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
595                                 continue;
596                         /* No match */
597                         goto fail;
598                 }
599                 if (d->callback && d->callback(d))
600                         break;
601                 count++;
602 fail:           d++;
603         }
604
605         return count;
606 }
607
608 EXPORT_SYMBOL(dmi_check_system);
609
610 /**
611  *      dmi_get_system_info - return DMI data value
612  *      @field: data index (see enum dmi_filed)
613  *
614  *      Returns one DMI data value, can be used to perform
615  *      complex DMI data checks.
616  */
617 char * dmi_get_system_info(int field)
618 {
619         return dmi_ident[field];
620 }
621
622 EXPORT_SYMBOL(dmi_get_system_info);