1 /* 2 * acpi_tables.c - ACPI Boot-Time Table Parsing 3 * 4 * Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 5 * 6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 * 24 */ 25 26 #include <linux/init.h> 27 #include <linux/kernel.h> 28 #include <linux/smp.h> 29 #include <linux/string.h> 30 #include <linux/types.h> 31 #include <linux/irq.h> 32 #include <linux/errno.h> 33 #include <linux/acpi.h> 34 #include <linux/bootmem.h> 35 36 #define PREFIX "ACPI: " 37 38 #define ACPI_MAX_TABLES 128 39 40 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; 41 static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; 42 43 static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; 44 45 void acpi_table_print_madt_entry(struct acpi_subtable_header * header) 46 { 47 if (!header) 48 return; 49 50 switch (header->type) { 51 52 case ACPI_MADT_TYPE_LOCAL_APIC: 53 { 54 struct acpi_madt_local_apic *p = 55 (struct acpi_madt_local_apic *)header; 56 printk(KERN_INFO PREFIX 57 "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", 58 p->processor_id, p->id, 59 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); 60 } 61 break; 62 63 case ACPI_MADT_TYPE_IO_APIC: 64 { 65 struct acpi_madt_io_apic *p = 66 (struct acpi_madt_io_apic *)header; 67 printk(KERN_INFO PREFIX 68 "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", 69 p->id, p->address, p->global_irq_base); 70 } 71 break; 72 73 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 74 { 75 struct acpi_madt_interrupt_override *p = 76 (struct acpi_madt_interrupt_override *)header; 77 printk(KERN_INFO PREFIX 78 "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", 79 p->bus, p->source_irq, p->global_irq, 80 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 81 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]); 82 if (p->inti_flags & 83 ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)) 84 printk(KERN_INFO PREFIX 85 "INT_SRC_OVR unexpected reserved flags: 0x%x\n", 86 p->inti_flags & 87 ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)); 88 89 } 90 break; 91 92 case ACPI_MADT_TYPE_NMI_SOURCE: 93 { 94 struct acpi_madt_nmi_source *p = 95 (struct acpi_madt_nmi_source *)header; 96 printk(KERN_INFO PREFIX 97 "NMI_SRC (%s %s global_irq %d)\n", 98 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 99 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 100 p->global_irq); 101 } 102 break; 103 104 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 105 { 106 struct acpi_madt_local_apic_nmi *p = 107 (struct acpi_madt_local_apic_nmi *)header; 108 printk(KERN_INFO PREFIX 109 "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", 110 p->processor_id, 111 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK ], 112 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 113 p->lint); 114 } 115 break; 116 117 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 118 { 119 struct acpi_madt_local_apic_override *p = 120 (struct acpi_madt_local_apic_override *)header; 121 printk(KERN_INFO PREFIX 122 "LAPIC_ADDR_OVR (address[%p])\n", 123 (void *)(unsigned long)p->address); 124 } 125 break; 126 127 case ACPI_MADT_TYPE_IO_SAPIC: 128 { 129 struct acpi_madt_io_sapic *p = 130 (struct acpi_madt_io_sapic *)header; 131 printk(KERN_INFO PREFIX 132 "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", 133 p->id, (void *)(unsigned long)p->address, 134 p->global_irq_base); 135 } 136 break; 137 138 case ACPI_MADT_TYPE_LOCAL_SAPIC: 139 { 140 struct acpi_madt_local_sapic *p = 141 (struct acpi_madt_local_sapic *)header; 142 printk(KERN_INFO PREFIX 143 "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", 144 p->processor_id, p->id, p->eid, 145 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); 146 } 147 break; 148 149 case ACPI_MADT_TYPE_INTERRUPT_SOURCE: 150 { 151 struct acpi_madt_interrupt_source *p = 152 (struct acpi_madt_interrupt_source *)header; 153 printk(KERN_INFO PREFIX 154 "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", 155 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 156 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 157 p->type, p->id, p->eid, p->io_sapic_vector, 158 p->global_irq); 159 } 160 break; 161 162 default: 163 printk(KERN_WARNING PREFIX 164 "Found unsupported MADT entry (type = 0x%x)\n", 165 header->type); 166 break; 167 } 168 } 169 170 171 int __init 172 acpi_table_parse_entries(char *id, 173 unsigned long table_size, 174 int entry_id, 175 acpi_table_entry_handler handler, 176 unsigned int max_entries) 177 { 178 struct acpi_table_header *table_header = NULL; 179 struct acpi_subtable_header *entry; 180 unsigned int count = 0; 181 unsigned long table_end; 182 183 if (!handler) 184 return -EINVAL; 185 186 /* Locate the table (if exists). There should only be one. */ 187 acpi_get_table(id, 0, &table_header); 188 189 if (!table_header) { 190 printk(KERN_WARNING PREFIX "%4.4s not present\n", id); 191 return -ENODEV; 192 } 193 194 table_end = (unsigned long)table_header + table_header->length; 195 196 /* Parse all entries looking for a match. */ 197 198 entry = (struct acpi_subtable_header *) 199 ((unsigned long)table_header + table_size); 200 201 while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < 202 table_end) { 203 if (entry->type == entry_id 204 && (!max_entries || count++ < max_entries)) 205 if (handler(entry, table_end)) 206 return -EINVAL; 207 208 entry = (struct acpi_subtable_header *) 209 ((unsigned long)entry + entry->length); 210 } 211 if (max_entries && count > max_entries) { 212 printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of " 213 "%i found\n", id, entry_id, count - max_entries, count); 214 } 215 216 return count; 217 } 218 219 int __init 220 acpi_table_parse_madt(enum acpi_madt_type id, 221 acpi_table_entry_handler handler, unsigned int max_entries) 222 { 223 return acpi_table_parse_entries(ACPI_SIG_MADT, 224 sizeof(struct acpi_table_madt), id, 225 handler, max_entries); 226 } 227 228 /** 229 * acpi_table_parse - find table with @id, run @handler on it 230 * 231 * @id: table id to find 232 * @handler: handler to run 233 * 234 * Scan the ACPI System Descriptor Table (STD) for a table matching @id, 235 * run @handler on it. Return 0 if table found, return on if not. 236 */ 237 int __init acpi_table_parse(char *id, acpi_table_handler handler) 238 { 239 struct acpi_table_header *table = NULL; 240 if (!handler) 241 return -EINVAL; 242 243 acpi_get_table(id, 0, &table); 244 if (table) { 245 handler(table); 246 return 0; 247 } else 248 return 1; 249 } 250 251 /* 252 * acpi_table_init() 253 * 254 * find RSDP, find and checksum SDT/XSDT. 255 * checksum all tables, print SDT/XSDT 256 * 257 * result: sdt_entry[] is initialized 258 */ 259 260 261 int __init acpi_table_init(void) 262 { 263 acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); 264 return 0; 265 } 266