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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  acpitable.c - x86-64-specific ACPI (1.0 & 2.0) boot-time initialization
  3.  *
  4.  *  Copyright (C) 1999 Andrew Henroid
  5.  *  Copyright (C) 2001 Richard Schaal
  6.  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
  7.  *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
  8.  *  Copyright (C) 2001 Arjan van de Ven <arjanv@redhat.com>
  9.  *  Copyright (C) 2002 Vojtech Pavlik <vojtech@suse.cz>
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/kernel.h>
  13. #include <linux/init.h>
  14. #include <linux/types.h>
  15. #include <linux/stddef.h>
  16. #include <linux/slab.h>
  17. #include <linux/pci.h>
  18. #include <asm/mpspec.h>
  19. #include <asm/io.h>
  20. #include <asm/apic.h>
  21. #include <asm/apicdef.h>
  22. #include <asm/page.h>
  23. #include <asm/pgtable.h>
  24. #include <asm/fixmap.h>
  25. #include "acpitable.h"
  26. static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT];
  27. extern unsigned long end_pfn;
  28. static inline int bad_ptr(void *p) 
  29. if ((unsigned long)p  >> PAGE_SHIFT >= end_pfn) 
  30. return 1; 
  31. return 0; 
  32. /*
  33.  * Checksum an ACPI table.
  34.  */
  35. static unsigned char __init acpi_checksum(void *buffer, int length)
  36. {
  37. unsigned char sum = 0;
  38. while (length--)
  39. sum += *(unsigned char *)buffer++;
  40. return sum;
  41. }
  42. /*
  43.  * Print an ACPI table header for debugging.
  44.  */
  45. static char __init *acpi_kill_spaces(char *t, char *s, int m)
  46. {
  47. int l = strnlen(s, m);
  48. strncpy(t, s, m);
  49. t[l] = 0;
  50. while (l > 0 && (t[l - 1] == ' ' || t[l - 1] == 't')) t[--l] = 0;
  51. while (t[0] == ' ' || t[0] == 't') t++;
  52. return t;
  53. }
  54. static void __init acpi_print_table_header(struct acpi_table_header * header)
  55. {
  56. char oem[7], id[9];
  57. printk(KERN_INFO "acpi: %.4s rev: %d oem: %s id: %s build: %d.%dn",
  58. header->signature, header->revision, acpi_kill_spaces(oem, header->oem_id, 6),
  59. acpi_kill_spaces(id, header->oem_table_id, 8), header->oem_revision >> 16,
  60. header->oem_revision & 0xffff);
  61. }
  62. /*
  63.  * Search a block of memory for the RSDP signature
  64.  */
  65. static void* __init acpi_tb_scan_memory_for_rsdp(void *address, int length)
  66. {
  67. u32 offset = 0;
  68. while (offset < length) {
  69. if (strncmp(address, "RSD PTR ", 8) == 0 &&
  70.     acpi_checksum(address, RSDP_CHECKSUM_LENGTH) == 0) {
  71. printk(KERN_INFO "acpi: RSDP found at address %pn", address);
  72. return address;
  73. }
  74. offset += RSDP_SCAN_STEP;
  75. address += RSDP_SCAN_STEP;
  76. }
  77. return NULL;
  78. }
  79. /*
  80.  * Search lower 1_mbyte of memory for the root system descriptor
  81.  * pointer structure. If it is found, set *RSDP to point to it.
  82.  */
  83. static struct acpi_table_rsdp* __init acpi_find_root_pointer(void)
  84. {
  85. struct acpi_table_rsdp *rsdp;
  86. if ((rsdp = acpi_tb_scan_memory_for_rsdp(__va(LO_RSDP_WINDOW_BASE), LO_RSDP_WINDOW_SIZE)))
  87. return rsdp;
  88. if ((rsdp = acpi_tb_scan_memory_for_rsdp(__va(HI_RSDP_WINDOW_BASE), HI_RSDP_WINDOW_SIZE)))
  89. return rsdp;
  90. return NULL;
  91. }
  92. static int __init acpi_process_table(u64 table)
  93. {
  94. struct acpi_table_header *header;
  95. int type;
  96. header = __va(table);
  97. acpi_print_table_header(header);
  98. if (acpi_checksum(header, header->length)) {
  99. printk(KERN_WARNING "acpi: ACPI table at %#lx has invalid checksum.n", table);
  100. return -1;
  101. }
  102. for (type = 0; type < ACPI_TABLE_COUNT; type++)
  103. if (!strncmp(header->signature, acpi_table_signatures[type], 4))
  104. break;
  105. if (type == ACPI_TABLE_COUNT || !acpi_boot_ops[type])
  106. return 0;
  107. return acpi_boot_ops[type](header, table);
  108. }
  109. static int __init acpi_tables_init(void)
  110. {
  111. struct acpi_table_rsdp *rsdp;
  112. struct acpi_table_xsdt *xsdt = NULL;
  113. struct acpi_table_rsdt *rsdt = NULL;
  114. char oem[7];
  115. int i;
  116. if (!(rsdp = acpi_find_root_pointer())) {
  117. printk(KERN_ERR "acpi: Couldn't find ACPI root pointer!n");
  118. return -1;
  119. }
  120. printk(KERN_INFO "acpi: RSDP rev: %d oem: %sn",
  121. rsdp->revision, acpi_kill_spaces(oem, rsdp->oem_id, 6));
  122. if (!acpi_checksum(rsdp, RSDP2_CHECKSUM_LENGTH)
  123. && rsdp->length >= RSDP2_CHECKSUM_LENGTH) { /* ACPI 2.0 might be present */
  124. xsdt = __va(rsdp->xsdt_address);
  125. if (bad_ptr(xsdt))
  126. return -1; 
  127. if (!strncmp(xsdt->header.signature, "XSDT", 4)) {
  128. acpi_print_table_header(&xsdt->header);
  129. for (i = 0; i < (xsdt->header.length - sizeof(struct acpi_table_header)) / sizeof(u64); i++)
  130. if (acpi_process_table(xsdt->entry[i]))
  131. return -1;
  132. return 0;
  133. }
  134. }
  135. rsdt = __va(rsdp->rsdt_address);
  136. if (bad_ptr(rsdt))
  137. return -1;
  138. if (!strncmp(rsdt->header.signature, "RSDT", 4)) {
  139. acpi_print_table_header(&rsdt->header);
  140. for (i = 0; i < (rsdt->header.length - sizeof(struct acpi_table_header)) / sizeof(u32); i++)
  141. if (acpi_process_table(rsdt->entry[i]))
  142. return -1;
  143. return 0;
  144. }
  145. printk(KERN_WARNING "acpi: No ACPI table directory found.n");
  146. return -1;
  147. }
  148. static void __init acpi_parse_lapic(struct acpi_table_lapic *local_apic)
  149. {
  150. printk(KERN_INFO "acpi: LAPIC acpi_id: %d id: %d enabled: %dn",
  151. local_apic->acpi_id, local_apic->id, local_apic->flags.enabled);
  152. }
  153. static void __init acpi_parse_ioapic(struct acpi_table_ioapic *ioapic)
  154. {
  155. printk(KERN_INFO "acpi: IOAPIC id: %d address: %#x global_irq_base: %#xn",
  156. ioapic->id, ioapic->address, ioapic->global_irq_base);
  157. }
  158. static void __init acpi_parse_int_src_ovr(struct acpi_table_int_src_ovr *intsrc)
  159. {
  160. printk(KERN_INFO "acpi: INT_SRC_OVR bus: %d irq: %d global_irq: %d polarity: %d trigger: %dn",
  161. intsrc->bus, intsrc->bus_irq, intsrc->global_irq, intsrc->flags.polarity, intsrc->flags.trigger);
  162. }
  163. static void __init acpi_parse_nmi_src(struct acpi_table_nmi_src *nmisrc)
  164. {
  165. printk(KERN_INFO "acpi: NMI_SRC polarity: %d trigger: %d global_irq: %dn",
  166. nmisrc->flags.polarity, nmisrc->flags.trigger, nmisrc->global_irq);
  167. }
  168. static void __init acpi_parse_lapic_nmi(struct acpi_table_lapic_nmi *localnmi)
  169. {
  170. printk(KERN_INFO "acpi: LAPIC_NMI acpi_id: %d polarity: %d trigger: %d lint: %dn",
  171. localnmi->acpi_id, localnmi->flags.polarity, localnmi->flags.trigger, localnmi->lint);
  172. }
  173. static void __init acpi_parse_lapic_addr_ovr(struct acpi_table_lapic_addr_ovr *lapic_addr_ovr)
  174. {
  175. printk(KERN_INFO "acpi: LAPIC_ADDR_OVR address: %#lxn",
  176. (unsigned long) lapic_addr_ovr->address);
  177. }
  178. static void __init acpi_parse_plat_int_src(struct acpi_table_plat_int_src *plintsrc)
  179. {
  180. printk(KERN_INFO "acpi: PLAT_INT_SRC polarity: %d trigger: %d type: %d id: %d eid: %d iosapic_vector: %#x global_irq: %dn",
  181. plintsrc->flags.polarity, plintsrc->flags.trigger, plintsrc->type, plintsrc->id, plintsrc->eid,
  182. plintsrc->iosapic_vector, plintsrc->global_irq);
  183. }
  184. static int __init acpi_parse_madt(struct acpi_table_header *header, unsigned long phys)
  185. {
  186. struct acpi_table_madt *madt;
  187. struct acpi_madt_entry_header *entry_header;
  188. int table_size;
  189. madt = __va(phys);
  190. table_size = header->length - sizeof(*madt);
  191. entry_header = (void *)madt + sizeof(*madt);
  192. while (entry_header && table_size > 0) {
  193. switch (entry_header->type) {
  194. case ACPI_MADT_LAPIC:
  195. acpi_parse_lapic((void *) entry_header);
  196. break;
  197. case ACPI_MADT_IOAPIC:
  198. acpi_parse_ioapic((void *) entry_header);
  199. break;
  200. case ACPI_MADT_INT_SRC_OVR:
  201. acpi_parse_int_src_ovr((void *) entry_header);
  202. break;
  203. case ACPI_MADT_NMI_SRC:
  204. acpi_parse_nmi_src((void *) entry_header);
  205. break;
  206. case ACPI_MADT_LAPIC_NMI:
  207. acpi_parse_lapic_nmi((void *) entry_header);
  208. break;
  209. case ACPI_MADT_LAPIC_ADDR_OVR:
  210. acpi_parse_lapic_addr_ovr((void *) entry_header);
  211. break;
  212. case ACPI_MADT_PLAT_INT_SRC:
  213. acpi_parse_plat_int_src((void *) entry_header);
  214. break;
  215. default:
  216. printk(KERN_WARNING "acpi: Unsupported MADT entry type 0x%xn", entry_header->type);
  217. break;
  218. }
  219. table_size -= entry_header->length;
  220. entry_header = (void *) entry_header + entry_header->length;
  221. }
  222. printk(KERN_INFO "acpi: Local APIC address %#xn", madt->lapic_address);
  223. return 0;
  224. }
  225. static int __init acpi_parse_hpet(struct acpi_table_header *header, unsigned long phys)
  226. {
  227. struct acpi_table_hpet *hpet_tbl;
  228. hpet_tbl = __va(phys);
  229. if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
  230. printk(KERN_WARNING "acpi: HPET timers must be located in memory.n");
  231. return -1;
  232. }
  233. hpet.address = hpet_tbl->addr.addrl | ((long) hpet_tbl->addr.addrh << 32);
  234. printk(KERN_INFO "acpi: HPET id: %#x base: %#lxn", hpet_tbl->id, hpet.address);
  235. return 0;
  236. }
  237. /*
  238.  * Configure the processor info using MADT in the ACPI tables. If we fail to
  239.  * configure that, then we use the MPS tables.
  240.  */
  241. void __init config_acpi_tables(void)
  242. {
  243. acpi_boot_ops[ACPI_APIC] = acpi_parse_madt;
  244. acpi_boot_ops[ACPI_HPET] = acpi_parse_hpet;
  245. if (acpi_tables_init())
  246. printk(KERN_ERR "acpi: Init failed.n");
  247. }