vserver 1.9.3
[linux-2.6.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 <linux/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 ProLiant DL380 G2", {
312                         MATCH(DMI_SYS_VENDOR, "Compaq"),
313                         MATCH(DMI_PRODUCT_NAME, "ProLiant DL380 G2"),
314                         NO_MATCH, NO_MATCH }},
315
316         { force_acpi_ht, "Compaq ProLiant ML530 G2", {
317                         MATCH(DMI_SYS_VENDOR, "Compaq"),
318                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML530 G2"),
319                         NO_MATCH, NO_MATCH }},
320
321         { force_acpi_ht, "Compaq ProLiant ML350 G3", {
322                         MATCH(DMI_SYS_VENDOR, "Compaq"),
323                         MATCH(DMI_PRODUCT_NAME, "ProLiant ML350 G3"),
324                         NO_MATCH, NO_MATCH }},
325
326         { force_acpi_ht, "Compaq Workstation W8000", {
327                         MATCH(DMI_SYS_VENDOR, "Compaq"),
328                         MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
329                         NO_MATCH, NO_MATCH }},
330
331         { force_acpi_ht, "ASUS P4B266", {
332                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
333                         MATCH(DMI_BOARD_NAME, "P4B266"),
334                         NO_MATCH, NO_MATCH }},
335
336         { force_acpi_ht, "ASUS P2B-DS", {
337                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
338                         MATCH(DMI_BOARD_NAME, "P2B-DS"),
339                         NO_MATCH, NO_MATCH }},
340
341         { force_acpi_ht, "ASUS CUR-DLS", {
342                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
343                         MATCH(DMI_BOARD_NAME, "CUR-DLS"),
344                         NO_MATCH, NO_MATCH }},
345
346         { force_acpi_ht, "ABIT i440BX-W83977", {
347                         MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
348                         MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
349                         NO_MATCH, NO_MATCH }},
350
351         { force_acpi_ht, "IBM Bladecenter", {
352                         MATCH(DMI_BOARD_VENDOR, "IBM"),
353                         MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
354                         NO_MATCH, NO_MATCH }},
355
356         { force_acpi_ht, "IBM eServer xSeries 360", {
357                         MATCH(DMI_BOARD_VENDOR, "IBM"),
358                         MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
359                         NO_MATCH, NO_MATCH }},
360
361         { force_acpi_ht, "IBM eserver xSeries 330", {
362                         MATCH(DMI_BOARD_VENDOR, "IBM"),
363                         MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
364                         NO_MATCH, NO_MATCH }},
365
366         { force_acpi_ht, "IBM eserver xSeries 440", {
367                         MATCH(DMI_BOARD_VENDOR, "IBM"),
368                         MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
369                         NO_MATCH, NO_MATCH }},
370
371         /*
372          * Systems with nForce2 BIOS timer override bug
373          * nVidia claims all nForce have timer on pin0,
374          * and applying this workaround is a NOP on fixed BIOS,
375          * so prospects are good for replacing these entries
376          * with something to key of chipset PCI-ID.
377          */
378         { ignore_timer_override, "Abit NF7-S v2", {
379                         MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"),
380                         MATCH(DMI_BOARD_NAME, "NF7-S/NF7,NF7-V (nVidia-nForce2)"),
381                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
382                         MATCH(DMI_BIOS_DATE, "03/24/2004") }},
383
384         { ignore_timer_override, "Asus A7N8X v2", {
385                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
386                         MATCH(DMI_BOARD_NAME, "A7N8X2.0"),
387                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X2.0 Deluxe ACPI BIOS Rev 1007"),
388                         MATCH(DMI_BIOS_DATE, "10/06/2003") }},
389
390         { ignore_timer_override, "Asus A7N8X-X", {
391                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
392                         MATCH(DMI_BOARD_NAME, "A7N8X-X"),
393                         MATCH(DMI_BIOS_VERSION, "ASUS A7N8X-X ACPI BIOS Rev 1009"),
394                         MATCH(DMI_BIOS_DATE, "2/3/2004") }},
395
396         { ignore_timer_override, "MSI K7N2-Delta", {
397                         MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
398                         MATCH(DMI_BOARD_NAME, "MS-6570"),
399                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
400                         MATCH(DMI_BIOS_DATE, "03/29/2004") }},
401
402         { ignore_timer_override, "Shuttle SN41G2", {
403                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
404                         MATCH(DMI_BOARD_NAME, "FN41"),
405                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
406                         MATCH(DMI_BIOS_DATE, "01/14/2004") }},
407
408         { ignore_timer_override, "Shuttle AN35N", {
409                         MATCH(DMI_BOARD_VENDOR, "Shuttle Inc"),
410                         MATCH(DMI_BOARD_NAME, "AN35"),
411                         MATCH(DMI_BIOS_VERSION, "6.00 PG"),
412                         MATCH(DMI_BIOS_DATE, "12/05/2003") }},
413 #endif  // CONFIG_ACPI_BOOT
414
415 #ifdef  CONFIG_ACPI_PCI
416         /*
417          *      Boxes that need ACPI PCI IRQ routing disabled
418          */
419
420         { disable_acpi_irq, "ASUS A7V", {
421                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
422                         MATCH(DMI_BOARD_NAME, "<A7V>"),
423                         /* newer BIOS, Revision 1011, does work */
424                         MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
425                         NO_MATCH }},
426
427         /*
428          *      Boxes that need ACPI PCI IRQ routing and PCI scan disabled
429          */
430         { disable_acpi_pci, "ASUS PR-DLS", {    /* _BBN 0 bug */
431                         MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
432                         MATCH(DMI_BOARD_NAME, "PR-DLS"),
433                         MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
434                         MATCH(DMI_BIOS_DATE, "03/21/2003") }},
435
436         { disable_acpi_pci, "Acer TravelMate 36x Laptop", {
437                         MATCH(DMI_SYS_VENDOR, "Acer"),
438                         MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
439                         NO_MATCH, NO_MATCH
440                         } },
441
442 #endif
443
444         { NULL, }
445 };
446
447 /*
448  *      Process a DMI table entry. Right now all we care about are the BIOS
449  *      and machine entries. For 2.5 we should pull the smbus controller info
450  *      out of here.
451  */
452
453 static void __init dmi_decode(struct dmi_header *dm)
454 {
455 #ifdef DMI_DEBUG
456         u8 *data = (u8 *)dm;
457 #endif
458         
459         switch(dm->type)
460         {
461                 case  0:
462                         dmi_printk(("BIOS Vendor: %s\n",
463                                 dmi_string(dm, data[4])));
464                         dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
465                         dmi_printk(("BIOS Version: %s\n", 
466                                 dmi_string(dm, data[5])));
467                         dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
468                         dmi_printk(("BIOS Release: %s\n",
469                                 dmi_string(dm, data[8])));
470                         dmi_save_ident(dm, DMI_BIOS_DATE, 8);
471                         break;
472                 case 1:
473                         dmi_printk(("System Vendor: %s\n",
474                                 dmi_string(dm, data[4])));
475                         dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
476                         dmi_printk(("Product Name: %s\n",
477                                 dmi_string(dm, data[5])));
478                         dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
479                         dmi_printk(("Version: %s\n",
480                                 dmi_string(dm, data[6])));
481                         dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
482                         dmi_printk(("Serial Number: %s\n",
483                                 dmi_string(dm, data[7])));
484                         break;
485                 case 2:
486                         dmi_printk(("Board Vendor: %s\n",
487                                 dmi_string(dm, data[4])));
488                         dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
489                         dmi_printk(("Board Name: %s\n",
490                                 dmi_string(dm, data[5])));
491                         dmi_save_ident(dm, DMI_BOARD_NAME, 5);
492                         dmi_printk(("Board Version: %s\n",
493                                 dmi_string(dm, data[6])));
494                         dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
495                         break;
496         }
497 }
498
499 void __init dmi_scan_machine(void)
500 {
501         int err = dmi_iterate(dmi_decode);
502         if(err == 0)
503                 dmi_check_system(dmi_blacklist);
504         else
505                 printk(KERN_INFO "DMI not present.\n");
506 }
507
508
509 /**
510  *      dmi_check_system - check system DMI data
511  *      @list: array of dmi_system_id structures to match against
512  *
513  *      Walk the blacklist table running matching functions until someone
514  *      returns non zero or we hit the end. Callback function is called for
515  *      each successfull match. Returns the number of matches.
516  */
517 int dmi_check_system(struct dmi_system_id *list)
518 {
519         int i, count = 0;
520         struct dmi_system_id *d = list;
521
522         while (d->ident) {
523                 for (i = 0; i < ARRAY_SIZE(d->matches); i++) {
524                         int s = d->matches[i].slot;
525                         if (s == DMI_NONE)
526                                 continue;
527                         if (dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
528                                 continue;
529                         /* No match */
530                         goto fail;
531                 }
532                 if (d->callback && d->callback(d))
533                         break;
534                 count++;
535 fail:           d++;
536         }
537
538         return count;
539 }
540
541 EXPORT_SYMBOL(dmi_check_system);
542
543 /**
544  *      dmi_get_system_info - return DMI data value
545  *      @field: data index (see enum dmi_filed)
546  *
547  *      Returns one DMI data value, can be used to perform
548  *      complex DMI data checks.
549  */
550 char * dmi_get_system_info(int field)
551 {
552         return dmi_ident[field];
553 }
554
555 EXPORT_SYMBOL(dmi_get_system_info);