dmi_scan.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:19k
源码类别:

嵌入式Linux

开发平台:

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. unsigned long dmi_broken;
  13. int is_sony_vaio_laptop;
  14. struct dmi_header
  15. {
  16. u8 type;
  17. u8 length;
  18. u16 handle;
  19. };
  20. #define dmi_printk(x)
  21. //#define dmi_printk(x) printk x
  22. static char * __init dmi_string(struct dmi_header *dm, u8 s)
  23. {
  24. u8 *bp=(u8 *)dm;
  25. bp+=dm->length;
  26. if(!s)
  27. return "";
  28. s--;
  29. while(s>0)
  30. {
  31. bp+=strlen(bp);
  32. bp++;
  33. s--;
  34. }
  35. return bp;
  36. }
  37. /*
  38.  * We have to be cautious here. We have seen BIOSes with DMI pointers
  39.  * pointing to completely the wrong place for example
  40.  */
  41.  
  42. static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
  43. {
  44. u8 *buf;
  45. struct dmi_header *dm;
  46. u8 *data;
  47. int i=1;
  48. buf = ioremap(base, len);
  49. if(buf==NULL)
  50. return -1;
  51. data = buf;
  52. /*
  53.    * Stop when we see al the items the table claimed to have
  54.    * OR we run off the end of the table (also happens)
  55.    */
  56.  
  57. while(i<num && (data - buf) < len)
  58. {
  59. dm=(struct dmi_header *)data;
  60. /*
  61.  * Avoid misparsing crud if the length of the last
  62.    * record is crap 
  63.  */
  64. if((data-buf+dm->length) >= len)
  65. break;
  66. decode(dm);
  67. data+=dm->length;
  68. /*
  69.  * Don't go off the end of the data if there is
  70.    * stuff looking like string fill past the end
  71.    */
  72. while((data-buf) < len && (*data || data[1]))
  73. data++;
  74. data+=2;
  75. i++;
  76. }
  77. iounmap(buf);
  78. return 0;
  79. }
  80. static int __init dmi_iterate(void (*decode)(struct dmi_header *))
  81. {
  82. unsigned char buf[20];
  83. long fp=0xE0000L;
  84. fp -= 16;
  85. #ifdef CONFIG_SIMNOW
  86. /*
  87.    * Skip on x86/64 with simnow. Will eventually go away
  88.    * If you see this ifdef in 2.6pre mail me !
  89.    */
  90. return -1;
  91. #endif
  92.  
  93. while( fp < 0xFFFFF)
  94. {
  95. fp+=16;
  96. isa_memcpy_fromio(buf, fp, 20);
  97. if(memcmp(buf, "_DMI_", 5)==0)
  98. {
  99. u16 num=buf[13]<<8|buf[12];
  100. u16 len=buf[7]<<8|buf[6];
  101. u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
  102. dmi_printk((KERN_INFO "DMI %d.%d present.n",
  103. buf[14]>>4, buf[14]&0x0F));
  104. dmi_printk((KERN_INFO "%d structures occupying %d bytes.n",
  105. buf[13]<<8|buf[12],
  106. buf[7]<<8|buf[6]));
  107. dmi_printk((KERN_INFO "DMI table at 0x%08X.n",
  108. buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]));
  109. if(dmi_table(base,len, num, decode)==0)
  110. return 0;
  111. }
  112. }
  113. return -1;
  114. }
  115. enum
  116. {
  117. DMI_BIOS_VENDOR,
  118. DMI_BIOS_VERSION,
  119. DMI_BIOS_DATE,
  120. DMI_SYS_VENDOR,
  121. DMI_PRODUCT_NAME,
  122. DMI_PRODUCT_VERSION,
  123. DMI_BOARD_VENDOR,
  124. DMI_BOARD_NAME,
  125. DMI_BOARD_VERSION,
  126. DMI_STRING_MAX
  127. };
  128. static char *dmi_ident[DMI_STRING_MAX];
  129. /*
  130.  * Save a DMI string
  131.  */
  132.  
  133. static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
  134. {
  135. char *d = (char*)dm;
  136. char *p = dmi_string(dm, d[string]);
  137. if(p==NULL || *p == 0)
  138. return;
  139. if (dmi_ident[slot])
  140. return;
  141. dmi_ident[slot] = kmalloc(strlen(p)+1, GFP_KERNEL);
  142. if(dmi_ident[slot])
  143. strcpy(dmi_ident[slot], p);
  144. else
  145. printk(KERN_ERR "dmi_save_ident: out of memory.n");
  146. }
  147. /*
  148.  * DMI callbacks for problem boards
  149.  */
  150. struct dmi_strmatch
  151. {
  152. u8 slot;
  153. char *substr;
  154. };
  155. #define NONE 255
  156. struct dmi_blacklist
  157. {
  158. int (*callback)(struct dmi_blacklist *);
  159. char *ident;
  160. struct dmi_strmatch matches[4];
  161. };
  162. #define NO_MATCH { NONE, NULL}
  163. #define MATCH(a,b) { a, b }
  164. /*
  165.  * We have problems with IDE DMA on some platforms. In paticular the
  166.  * KT7 series. On these it seems the newer BIOS has fixed them. The
  167.  * rule needs to be improved to match specific BIOS revisions with
  168.  * corruption problems
  169.  */ 
  170.  
  171. static __init int disable_ide_dma(struct dmi_blacklist *d)
  172. {
  173. #ifdef CONFIG_BLK_DEV_IDE
  174. extern int noautodma;
  175. if(noautodma == 0)
  176. {
  177. noautodma = 1;
  178. printk(KERN_INFO "%s series board detected. Disabling IDE DMA.n", d->ident);
  179. }
  180. #endif
  181. return 0;
  182. }
  183. /* 
  184.  * Reboot options and system auto-detection code provided by
  185.  * Dell Computer Corporation so their systems "just work". :-)
  186.  */
  187. /* 
  188.  * Some machines require the "reboot=b"  commandline option, this quirk makes that automatic.
  189.  */
  190. static __init int set_bios_reboot(struct dmi_blacklist *d)
  191. {
  192. extern int reboot_thru_bios;
  193. if (reboot_thru_bios == 0)
  194. {
  195. reboot_thru_bios = 1;
  196. printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.n", d->ident);
  197. }
  198. return 0;
  199. }
  200. /*
  201.  * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
  202.  */
  203. static __init int set_smp_reboot(struct dmi_blacklist *d)
  204. {
  205. #ifdef CONFIG_SMP
  206. extern int reboot_smp;
  207. if (reboot_smp == 0)
  208. {
  209. reboot_smp = 1;
  210. printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.n", d->ident);
  211. }
  212. #endif
  213. return 0;
  214. }
  215. /*
  216.  * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
  217.  */
  218. static __init int set_smp_bios_reboot(struct dmi_blacklist *d)
  219. {
  220. set_smp_reboot(d);
  221. set_bios_reboot(d);
  222. return 0;
  223. }
  224. /*
  225.  * Some bioses have a broken protected mode poweroff and need to use realmode
  226.  */
  227. static __init int set_realmode_power_off(struct dmi_blacklist *d)
  228. {
  229.        if (apm_info.realmode_power_off == 0)
  230.        {
  231.                apm_info.realmode_power_off = 1;
  232.                printk(KERN_INFO "%s bios detected. Using realmode poweroff only.n", d->ident);
  233.        }
  234.        return 0;
  235. }
  236. /* 
  237.  * Some laptops require interrupts to be enabled during APM calls 
  238.  */
  239. static __init int set_apm_ints(struct dmi_blacklist *d)
  240. {
  241. if (apm_info.allow_ints == 0)
  242. {
  243. apm_info.allow_ints = 1;
  244. printk(KERN_INFO "%s machine detected. Enabling interrupts during APM calls.n", d->ident);
  245. }
  246. return 0;
  247. }
  248. /* 
  249.  * Some APM bioses corrupt memory or just plain do not work
  250.  */
  251. static __init int apm_is_horked(struct dmi_blacklist *d)
  252. {
  253. if (apm_info.disabled == 0)
  254. {
  255. apm_info.disabled = 1;
  256. printk(KERN_INFO "%s machine detected. Disabling APM.n", d->ident);
  257. }
  258. return 0;
  259. }
  260. /*
  261.  *  Check for clue free BIOS implementations who use
  262.  *  the following QA technique
  263.  *
  264.  *      [ Write BIOS Code ]<------
  265.  *               |                ^
  266.  *      < Does it Compile >----N--
  267.  *               |Y               ^
  268.  * < Does it Boot Win98 >-N--
  269.  *               |Y
  270.  *           [Ship It]
  271.  *
  272.  * Phoenix A04  08/24/2000 is known bad (Dell Inspiron 5000e)
  273.  * Phoenix A07  09/29/2000 is known good (Dell Inspiron 5000)
  274.  */
  275. static __init int broken_apm_power(struct dmi_blacklist *d)
  276. {
  277. apm_info.get_power_status_broken = 1;
  278. printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.n");
  279. return 0;
  280. }
  281. /*
  282.  * Check for a Sony Vaio system
  283.  *
  284.  * On a Sony system we want to enable the use of the sonypi
  285.  * driver for Sony-specific goodies like the camera and jogdial.
  286.  * We also want to avoid using certain functions of the PnP BIOS.
  287.  */
  288. static __init int sony_vaio_laptop(struct dmi_blacklist *d)
  289. {
  290. if (is_sony_vaio_laptop == 0)
  291. {
  292. is_sony_vaio_laptop = 1;
  293. printk(KERN_INFO "%s laptop detected.n", d->ident);
  294. }
  295. return 0;
  296. }
  297. /*
  298.  * This bios swaps the APM minute reporting bytes over (Many sony laptops
  299.  * have this problem).
  300.  */
  301.  
  302. static __init int swab_apm_power_in_minutes(struct dmi_blacklist *d)
  303. {
  304. apm_info.get_power_status_swabinminutes = 1;
  305. printk(KERN_WARNING "BIOS strings suggest APM reports battery life in minutes and wrong byte order.n");
  306. return 0;
  307. }
  308. /*
  309.  * The Intel 440GX hall of shame. 
  310.  *
  311.  * On many (all we have checked) of these boxes the $PIRQ table is wrong.
  312.  * The MP1.4 table is right however and so SMP kernels tend to work. 
  313.  */
  314.  
  315. static __init int broken_pirq(struct dmi_blacklist *d)
  316. {
  317. printk(KERN_INFO " *** Possibly defective BIOS detected (irqtable)n");
  318. printk(KERN_INFO " *** Many BIOSes matching this signature have incorrect IRQ routing tables.n");
  319. printk(KERN_INFO " *** If you see IRQ problems, in paticular SCSI resets and hangs at bootn");
  320. printk(KERN_INFO " *** contact your hardware vendor and ask about updates.n");
  321. printk(KERN_INFO " *** Building an SMP kernel may evade the bug some of the time.n");
  322. return 0;
  323. }
  324. /*
  325.  * ASUS K7V-RM has broken ACPI table defining sleep modes
  326.  */
  327. static __init int broken_acpi_Sx(struct dmi_blacklist *d)
  328. {
  329. printk(KERN_WARNING "Detected ASUS mainboard with broken ACPI sleep tablen");
  330. dmi_broken |= BROKEN_ACPI_Sx;
  331. return 0;
  332. }
  333. /*
  334.  * Toshiba keyboard likes to repeat keys when they are not repeated.
  335.  */
  336. static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
  337. {
  338. printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, contact pavel@ucw.czn");
  339. return 0;
  340. }
  341. /*
  342.  * Toshiba fails to preserve interrupts over S1
  343.  */
  344. static __init int init_ints_after_s1(struct dmi_blacklist *d)
  345. {
  346. printk(KERN_WARNING "Toshiba with broken S1 detected.n");
  347. dmi_broken |= BROKEN_INIT_AFTER_S1;
  348. return 0;
  349. }
  350. /*
  351.  * Some Bioses enable the PS/2 mouse (touchpad) at resume, even if it
  352.  * was disabled before the suspend. Linux gets terribly confused by that.
  353.  */
  354. typedef void (pm_kbd_func) (void);
  355. static __init int broken_ps2_resume(struct dmi_blacklist *d)
  356. {
  357. #ifdef CONFIG_VT
  358. if (pm_kbd_request_override == NULL)
  359. {
  360. pm_kbd_request_override = pckbd_pm_resume;
  361. printk(KERN_INFO "%s machine detected. Mousepad Resume Bug workaround enabled.n", d->ident);
  362. }
  363. #endif
  364. return 0;
  365. }
  366. /*
  367.  * Simple "print if true" callback
  368.  */
  369.  
  370. static __init int print_if_true(struct dmi_blacklist *d)
  371. {
  372. printk("%sn", d->ident);
  373. return 0;
  374. }
  375. /*
  376.  * Process the DMI blacklists
  377.  */
  378.  
  379. /*
  380.  * This will be expanded over time to force things like the APM 
  381.  * interrupt mask settings according to the laptop
  382.  */
  383.  
  384. static __initdata struct dmi_blacklist dmi_blacklist[]={
  385. #if 0
  386. { disable_ide_dma, "KT7", { /* Overbroad right now - kill DMA on problem KT7 boards */
  387. MATCH(DMI_PRODUCT_NAME, "KT7-RAID"),
  388. NO_MATCH, NO_MATCH, NO_MATCH
  389. } },
  390. #endif
  391. { broken_ps2_resume, "Dell Latitude C600", { /* Handle problems with APM on the C600 */
  392.         MATCH(DMI_SYS_VENDOR, "Dell"),
  393. MATCH(DMI_PRODUCT_NAME, "Latitude C600"),
  394. NO_MATCH, NO_MATCH
  395.                 } },
  396. { broken_apm_power, "Dell Inspiron 5000e", { /* Handle problems with APM on Inspiron 5000e */
  397. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  398. MATCH(DMI_BIOS_VERSION, "A04"),
  399. MATCH(DMI_BIOS_DATE, "08/24/2000"), NO_MATCH
  400. } },
  401. { set_realmode_power_off, "Award Software v4.60 PGMA", { /* broken PM poweroff bios */
  402. MATCH(DMI_BIOS_VENDOR, "Award Software International, Inc."),
  403. MATCH(DMI_BIOS_VERSION, "4.60 PGMA"),
  404. MATCH(DMI_BIOS_DATE, "134526184"), NO_MATCH
  405. } },
  406. { set_smp_bios_reboot, "Dell PowerEdge 1300", { /* Handle problems with rebooting on Dell 1300's */
  407. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  408. MATCH(DMI_PRODUCT_NAME, "PowerEdge 1300/"),
  409. NO_MATCH, NO_MATCH
  410. } },
  411. { set_bios_reboot, "Dell PowerEdge 300", { /* Handle problems with rebooting on Dell 1300's */
  412. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  413. MATCH(DMI_PRODUCT_NAME, "PowerEdge 300/"),
  414. NO_MATCH, NO_MATCH
  415. } },
  416. { set_bios_reboot, "Dell PowerEdge 2400", {  /* Handle problems with rebooting on Dell 300/800's */
  417. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  418. MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"),
  419. NO_MATCH, NO_MATCH
  420. } },
  421. { set_apm_ints, "Dell Inspiron", { /* Allow interrupts during suspend on Dell Inspiron laptops*/
  422. MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
  423. MATCH(DMI_PRODUCT_NAME, "Inspiron 4000"),
  424. NO_MATCH, NO_MATCH
  425. } },
  426. { set_apm_ints, "Compaq 12XL125", { /* Allow interrupts during suspend on Compaq Laptops*/
  427. MATCH(DMI_SYS_VENDOR, "Compaq"),
  428. MATCH(DMI_PRODUCT_NAME, "Compaq PC"),
  429. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  430. MATCH(DMI_BIOS_VERSION,"4.06")
  431. } },
  432. { set_apm_ints, "ASUSTeK", {   /* Allow interrupts during APM or the clock goes slow */
  433. MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
  434. MATCH(DMI_PRODUCT_NAME, "L8400K series Notebook PC"),
  435. NO_MATCH, NO_MATCH
  436. } },
  437. { apm_is_horked, "Trigem Delhi3", { /* APM crashes */
  438. MATCH(DMI_SYS_VENDOR, "TriGem Computer, Inc"),
  439. MATCH(DMI_PRODUCT_NAME, "Delhi3"),
  440. NO_MATCH, NO_MATCH,
  441. } },
  442. { apm_is_horked, "Sharp PC-PJ/AX", { /* APM crashes */
  443. MATCH(DMI_SYS_VENDOR, "SHARP"),
  444. MATCH(DMI_PRODUCT_NAME, "PC-PJ/AX"),
  445. MATCH(DMI_BIOS_VENDOR,"SystemSoft"),
  446. MATCH(DMI_BIOS_VERSION,"Version R2.08")
  447. } },
  448. { sony_vaio_laptop, "Sony Vaio", { /* This is a Sony Vaio laptop */
  449. MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
  450. MATCH(DMI_PRODUCT_NAME, "PCG-"),
  451. NO_MATCH, NO_MATCH,
  452. } },
  453. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505X(DE) */
  454. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  455. MATCH(DMI_BIOS_VERSION, "R0206H"),
  456. MATCH(DMI_BIOS_DATE, "08/23/99"), NO_MATCH
  457. } },
  458. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-N505VX */
  459. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  460. MATCH(DMI_BIOS_VERSION, "W2K06H0"),
  461. MATCH(DMI_BIOS_DATE, "02/03/00"), NO_MATCH
  462. } },
  463. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-XG29 */
  464. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  465. MATCH(DMI_BIOS_VERSION, "R0117A0"),
  466. MATCH(DMI_BIOS_DATE, "04/25/00"), NO_MATCH
  467. } },
  468. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */
  469. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  470. MATCH(DMI_BIOS_VERSION, "R0121Z1"),
  471. MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
  472. } },
  473. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z600NE */
  474. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  475. MATCH(DMI_BIOS_VERSION, "WME01Z1"),
  476. MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
  477. } },
  478. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
  479. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  480. MATCH(DMI_BIOS_VERSION, "R0203D0"),
  481. MATCH(DMI_BIOS_DATE, "05/12/00"), NO_MATCH
  482. } },
  483. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-Z505LS */
  484. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  485. MATCH(DMI_BIOS_VERSION, "R0203Z3"),
  486. MATCH(DMI_BIOS_DATE, "08/25/00"), NO_MATCH
  487. } },
  488. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-F104K */
  489. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  490. MATCH(DMI_BIOS_VERSION, "R0204K2"),
  491. MATCH(DMI_BIOS_DATE, "08/28/00"), NO_MATCH
  492. } },
  493. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VN/C1VE */
  494. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  495. MATCH(DMI_BIOS_VERSION, "R0208P1"),
  496. MATCH(DMI_BIOS_DATE, "11/09/00"), NO_MATCH
  497. } },
  498. { swab_apm_power_in_minutes, "Sony VAIO", { /* Handle problems with APM on Sony Vaio PCG-C1VE */
  499. MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
  500. MATCH(DMI_BIOS_VERSION, "R0204P1"),
  501. MATCH(DMI_BIOS_DATE, "09/12/00"), NO_MATCH
  502. } },
  503. /* Problem Intel 440GX bioses */
  504. { broken_pirq, "SABR1 Bios", { /* Bad $PIR */
  505. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  506. MATCH(DMI_BIOS_VERSION,"SABR1"),
  507. NO_MATCH, NO_MATCH
  508. } },
  509. { broken_pirq, "l44GX Bios", {         /* Bad $PIR */
  510. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  511. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0094.P10"),
  512. NO_MATCH, NO_MATCH
  513.                         } },
  514. { broken_pirq, "l44GX Bios", {         /* Bad $PIR */
  515. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  516. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0120.P12"),
  517. NO_MATCH, NO_MATCH
  518.                         } },
  519. { broken_pirq, "l44GX Bios", { /* Bad $PIR */
  520. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  521. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0125.P13"),
  522. NO_MATCH, NO_MATCH
  523. } },
  524. { broken_pirq, "l44GX Bios", { /* Bad $PIR */
  525. MATCH(DMI_BIOS_VENDOR, "Intel Corporation"),
  526. MATCH(DMI_BIOS_VERSION,"L440GX0.86B.0066.P07.9906041405"),
  527. NO_MATCH, NO_MATCH
  528. } },
  529.                         
  530. /* Intel in disgiuse - In this case they can't hide and they don't run
  531.    too well either... */
  532. { broken_pirq, "Dell PowerEdge 8450", { /* Bad $PIR */
  533. MATCH(DMI_PRODUCT_NAME, "Dell PowerEdge 8450"),
  534. NO_MATCH, NO_MATCH, NO_MATCH
  535. } },
  536. { broken_acpi_Sx, "ASUS K7V-RM", { /* Bad ACPI Sx table */
  537. MATCH(DMI_BIOS_VERSION,"ASUS K7V-RM ACPI BIOS Revision 1003A"),
  538. MATCH(DMI_BOARD_NAME, "<K7V-RM>"),
  539. NO_MATCH, NO_MATCH
  540. } },
  541. { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
  542. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  543. NO_MATCH, NO_MATCH, NO_MATCH
  544. } },
  545. { init_ints_after_s1, "Toshiba Satellite 4030cdt", { /* Reinitialization of 8259 is needed after S1 resume */
  546. MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
  547. NO_MATCH, NO_MATCH, NO_MATCH
  548. } },
  549. { print_if_true, KERN_WARNING "IBM T23 - BIOS 1.03b+ and controller firmware 1.02+ may be needed for Linux APM.", {
  550. MATCH(DMI_SYS_VENDOR, "IBM"),
  551. MATCH(DMI_BIOS_VERSION, "1AET38WW (1.01b)"),
  552. NO_MATCH, NO_MATCH
  553. } },
  554.  
  555. /*
  556.  * Generic per vendor APM settings
  557.  */
  558.  
  559. { set_apm_ints, "IBM", { /* Allow interrupts during suspend on IBM laptops */
  560. MATCH(DMI_SYS_VENDOR, "IBM"),
  561. NO_MATCH, NO_MATCH, NO_MATCH
  562. } },
  563. { NULL, }
  564. };
  565. /*
  566.  * Walk the blacklist table running matching functions until someone 
  567.  * returns 1 or we hit the end.
  568.  */
  569.  
  570. static __init void dmi_check_blacklist(void)
  571. {
  572. struct dmi_blacklist *d;
  573. int i;
  574. d=&dmi_blacklist[0];
  575. while(d->callback)
  576. {
  577. for(i=0;i<4;i++)
  578. {
  579. int s = d->matches[i].slot;
  580. if(s==NONE)
  581. continue;
  582. if(dmi_ident[s] && strstr(dmi_ident[s], d->matches[i].substr))
  583. continue;
  584. /* No match */
  585. goto fail;
  586. }
  587. if(d->callback(d))
  588. return;
  589. fail:
  590. d++;
  591. }
  592. }
  593. /*
  594.  * Process a DMI table entry. Right now all we care about are the BIOS
  595.  * and machine entries. For 2.5 we should pull the smbus controller info
  596.  * out of here.
  597.  */
  598. static void __init dmi_decode(struct dmi_header *dm)
  599. {
  600. u8 *data = (u8 *)dm;
  601. char *p;
  602. switch(dm->type)
  603. {
  604. case  0:
  605. p=dmi_string(dm,data[4]);
  606. if(*p)
  607. {
  608. dmi_printk(("BIOS Vendor: %sn", p));
  609. dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
  610. dmi_printk(("BIOS Version: %sn", 
  611. dmi_string(dm, data[5])));
  612. dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
  613. dmi_printk(("BIOS Release: %sn",
  614. dmi_string(dm, data[8])));
  615. dmi_save_ident(dm, DMI_BIOS_DATE, 8);
  616. }
  617. break;
  618. case 1:
  619. p=dmi_string(dm,data[4]);
  620. if(*p)
  621. {
  622. dmi_printk(("System Vendor: %s.n",p));
  623. dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
  624. dmi_printk(("Product Name: %s.n",
  625. dmi_string(dm, data[5])));
  626. dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
  627. dmi_printk(("Version %s.n",
  628. dmi_string(dm, data[6])));
  629. dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
  630. dmi_printk(("Serial Number %s.n",
  631. dmi_string(dm, data[7])));
  632. }
  633. break;
  634. case 2:
  635. p=dmi_string(dm,data[4]);
  636. if(*p)
  637. {
  638. dmi_printk(("Board Vendor: %s.n",p));
  639. dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
  640. dmi_printk(("Board Name: %s.n",
  641. dmi_string(dm, data[5])));
  642. dmi_save_ident(dm, DMI_BOARD_NAME, 5);
  643. dmi_printk(("Board Version: %s.n",
  644. dmi_string(dm, data[6])));
  645. dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
  646. }
  647. break;
  648. case 3:
  649. p=dmi_string(dm,data[8]);
  650. if(*p && *p!=' ')
  651. dmi_printk(("Asset Tag: %s.n", p));
  652. break;
  653. }
  654. }
  655. static int __init dmi_scan_machine(void)
  656. {
  657. int err = dmi_iterate(dmi_decode);
  658. if(err == 0)
  659. dmi_check_blacklist();
  660. return err;
  661. }
  662. module_init(dmi_scan_machine);