update to 2.6.9-rc1
[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  * Toshiba keyboard likes to repeat keys when they are not repeated.
167  */
168
169 static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
170 {
171         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");
172         return 0;
173 }
174
175
176 #ifdef CONFIG_ACPI_SLEEP
177 static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
178 {
179         /* See acpi_wakeup.S */
180         extern long acpi_video_flags;
181         acpi_video_flags |= 2;
182         return 0;
183 }
184 #endif
185
186
187 #ifdef  CONFIG_ACPI_BOOT
188 extern int acpi_force;
189
190 static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) 
191
192         if (!acpi_force) { 
193                 printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
194                 disable_acpi();
195         } else { 
196                 printk(KERN_NOTICE 
197                        "Warning: DMI blacklist says broken, but acpi forced\n"); 
198         }
199         return 0;
200
201
202 /*
203  * Limit ACPI to CPU enumeration for HT
204  */
205 static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) 
206
207         if (!acpi_force) { 
208                 printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); 
209                 disable_acpi();
210                 acpi_ht = 1; 
211         } else { 
212                 printk(KERN_NOTICE 
213                        "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); 
214         }
215         return 0;
216
217
218 /*
219  * early nForce2 reference BIOS shipped with a
220  * bogus ACPI IRQ0 -> pin2 interrupt override -- ignore it
221  */
222 static __init int ignore_timer_override(struct dmi_blacklist *d)
223 {
224         extern int acpi_skip_timer_override;
225         printk(KERN_NOTICE "%s detected: BIOS IRQ0 pin2 override"
226                 " will be ignored\n", d->ident);        
227
228         acpi_skip_timer_override = 1;
229         return 0;
230 }
231 #endif
232
233 #ifdef  CONFIG_ACPI_PCI
234 static __init int disable_acpi_irq(struct dmi_blacklist *d) 
235 {
236         if (!acpi_force) {
237                 printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
238                        d->ident);       
239                 acpi_noirq_set();
240         }
241         return 0;
242 }
243 static __init int disable_acpi_pci(struct dmi_blacklist *d) 
244 {
245         if (!acpi_force) {
246                 printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
247                        d->ident);       
248                 acpi_disable_pci();
249         }
250         return 0;
251 }  
252 #endif
253
254 /*
255  *      Process the DMI blacklists
256  */
257  
258
259 /*
260  *      This will be expanded over time to force things like the APM 
261  *      interrupt mask settings according to the laptop
262  */
263  
264 static __initdata struct dmi_blacklist dmi_blacklist[]={
265
266         { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
267                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
268                         NO_MATCH, NO_MATCH, NO_MATCH
269                         } },
270 #ifdef CONFIG_ACPI_SLEEP
271         { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
272                         MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
273                         NO_MATCH, NO_MATCH, NO_MATCH
274                         } },
275 #endif
276
277 #ifdef  CONFIG_ACPI_BOOT
278         /*
279          * If your system is blacklisted here, but you find that acpi=force
280          * works for you, please contact acpi-devel@sourceforge.net
281          */
282
283         /*
284          *      Boxes that need ACPI disabled
285          */
286
287         { dmi_disable_acpi, "IBM Thinkpad", {
288                         MATCH(DMI_BOARD_VENDOR, "IBM"),
289                         MATCH(DMI_BOARD_NAME, "2629H1G"),
290                         NO_MATCH, NO_MATCH }},
291
292         /*
293          *      Boxes that need acpi=ht 
294          */
295
296         { force_acpi_ht, "FSC Primergy T850", {
297                         MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
298                         MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
299                         NO_MATCH, NO_MATCH }},
300
301         { force_acpi_ht, "DELL GX240", {
302                         MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
303                         MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
304                         NO_MATCH, NO_MATCH }},
305
306         { force_acpi_ht, "HP VISUALIZE NT Workstation", {
307                         MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
308                         MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
309                         NO_MATCH, NO_MATCH }},
310
311         { force_acpi_ht, "Compaq Workstation W8000", {
312                         MATCH(DMI_SYS_VENDOR, "Compaq"),
313                         MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
314                         NO_MATCH, NO_MATCH }},
315
316         { force_acpi_ht, "ASUS P4B266", {
317                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
318                         MATCH(DMI_BOARD_NAME, "P4B266"),
319                         NO_MATCH, NO_MATCH }},
320
321         { force_acpi_ht, "ASUS P2B-DS", {
322                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
323                         MATCH(DMI_BOARD_NAME, "P2B-DS"),
324                         NO_MATCH, NO_MATCH }},
325
326         { force_acpi_ht, "ASUS CUR-DLS", {
327                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
328                         MATCH(DMI_BOARD_NAME, "CUR-DLS"),
329                         NO_MATCH, NO_MATCH }},
330
331         { force_acpi_ht, "ABIT i440BX-W83977", {
332                         MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
333                         MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
334                         NO_MATCH, NO_MATCH }},
335
336         { force_acpi_ht, "IBM Bladecenter", {
337                         MATCH(DMI_BOARD_VENDOR, "IBM"),
338                         MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
339                         NO_MATCH, NO_MATCH }},
340
341         { force_acpi_ht, "IBM eServer xSeries 360", {
342                         MATCH(DMI_BOARD_VENDOR, "IBM"),
343                         MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
344                         NO_MATCH, NO_MATCH }},
345
346         { force_acpi_ht, "IBM eserver xSeries 330", {
347                         MATCH(DMI_BOARD_VENDOR, "IBM"),
348                         MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
349                         NO_MATCH, NO_MATCH }},
350
351         { force_acpi_ht, "IBM eserver xSeries 440", {
352                         MATCH(DMI_BOARD_VENDOR, "IBM"),
353                         MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
354                         NO_MATCH, NO_MATCH }},
355
356         /*
357          * Systems with nForce2 BIOS timer override bug
358          * nVidia claims all nForce have timer on pin0,
359          * and applying this workaround is a NOP on fixed BIOS,
360          * so prospects are good for replacing these entries
361          * with something to key of chipset PCI-ID.
362          */
363         { ignore_timer_override, "Abit NF7-S v2", {
364                         MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
365                         MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
366                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
367                         MATCH(DMI_BIOS_DATE, "03/24/2004") }},
368
369         { ignore_timer_override, "Asus A7N8X v2", {
370                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
371                         MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
372                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
373                         MATCH(DMI_BIOS_DATE, "10/06/2003") }},
374
375         { ignore_timer_override, "Asus A7N8X-X", {
376                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
377                         MATCH(DMI_BOARD_NAME, "A7N8X-X"),
378                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"),
379                         MATCH(DMI_BIOS_DATE, "2/3/2004") }},
380
381         { ignore_timer_override, "MSI K7N2-Delta", {
382                         MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
383                         MATCH(DMI_BOARD_NAME, "MS-6570"),
384                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
385                         MATCH(DMI_BIOS_DATE, "03/29/2004") }},
386
387         { ignore_timer_override, "Shuttle SN41G2", {
388                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
389                         MATCH(DMI_BOARD_NAME, "FN41"),
390                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
391                         MATCH(DMI_BIOS_DATE, "01/14/2004") }},
392
393         { ignore_timer_override, "Shuttle AN35N", {
394                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
395                         MATCH(DMI_BOARD_NAME, "AN35"),
396                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
397                         MATCH(DMI_BIOS_DATE, "12/05/2003") }},
398 #endif  // CONFIG_ACPI_BOOT
399
400 #ifdef  CONFIG_ACPI_PCI
401         /*
402          *      Boxes that need ACPI PCI IRQ routing disabled
403          */
404
405         { disable_acpi_irq, "ASUS A7V", {
406                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
407                         MATCH(DMI_BOARD_NAME, "<A7V>"),
408                         /* newer BIOS, Revision 1011, does work */
409                         MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
410                         NO_MATCH }},
411
412         /*
413          *      Boxes that need ACPI PCI IRQ routing and PCI scan disabled
414          */
415         { disable_acpi_pci, "ASUS PR-DLS", {    /* _BBN 0 bug */
416                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
417                         MATCH(DMI_BOARD_NAME, "PR-DLS"),
418                         MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
419                         MATCH(DMI_BIOS_DATE, "03/21/2003") }},
420
421         { disable_acpi_pci, "Acer TravelMate 36x Laptop", {
422                         MATCH(DMI_SYS_VENDOR, "Acer"),
423                         MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
424                         NO_MATCH, NO_MATCH
425                         } },
426
427 #endif
428
429         { NULL, }
430 };
431         
432         
433 /*
434  *      Walk the blacklist table running matching functions until someone 
435  *      returns 1 or we hit the end.
436  */
437  
438
439 static __init void dmi_check_blacklist(void)
440 {
441 #ifdef  CONFIG_ACPI_BOOT
442 #define ACPI_BLACKLIST_CUTOFF_YEAR      2001
443
444         if (dmi_ident[DMI_BIOS_DATE]) { 
445                 char *s = strrchr(dmi_ident[DMI_BIOS_DATE], '/'); 
446                 if (s) { 
447                         int year, disable = 0;
448                         s++; 
449                         year = simple_strtoul(s,NULL,0); 
450                         if (year >= 1000) 
451                                 disable = year < ACPI_BLACKLIST_CUTOFF_YEAR; 
452                         else if (year < 1 || (year > 90 && year <= 99))
453                                 disable = 1; 
454                         if (disable && !acpi_force) { 
455                                 printk(KERN_NOTICE "ACPI disabled because your bios is from %s and too old\n", s);
456                                 printk(KERN_NOTICE "You can enable it with acpi=force\n");
457                                 disable_acpi();
458                         } 
459                 }
460         }
461 #endif
462         dmi_check_system(dmi_blacklist);
463 }
464
465         
466
467 /*
468  *      Process a DMI table entry. Right now all we care about are the BIOS
469  *      and machine entries. For 2.5 we should pull the smbus controller info
470  *      out of here.
471  */
472
473 static void __init dmi_decode(struct dmi_header *dm)
474 {
475 #ifdef DMI_DEBUG
476         u8 *data = (u8 *)dm;
477 #endif
478         
479         switch(dm->type)
480         {
481                 case  0:
482                         dmi_printk(("BIOS Vendor: %s\n",
483                                 dmi_string(dm, data[4])));
484                         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
485                         dmi_printk(("BIOS Version: %s\n", 
486                                 dmi_string(dm, data[5])));
487                         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
488                         dmi_printk(("BIOS Release: %s\n",
489                                 dmi_string(dm, data[8])));
490                         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
491                         break;
492                 case 1:
493                         dmi_printk(("System Vendor: %s\n",
494                                 dmi_string(dm, data[4])));
495                         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
496                         dmi_printk(("Product Name: %s\n",
497                                 dmi_string(dm, data[5])));
498                         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
499                         dmi_printk(("Version: %s\n",
500                                 dmi_string(dm, data[6])));
501                         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
502                         dmi_printk(("Serial Number: %s\n",
503                                 dmi_string(dm, data[7])));
504                         break;
505                 case 2:
506                         dmi_printk(("Board Vendor: %s\n",
507                                 dmi_string(dm, data[4])));
508                         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
509                         dmi_printk(("Board Name: %s\n",
510                                 dmi_string(dm, data[5])));
511                         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
512                         dmi_printk(("Board Version: %s\n",
513                                 dmi_string(dm, data[6])));
514                         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
515                         break;
516         }
517 }
518
519 void __init dmi_scan_machine(void)
520 {
521         int err = dmi_iterate(dmi_decode);
522         if(err == 0)
523                 dmi_check_blacklist();
524         else
525                 printk(KERN_INFO "DMI not present.\n");
526 }
527
528
529 /**
530  *      dmi_check_system - check system DMI data
531  *      @list: array of dmi_system_id structures to match against
532  *
533  *      Walk the blacklist table running matching functions until someone
534  *      returns non zero or we hit the end. Callback function is called for
535  *      each successfull match. Returns the number of matches.
536  */
537 int dmi_check_system(struct dmi_system_id *list)
538 {
539         int i, count = 0;
540         struct dmi_system_id *d = list;
541
542         while (d->ident) {
543                 for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
544                         int s = d->matches[i].slot;
545                         if (s == DMI_NONE)
546                                 continue;
547                         if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
548                                 continue;
549                         /* No match */
550                         goto fail;
551                 }
552                 if (d->callback && d->callback(d))
553                         break;
554                 count++;
555 fail:           d++;
556         }
557
558         return count;
559 }
560
561 EXPORT_SYMBOL(dmi_check_system);
562
563 /**
564  *      dmi_get_system_info - return DMI data value
565  *      @field: data index (see enum dmi_filed)
566  *
567  *      Returns one DMI data value, can be used to perform
568  *      complex DMI data checks.
569  */
570 char * dmi_get_system_info(int field)
571 {
572         return dmi_ident[field];
573 }
574
575 EXPORT_SYMBOL(dmi_get_system_info);