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/sched.h> 29 #include <linux/smp.h> 30 #include <linux/string.h> 31 #include <linux/types.h> 32 #include <linux/irq.h> 33 #include <linux/errno.h> 34 #include <linux/acpi.h> 35 #include <linux/bootmem.h> 36 37 #define PREFIX "ACPI: " 38 39 #define ACPI_MAX_TABLES 128 40 41 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" }; 42 static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" }; 43 44 static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata; 45 46 void acpi_table_print_madt_entry(struct acpi_subtable_header * header) 47 { 48 if (!header) 49 return; 50 51 switch (header->type) { 52 53 case ACPI_MADT_TYPE_LOCAL_APIC: 54 { 55 struct acpi_madt_local_apic *p = 56 (struct acpi_madt_local_apic *)header; 57 printk(KERN_INFO PREFIX 58 "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n", 59 p->processor_id, p->id, 60 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); 61 } 62 break; 63 64 case ACPI_MADT_TYPE_IO_APIC: 65 { 66 struct acpi_madt_io_apic *p = 67 (struct acpi_madt_io_apic *)header; 68 printk(KERN_INFO PREFIX 69 "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n", 70 p->id, p->address, p->global_irq_base); 71 } 72 break; 73 74 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE: 75 { 76 struct acpi_madt_interrupt_override *p = 77 (struct acpi_madt_interrupt_override *)header; 78 printk(KERN_INFO PREFIX 79 "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n", 80 p->bus, p->source_irq, p->global_irq, 81 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 82 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]); 83 if (p->inti_flags & 84 ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)) 85 printk(KERN_INFO PREFIX 86 "INT_SRC_OVR unexpected reserved flags: 0x%x\n", 87 p->inti_flags & 88 ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK)); 89 90 } 91 break; 92 93 case ACPI_MADT_TYPE_NMI_SOURCE: 94 { 95 struct acpi_madt_nmi_source *p = 96 (struct acpi_madt_nmi_source *)header; 97 printk(KERN_INFO PREFIX 98 "NMI_SRC (%s %s global_irq %d)\n", 99 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 100 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 101 p->global_irq); 102 } 103 break; 104 105 case ACPI_MADT_TYPE_LOCAL_APIC_NMI: 106 { 107 struct acpi_madt_local_apic_nmi *p = 108 (struct acpi_madt_local_apic_nmi *)header; 109 printk(KERN_INFO PREFIX 110 "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n", 111 p->processor_id, 112 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK ], 113 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 114 p->lint); 115 } 116 break; 117 118 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE: 119 { 120 struct acpi_madt_local_apic_override *p = 121 (struct acpi_madt_local_apic_override *)header; 122 printk(KERN_INFO PREFIX 123 "LAPIC_ADDR_OVR (address[%p])\n", 124 (void *)(unsigned long)p->address); 125 } 126 break; 127 128 case ACPI_MADT_TYPE_IO_SAPIC: 129 { 130 struct acpi_madt_io_sapic *p = 131 (struct acpi_madt_io_sapic *)header; 132 printk(KERN_INFO PREFIX 133 "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n", 134 p->id, (void *)(unsigned long)p->address, 135 p->global_irq_base); 136 } 137 break; 138 139 case ACPI_MADT_TYPE_LOCAL_SAPIC: 140 { 141 struct acpi_madt_local_sapic *p = 142 (struct acpi_madt_local_sapic *)header; 143 printk(KERN_INFO PREFIX 144 "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n", 145 p->processor_id, p->id, p->eid, 146 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled"); 147 } 148 break; 149 150 case ACPI_MADT_TYPE_INTERRUPT_SOURCE: 151 { 152 struct acpi_madt_interrupt_source *p = 153 (struct acpi_madt_interrupt_source *)header; 154 printk(KERN_INFO PREFIX 155 "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n", 156 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK], 157 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2], 158 p->type, p->id, p->eid, p->io_sapic_vector, 159 p->global_irq); 160 } 161 break; 162 163 default: 164 printk(KERN_WARNING PREFIX 165 "Found unsupported MADT entry (type = 0x%x)\n", 166 header->type); 167 break; 168 } 169 } 170 171 172 int __init 173 acpi_table_parse_madt_family(char *id, 174 unsigned long madt_size, 175 int entry_id, 176 acpi_madt_entry_handler handler, 177 unsigned int max_entries) 178 { 179 struct acpi_table_header *madt = NULL; 180 struct acpi_subtable_header *entry; 181 unsigned int count = 0; 182 unsigned long madt_end; 183 184 if (!handler) 185 return -EINVAL; 186 187 /* Locate the MADT (if exists). There should only be one. */ 188 acpi_get_table(id, 0, &madt); 189 190 if (!madt) { 191 printk(KERN_WARNING PREFIX "%4.4s not present\n", id); 192 return -ENODEV; 193 } 194 195 madt_end = (unsigned long)madt + madt->length; 196 197 /* Parse all entries looking for a match. */ 198 199 entry = (struct acpi_subtable_header *) 200 ((unsigned long)madt + madt_size); 201 202 while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) < 203 madt_end) { 204 if (entry->type == entry_id 205 && (!max_entries || count++ < max_entries)) 206 if (handler(entry, madt_end)) 207 return -EINVAL; 208 209 entry = (struct acpi_subtable_header *) 210 ((unsigned long)entry + entry->length); 211 } 212 if (max_entries && count > max_entries) { 213 printk(KERN_WARNING PREFIX "[%4.4s:0x%02x] ignored %i entries of " 214 "%i found\n", id, entry_id, count - max_entries, count); 215 } 216 217 return count; 218 } 219 220 int __init 221 acpi_table_parse_madt(enum acpi_madt_type id, 222 acpi_madt_entry_handler handler, unsigned int max_entries) 223 { 224 return acpi_table_parse_madt_family(ACPI_SIG_MADT, 225 sizeof(struct acpi_table_madt), id, 226 handler, max_entries); 227 } 228 229 int __init acpi_table_parse(char *id, acpi_table_handler handler) 230 { 231 struct acpi_table_header *table = NULL; 232 if (!handler) 233 return -EINVAL; 234 235 acpi_get_table(id, 0, &table); 236 if (table) { 237 handler(table); 238 return 1; 239 } else 240 return 0; 241 } 242 243 /* 244 * acpi_table_init() 245 * 246 * find RSDP, find and checksum SDT/XSDT. 247 * checksum all tables, print SDT/XSDT 248 * 249 * result: sdt_entry[] is initialized 250 */ 251 252 253 int __init acpi_table_init(void) 254 { 255 acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); 256 return 0; 257 } 258