dmi_scan.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:24k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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/apm_bios.h>
  7. #include <linux/slab.h>
  8. #include <asm/io.h>
  9. #include <linux/pm.h>
  10. #include <asm/keyboard.h>
  11. #include <asm/system.h>
  12. #include <linux/bootmem.h>
  13. unsigned long dmi_broken;
  14. int is_sony_vaio_laptop;
  15. struct dmi_header
  16. {
  17. u8 type;
  18. u8 length;
  19. u16 handle;
  20. };
  21. #define dmi_printk(x)
  22. //#define dmi_printk(x) printk x
  23. static char * __init dmi_string(struct dmi_header *dm, u8 s)
  24. {
  25. u8 *bp=(u8 *)dm;
  26. bp+=dm->length;
  27. if(!s)
  28. return "";
  29. s--;
  30. while(s>0 && *bp)
  31. {
  32. bp+=strlen(bp);
  33. bp++;
  34. s--;
  35. }
  36. return bp;
  37. }
  38. /*
  39.  * We have to be cautious here. We have seen BIOSes with DMI pointers
  40.  * pointing to completely the wrong place for example
  41.  */
  42.  
  43. static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
  44. {
  45. u8 *buf;
  46. struct dmi_header *dm;
  47. u8 *data;
  48. int i=0;
  49. buf = bt_ioremap(base, len);
  50. if(buf==NULL)
  51. return -1;
  52. data = buf;
  53. /*
  54.    * Stop when we see all the items the table claimed to have
  55.    * OR we run off the end of the table (also happens)
  56.    */
  57.  
  58. while(i<num && data-buf+sizeof(struct dmi_header)<=len)
  59. {
  60. dm=(struct dmi_header *)data;
  61. /*
  62.  *  We want to know the total length (formated area and strings)
  63.  *  before decoding to make sure we won't run off the table in
  64.  *  dmi_decode or dmi_string
  65.  */
  66. data+=dm->length;
  67. while(data-buf<len-1 && (data[0] || data[1]))
  68. data++;
  69. if(data-buf<len-1)
  70. decode(dm);
  71. data+=2;
  72. i++;
  73. }
  74. bt_iounmap(buf, len);
  75. return 0;
  76. }
  77. inline static int __init dmi_checksum(u8 *buf)
  78. {
  79. u8 sum=0;
  80. int a;
  81. for(a=0; a<15; a++)
  82. sum+=buf[a];
  83. return (sum==0);
  84. }
  85. static int __init dmi_iterate(void (*decode)(struct dmi_header *))
  86. {
  87. u8 buf[15];
  88. u32 fp=0xF0000;
  89. #ifdef CONFIG_SIMNOW
  90. /*
  91.    * Skip on x86/64 with simnow. Will eventually go away
  92.    * If you see this ifdef in 2.6pre mail me !
  93.    */
  94. return -1;
  95. #endif
  96.  
  97. while( fp < 0xFFFFF)
  98. {
  99. isa_memcpy_fromio(buf, fp, 15);
  100. if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
  101. {
  102. u16 num=buf[13]<<8|buf[12];
  103. u16 len=buf[7]<<8|buf[6];
  104. u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
  105. /*
  106.  * DMI version 0.0 means that the real version is taken from
  107.  * the SMBIOS version, which we don't know at this point.
  108.  */
  109. if(buf[14]!=0)
  110. dmi_printk((KERN_INFO "DMI %d.%d present.n",
  111. buf[14]>>4, buf[14]&0x0F));
  112. else
  113. dmi_printk((KERN_INFO "DMI present.n"));
  114. dmi_printk((KERN_INFO "%d structures occupying %d bytes.n",
  115. num, len));
  116. dmi_printk((KERN_INFO "DMI table at 0x%08X.n",
  117. base));
  118. if(dmi_table(base,len, num, decode)==0)
  119. return 0;
  120. }
  121. fp+=16;
  122. }
  123. return -1;
  124. }
  125. enum
  126. {
  127. DMI_BIOS_VENDOR,
  128. DMI_BIOS_VERSION,
  129. DMI_BIOS_DATE,
  130. DMI_SYS_VENDOR,
  131. DMI_PRODUCT_NAME,
  132. DMI_PRODUCT_VERSION,
  133. DMI_BOARD_VENDOR,
  134. DMI_BOARD_NAME,
  135. DMI_BOARD_VERSION,
  136. DMI_STRING_MAX
  137. };
  138. static char *dmi_ident[DMI_STRING_MAX];
  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.  * DMI callbacks for problem boards
  159.  */
  160. struct dmi_strmatch
  161. {
  162. u8 slot;
  163. char *substr;
  164. };
  165. #define NONE 255
  166. struct dmi_blacklist
  167. {
  168. int (*callback)(struct dmi_blacklist *);
  169. char *ident;
  170. struct dmi_strmatch matches[4];
  171. };
  172. #define NO_MATCH { NONE, NULL}
  173. #define MATCH(a,b) { a, b }
  174. /*
  175.  * We have problems with IDE DMA on some platforms. In paticular the
  176.  * KT7 series. On these it seems the newer BIOS has fixed them. The
  177.  * rule needs to be improved to match specific BIOS revisions with
  178.  * corruption problems
  179.  
  180. static __init int disable_ide_dma(struct dmi_blacklist *d)
  181. {
  182. #ifdef CONFIG_BLK_DEV_IDE
  183. extern int noautodma;
  184. if(noautodma == 0)
  185. {
  186. noautodma = 1;
  187. printk(KERN_INFO "%s series board detected. Disabling IDE DMA.n", d->ident);
  188. }
  189. #endif
  190. return 0;
  191. }
  192.  */ 
  193. /* 
  194.  * Reboot options and system auto-detection code provided by
  195.  * Dell Computer Corporation so their systems "just work". :-)
  196.  */
  197. /* 
  198.  * Some machines require the "reboot=b"  commandline option, this quirk makes that automatic.
  199.  */
  200. static __init int set_bios_reboot(struct dmi_blacklist *d)
  201. {
  202. extern int reboot_thru_bios;
  203. if (reboot_thru_bios == 0)
  204. {
  205. reboot_thru_bios = 1;
  206. printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.n", d->ident);
  207. }
  208. return 0;
  209. }
  210. /*
  211.  * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
  212.  */
  213. static __init int set_smp_reboot(struct dmi_blacklist *d)
  214. {
  215. #ifdef CONFIG_SMP
  216. extern int reboot_smp;
  217. if (reboot_smp == 0)
  218. {
  219. reboot_smp = 1;
  220. printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.n", d->ident);
  221. }
  222. #endif
  223. return 0;
  224. }
  225. /*
  226.  * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
  227.  */
  228. static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
  229. {
  230. set_smp_reboot(d);
  231. set_bios_reboot(d);
  232. return 0;
  233. }
  234. /*
  235.  * Some bioses have a broken protected mode poweroff and need to use realmode
  236.  */
  237. static __init int set_realmode_power_off(struct dmi_blacklist *d)
  238. {
  239.        if (apm_info.realmode_power_off == 0)
  240.        {
  241.                apm_info.realmode_power_off = 1;
  242.                printk(KERN_INFO "%s bios detected. Using realmode poweroff only.n", d->ident);
  243.        }
  244.        return 0;
  245. }
  246. /* 
  247.  * Some laptops require interrupts to be enabled during APM calls 
  248.  */
  249. static __init int set_apm_ints(struct dmi_blacklist *d)
  250. {
  251. if (apm_info.allow_ints == 0)
  252. {
  253. apm_info.allow_ints = 1;
  254. printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.n", d->ident);
  255. }
  256. return 0;
  257. }
  258. /* 
  259.  * Some APM bioses corrupt memory or just plain do not work
  260.  */
  261. static __init int apm_is_horked(struct dmi_blacklist *d)
  262. {
  263. if (apm_info.disabled == 0)
  264. {
  265. apm_info.disabled = 1;
  266. printk(KERN_INFO "%s machine detected. Disabling APM.n", d->ident);
  267. }
  268. return 0;
  269. }
  270. /*
  271.  * Some machines, usually laptops, can't handle an enabled local APIC.
  272.  * The symptoms include hangs or reboots when suspending or resuming,
  273.  * attaching or detaching the power cord, or entering BIOS setup screens
  274.  * through magic key sequences.
  275.  */
  276. static int __init local_apic_kills_bios(struct dmi_blacklist *d)
  277. {
  278. #ifdef CONFIG_X86_LOCAL_APIC
  279. extern int dont_enable_local_apic;
  280. if (!dont_enable_local_apic) {
  281. dont_enable_local_apic = 1;
  282. printk(KERN_WARNING "%s with broken BIOS detected. "
  283.        "Refusing to enable the local APIC.n",
  284.        d->ident);
  285. }
  286. #endif
  287. return 0;
  288. }
  289. /*
  290.  * The Microstar 6163-2 (a.k.a Pro) mainboard will hang shortly after
  291.  * resumes, and also at what appears to be asynchronous APM events,
  292.  * if the local APIC is enabled.
  293.  */
  294. static int __init apm_kills_local_apic(struct dmi_blacklist *d)
  295. {
  296. #ifdef CONFIG_X86_LOCAL_APIC
  297. extern int dont_enable_local_apic;
  298. if (apm_info.bios.version && !dont_enable_local_apic) {
  299. dont_enable_local_apic = 1;
  300. printk(KERN_WARNING "%s with broken BIOS detected. "
  301.        "Refusing to enable the local APIC.n",
  302.        d->ident);
  303. }
  304. #endif
  305. return 0;
  306. }
  307. /*
  308.  * The Intel AL440LX mainboard will hang randomly if the local APIC
  309.  * timer is running and the APM BIOS hasn't been disabled.
  310.  */
  311. static int __init apm_kills_local_apic_timer(struct dmi_blacklist *d)
  312. {
  313. #ifdef CONFIG_X86_LOCAL_APIC
  314. extern int dont_use_local_apic_timer;
  315. if (apm_info.bios.version && !dont_use_local_apic_timer) {
  316. dont_use_local_apic_timer = 1;
  317. printk(KERN_WARNING "%s with broken BIOS detected. "
  318.        "The local APIC timer will not be used.n",
  319.        d->ident);
  320. }
  321. #endif
  322. return 0;
  323. }
  324. /*
  325.  *  Check for clue free BIOS implementations who use
  326.  *  the following QA technique
  327.  *
  328.  *      [ Write BIOS Code ]<------
  329.  *               |                ^
  330.  *      < Does it Compile >----N--
  331.  *               |Y               ^
  332.  * < Does it Boot Win98 >-N--
  333.  *               |Y
  334.  *           [Ship It]
  335.  *
  336.  * Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
  337.  * Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
  338.  */
  339. static __init int broken_apm_power(struct dmi_blacklist *d)
  340. {
  341. apm_info.get_power_status_broken = 1;
  342. printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.n");
  343. return 0;
  344. }
  345. /*
  346.  * Check for a Sony Vaio system
  347.  *
  348.  * On a Sony system we want to enable the use of the sonypi
  349.  * driver for Sony-specific goodies like the camera and jogdial.
  350.  * We also want to avoid using certain functions of the PnP BIOS.
  351.  */
  352. static __init int sony_vaio_laptop(struct dmi_blacklist *d)
  353. {
  354. if (is_sony_vaio_laptop == 0)
  355. {
  356. is_sony_vaio_laptop = 1;
  357. printk(KERN_INFO "%s laptop detected.n", d->ident);
  358. }
  359. return 0;
  360. }
  361. /*
  362.  * This bios swaps the APM minute reporting bytes over (Many sony laptops
  363.  * have this problem).
  364.  */
  365.  
  366. static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
  367. {
  368. apm_info.get_power_status_swabinminutes = 1;
  369. printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.n");
  370. return 0;
  371. }
  372. /*
  373.  * The Intel 440GX hall of shame. 
  374.  *
  375.  * On many (all we have checked) of these boxes the $PIRQ table is wrong.
  376.  * The MP1.4 table is right however and so SMP kernels tend to work. 
  377.  */
  378.  
  379. extern int skip_ioapic_setup;
  380. static __init int broken_pirq(struct dmi_blacklist *d)
  381. {
  382. printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)n");
  383. printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.n");
  384. printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at bootn");
  385. printk(KERN_INFO " *** contact your hardware vendor and ask about updates.n");
  386. printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.n");
  387. #ifdef CONFIG_X86_IO_APIC
  388. skip_ioapic_setup = 0;
  389. #endif
  390. return 0;
  391. }
  392. /*
  393.  * ASUS K7V-RM has broken ACPI table defining sleep modes
  394.  */
  395. static __init int broken_acpi_Sx(struct dmi_blacklist *d)
  396. {
  397. printk(KERN_WARNING "Detected ASUS mainboard with broken ACPI sleep tablen");
  398. dmi_broken |= BROKEN_ACPI_Sx;
  399. return 0;
  400. }
  401. /*
  402.  * Toshiba keyboard likes to repeat keys when they are not repeated.
  403.  */
  404. static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
  405. {
  406. printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, contact pavel@ucw.czn");
  407. return 0;
  408. }
  409. /*
  410.  * Toshiba fails to preserve interrupts over S1
  411.  */
  412. static __init int init_ints_after_s1(struct dmi_blacklist *d)
  413. {
  414. printk(KERN_WARNING "Toshiba with broken S1 detected.n");
  415. dmi_broken |= BROKEN_INIT_AFTER_S1;
  416. return 0;
  417. }
  418. /*
  419.  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it
  420.  * was disabled before the suspend. Linux gets terribly confused by that.
  421.  */
  422. typedef void (pm_kbd_func) (void);
  423. static __init int broken_ps2_resume(struct dmi_blacklist *d)
  424. {
  425. #ifdef CONFIG_VT
  426. if (pm_kbd_request_override == NULL)
  427. {
  428. pm_kbd_request_override = pckbd_pm_resume;
  429. printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.n", d->ident);
  430. }
  431. #endif
  432. return 0;
  433. }
  434. /*
  435.  * Work around broken HP Pavilion Notebooks which assign USB to
  436.  * IRQ 9 even though it is actually wired to IRQ 11
  437.  */
  438. static __init int fix_broken_hp_bios_irq9(struct dmi_blacklist *d)
  439. {
  440. #ifdef CONFIG_PCI
  441. extern int broken_hp_bios_irq9;
  442. if (broken_hp_bios_irq9 == 0)
  443. {
  444. broken_hp_bios_irq9 = 1;
  445. printk(KERN_INFO "%s detected - fixing broken IRQ routingn", d->ident);
  446. }
  447. #endif
  448. return 0;
  449. }
  450. /*
  451.  * Simple "print if true" callback
  452.  */
  453.  
  454. static __init int print_if_true(struct dmi_blacklist *d)
  455. {
  456. printk("%sn", d->ident);
  457. return 0;
  458. }
  459. /*
  460.  * Process the DMI blacklists
  461.  */
  462.  
  463. /*
  464.  * This will be expanded over time to force things like the APM 
  465.  * interrupt mask settings according to the laptop
  466.  */
  467.  
  468. static __initdata struct dmi_blacklist dmi_blacklist[]={
  469. #if 0
  470. { disable_ide_dma, "KT7", { /* Overbroad right now - kill DMA on problem KT7 boards */
  471. MATCH(DMI_PRODUCT_NAME, "KT7-RAID"),
  472. NO_MATCH, NO_MATCH, NO_MATCH
  473. } },
  474. #endif
  475. { broken_ps2_resume, "Dell Latitude C600", { /* Handle problems with APM on the C600 */
  476.         MATCH(DMI_SYS_VENDOR, "Dell"),
  477. MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
  478. NO_MATCH, NO_MATCH
  479.                 } },
  480. { broken_apm_power, "Dell Inspiron 5000e", { /* Handle problems with APM on Inspiron 5000e */
  481. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  482. MATCH(DMI_BIOS_VERSION, "A04"),
  483. MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
  484. } },
  485. { broken_apm_power, "Dell Inspiron 2500", { /* Handle problems with APM on Inspiron 2500 */
  486. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  487. MATCH(DMI_BIOS_VERSION, "A12"),
  488. MATCH(DMI_BIOS_DATE, "02/04/2002"), NO_MATCH
  489. } },
  490. { set_realmode_power_off, "Award Software v4.60 PGMA", { /* broken PM poweroff bios */
  491. MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
  492. MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
  493. MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
  494. } },
  495. { set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */
  496. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  497. MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
  498. NO_MATCH, NO_MATCH
  499. } },
  500. { set_bios_reboot, "Dell PowerEdge 300", { /* Handle problems with rebooting on Dell 1300's */
  501. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  502. MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
  503. NO_MATCH, NO_MATCH
  504. } },
  505. { set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 300/800's */
  506. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  507. MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
  508. NO_MATCH, NO_MATCH
  509. } },
  510. { set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/
  511. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  512. MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
  513. NO_MATCH, NO_MATCH
  514. } },
  515. { set_apm_ints, "Compaq 12XL125", { /* Allow interrupts during suspend on Compaq Laptops*/
  516. MATCH(DMI_SYS_VENDOR, "Compaq"),
  517. MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
  518. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  519. MATCH(DMI_BIOS_VERSION,"4.06")
  520. } },
  521. { set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
  522. MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  523. MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
  524. NO_MATCH, NO_MATCH
  525. } },
  526. { apm_is_horked, "Trigem Delhi3", { /* APM crashes */
  527. MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
  528. MATCH(DMI_PRODUCT_NAME, "Delhi3"),
  529. NO_MATCH, NO_MATCH,
  530. } },
  531. { apm_is_horked, "Fujitsu-Siemens", { /* APM crashes */
  532. MATCH(DMI_BIOS_VENDOR, "hoenix/FUJITSU SIEMENS"),
  533. MATCH(DMI_BIOS_VERSION, "Version1.01"),
  534. NO_MATCH, NO_MATCH,
  535. } },
  536. { apm_is_horked, "Intel D850MD", { /* APM crashes */
  537. MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
  538. MATCH(DMI_BIOS_VERSION, "MV85010A.86A.0016.P07.0201251536"),
  539. NO_MATCH, NO_MATCH,
  540. } },
  541. { apm_is_horked, "Dell XPS-Z", { /* APM crashes */
  542. MATCH(DMI_BIOS_VENDOR, "Intel Corp."),
  543. MATCH(DMI_BIOS_VERSION, "A11"),
  544. MATCH(DMI_PRODUCT_NAME, "XPS-Z"),
  545. NO_MATCH,
  546. } },
  547. { apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
  548. MATCH(DMI_SYS_VENDOR, "SHARP"),
  549. MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
  550. MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
  551. MATCH(DMI_BIOS_VERSION,"Version R2.08")
  552. } },
  553. { apm_is_horked, "Dell Inspiron 2500", { /* APM crashes */
  554. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  555. MATCH(DMI_PRODUCT_NAME, "Inspiron 2500"),
  556. MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"),
  557. MATCH(DMI_BIOS_VERSION,"A11")
  558. } },
  559. { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
  560. MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  561. MATCH(DMI_PRODUCT_NAME, "PCG-"),
  562. NO_MATCH, NO_MATCH,
  563. } },
  564. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
  565. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  566. MATCH(DMI_BIOS_VERSION, "R0206H"),
  567. MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
  568. } },
  569. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
  570. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  571. MATCH(DMI_BIOS_VERSION, "W2K06H0"),
  572. MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
  573. } },
  574. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-XG29 */
  575. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  576. MATCH(DMI_BIOS_VERSION, "R0117A0"),
  577. MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
  578. } },
  579. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */
  580. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  581. MATCH(DMI_BIOS_VERSION, "R0121Z1"),
  582. MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
  583. } },
  584. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */
  585. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  586. MATCH(DMI_BIOS_VERSION, "WME01Z1"),
  587. MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
  588. } },
  589. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600LEK(DE) */
  590. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  591. MATCH(DMI_BIOS_VERSION, "R0206Z3"),
  592. MATCH(DMI_BIOS_DATE, "12/25/00"), NO_MATCH
  593. } },
  594. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
  595. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  596. MATCH(DMI_BIOS_VERSION, "R0203D0"),
  597. MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
  598. } },
  599. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
  600. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  601. MATCH(DMI_BIOS_VERSION, "R0203Z3"),
  602. MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
  603. } },
  604. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
  605. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  606. MATCH(DMI_BIOS_VERSION, "R0209Z3"),
  607. MATCH(DMI_BIOS_DATE, "05/12/01"), NO_MATCH
  608. } },
  609. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS (with updated BIOS) */
  610. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  611. MATCH(DMI_BIOS_VERSION, "WXP01Z3"),
  612. MATCH(DMI_BIOS_DATE, "10/26/01"), NO_MATCH
  613. } },
  614. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-F104K */
  615. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  616. MATCH(DMI_BIOS_VERSION, "R0204K2"),
  617. MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
  618. } },
  619. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
  620. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  621. MATCH(DMI_BIOS_VERSION, "R0208P1"),
  622. MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
  623. } },
  624. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VE */
  625. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  626. MATCH(DMI_BIOS_VERSION, "R0204P1"),
  627. MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
  628. } },
  629. /* Machines which have problems handling enabled local APICs */
  630. { local_apic_kills_bios, "Dell Inspiron", {
  631. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  632. MATCH(DMI_PRODUCT_NAME, "Inspiron"),
  633. NO_MATCH, NO_MATCH
  634. } },
  635. { local_apic_kills_bios, "Dell Latitude", {
  636. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  637. MATCH(DMI_PRODUCT_NAME, "Latitude"),
  638. NO_MATCH, NO_MATCH
  639. } },
  640. { local_apic_kills_bios, "IBM Thinkpad T20", {
  641. MATCH(DMI_BOARD_VENDOR, "IBM"),
  642. MATCH(DMI_BOARD_NAME, "264741U"),
  643. NO_MATCH, NO_MATCH
  644. } },
  645. { apm_kills_local_apic, "Microstar 6163", {
  646. MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
  647. MATCH(DMI_BOARD_NAME, "MS-6163"),
  648. NO_MATCH, NO_MATCH } },
  649. { apm_kills_local_apic_timer, "Intel AL440LX", {
  650. MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
  651. MATCH(DMI_BOARD_NAME, "AL440LX"),
  652. NO_MATCH, NO_MATCH } },
  653. /* Problem Intel 440GX bioses */
  654. { broken_pirq, "SABR1 Bios", { /* Bad $PIR */
  655. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  656. MATCH(DMI_BIOS_VERSION,"SABR1"),
  657. NO_MATCH, NO_MATCH
  658. } },
  659. { broken_pirq, "l44GX Bios", {         /* Bad $PIR */
  660. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  661. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
  662. NO_MATCH, NO_MATCH
  663.                         } },
  664. { broken_pirq, "l44GX Bios", {         /* Bad $PIR */
  665. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  666. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0120.P12"),
  667. NO_MATCH, NO_MATCH
  668.                         } },
  669. { broken_pirq, "l44GX Bios", { /* Bad $PIR */
  670. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  671. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
  672. NO_MATCH, NO_MATCH
  673. } },
  674. { broken_pirq, "l44GX Bios", { /* Bad $PIR */
  675. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  676. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07.9906041405"),
  677. NO_MATCH, NO_MATCH
  678. } },
  679.                         
  680. /* Intel in disgiuse - In this case they can't hide and they don't run
  681.    too well either... */
  682. { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */
  683. MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
  684. NO_MATCH, NO_MATCH, NO_MATCH
  685. } },
  686. { broken_acpi_Sx, "ASUS K7V-RM", { /* Bad ACPI Sx table */
  687. MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
  688. MATCH(DMI_BOARD_NAME, "<K7V-RM>"),
  689. NO_MATCH, NO_MATCH
  690. } },
  691. { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
  692. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  693. NO_MATCH, NO_MATCH, NO_MATCH
  694. } },
  695. { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
  696. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  697. NO_MATCH, NO_MATCH, NO_MATCH
  698. } },
  699. { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
  700. MATCH(DMI_SYS_VENDOR, "IBM"),
  701. MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
  702. NO_MATCH, NO_MATCH
  703. } },
  704.  
  705. { fix_broken_hp_bios_irq9, "HP Pavilion N5400 Series Laptop", {
  706. MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
  707. MATCH(DMI_BIOS_VERSION, "GE.M1.03"),
  708. MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"),
  709. MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736")
  710. } },
  711.  
  712. /*
  713.  * Generic per vendor APM settings
  714.  */
  715.  
  716. { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */
  717. MATCH(DMI_SYS_VENDOR, "IBM"),
  718. NO_MATCH, NO_MATCH, NO_MATCH
  719. } },
  720. { NULL, }
  721. };
  722. /*
  723.  * Walk the blacklist table running matching functions until someone 
  724.  * returns 1 or we hit the end.
  725.  */
  726.  
  727. static __init void dmi_check_blacklist(void)
  728. {
  729. struct dmi_blacklist *d;
  730. int i;
  731. d=&dmi_blacklist[0];
  732. while(d->callback)
  733. {
  734. for(i=0;i<4;i++)
  735. {
  736. int s = d->matches[i].slot;
  737. if(s==NONE)
  738. continue;
  739. if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
  740. continue;
  741. /* No match */
  742. goto fail;
  743. }
  744. if(d->callback(d))
  745. return;
  746. fail:
  747. d++;
  748. }
  749. }
  750. /*
  751.  * Process a DMI table entry. Right now all we care about are the BIOS
  752.  * and machine entries. For 2.5 we should pull the smbus controller info
  753.  * out of here.
  754.  */
  755. static void __init dmi_decode(struct dmi_header *dm)
  756. {
  757. u8 *data = (u8 *)dm;
  758. switch(dm->type)
  759. {
  760. case  0:
  761. dmi_printk(("BIOS Vendor: %sn",
  762. dmi_string(dm, data[4])));
  763. dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
  764. dmi_printk(("BIOS Version: %sn", 
  765. dmi_string(dm, data[5])));
  766. dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
  767. dmi_printk(("BIOS Release: %sn",
  768. dmi_string(dm, data[8])));
  769. dmi_save_ident(dm, DMI_BIOS_DATE, 8);
  770. break;
  771. case 1:
  772. dmi_printk(("System Vendor: %sn",
  773. dmi_string(dm, data[4])));
  774. dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
  775. dmi_printk(("Product Name: %sn",
  776. dmi_string(dm, data[5])));
  777. dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
  778. dmi_printk(("Version: %sn",
  779. dmi_string(dm, data[6])));
  780. dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
  781. dmi_printk(("Serial Number: %sn",
  782. dmi_string(dm, data[7])));
  783. break;
  784. case 2:
  785. dmi_printk(("Board Vendor: %sn",
  786. dmi_string(dm, data[4])));
  787. dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
  788. dmi_printk(("Board Name: %sn",
  789. dmi_string(dm, data[5])));
  790. dmi_save_ident(dm, DMI_BOARD_NAME, 5);
  791. dmi_printk(("Board Version: %sn",
  792. dmi_string(dm, data[6])));
  793. dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
  794. break;
  795. }
  796. }
  797. void __init dmi_scan_machine(void)
  798. {
  799. int err = dmi_iterate(dmi_decode);
  800. if(err == 0)
  801. dmi_check_blacklist();
  802. }