linux-old/arch/i386/kernel/acpitable.c
<<
>>
Prefs
   1/*
   2 *  acpitable.c - IA32-specific ACPI boot-time initialization (Revision: 1)
   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 *
  10 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  11 *
  12 *  This program is free software; you can redistribute it and/or modify
  13 *  it under the terms of the GNU General Public License as published by
  14 *  the Free Software Foundation; either version 2 of the License, or
  15 *  (at your option) any later version.
  16 *
  17 *  This program is distributed in the hope that it will be useful,
  18 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 *  GNU General Public License for more details.
  21 *
  22 *  You should have received a copy of the GNU General Public License
  23 *  along with this program; if not, write to the Free Software
  24 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25 *
  26 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27 *
  28 * $Id: acpitable.c,v 1.7 2001/11/04 12:21:18 fenrus Exp $
  29 */
  30#include <linux/config.h>
  31#include <linux/kernel.h>
  32#include <linux/init.h>
  33#include <linux/types.h>
  34#include <linux/stddef.h>
  35#include <linux/slab.h>
  36#include <linux/pci.h>
  37#include <asm/mpspec.h>
  38#include <asm/io.h>
  39#include <asm/apic.h>
  40#include <asm/apicdef.h>
  41#include <asm/page.h>
  42#include <asm/pgtable.h>
  43
  44#include "acpitable.h"
  45
  46static acpi_table_handler acpi_boot_ops[ACPI_TABLE_COUNT];
  47
  48
  49static unsigned char __init
  50acpi_checksum(void *buffer, int length)
  51{
  52        int i;
  53        unsigned char *bytebuffer;
  54        unsigned char sum = 0;
  55
  56        if (!buffer || length <= 0)
  57                return 0;
  58
  59        bytebuffer = (unsigned char *) buffer;
  60
  61        for (i = 0; i < length; i++)
  62                sum += *(bytebuffer++);
  63
  64        return sum;
  65}
  66
  67static void __init
  68acpi_print_table_header(acpi_table_header * header)
  69{
  70        if (!header)
  71                return;
  72
  73        printk(KERN_INFO "ACPI table found: %.4s v%d [%.6s %.8s %d.%d]\n",
  74               header->signature, header->revision, header->oem_id,
  75               header->oem_table_id, header->oem_revision >> 16,
  76               header->oem_revision & 0xffff);
  77
  78        return;
  79}
  80
  81/*******************************************************************************
  82 *
  83 * FUNCTION:    acpi_tb_scan_memory_for_rsdp
  84 *
  85 * PARAMETERS:  address       - Starting pointer for search
  86 *              length        - Maximum length to search
  87 *
  88 * RETURN:      Pointer to the RSDP if found and valid, otherwise NULL.
  89 *
  90 * DESCRIPTION: Search a block of memory for the RSDP signature
  91 *
  92 ******************************************************************************/
  93
  94static void *__init
  95acpi_tb_scan_memory_for_rsdp(void *address, int length)
  96{
  97        u32 offset;
  98
  99        if (length <= 0)
 100                return NULL;
 101
 102        /* Search from given start addr for the requested length  */
 103
 104        offset = 0;
 105
 106        while (offset < length) {
 107                /* The signature must match and the checksum must be correct */
 108                if (strncmp(address, RSDP_SIG, sizeof(RSDP_SIG) - 1) == 0 &&
 109                    acpi_checksum(address, RSDP_CHECKSUM_LENGTH) == 0) {
 110                        /* If so, we have found the RSDP */
 111                        printk(KERN_INFO "ACPI: RSDP located at physical address %p\n",
 112                               address);
 113                        return address;
 114                }
 115                offset += RSDP_SCAN_STEP;
 116                address += RSDP_SCAN_STEP;
 117        }
 118
 119        /* Searched entire block, no RSDP was found */
 120        printk(KERN_INFO "ACPI: Searched entire block, no RSDP was found.\n");
 121        return NULL;
 122}
 123
 124/*******************************************************************************
 125 *
 126 * FUNCTION:    acpi_find_root_pointer
 127 *
 128 * PARAMETERS:  none
 129 *
 130 * RETURN:      physical address of the RSDP 
 131 *
 132 * DESCRIPTION: Search lower 1_mbyte of memory for the root system descriptor
 133 *              pointer structure.  If it is found, set *RSDP to point to it.
 134 *
 135 *              NOTE: The RSDP must be either in the first 1_k of the Extended
 136 *              BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
 137 *              5.2.2; assertion #421).
 138 *
 139 ******************************************************************************/
 140
 141static struct acpi_table_rsdp * __init
 142acpi_find_root_pointer(void)
 143{
 144        struct acpi_table_rsdp * rsdp;
 145
 146        /*
 147         * Physical address is given
 148         */
 149        /*
 150         * Region 1) Search EBDA (low memory) paragraphs
 151         */
 152        rsdp = acpi_tb_scan_memory_for_rsdp(__va(LO_RSDP_WINDOW_BASE),
 153                                         LO_RSDP_WINDOW_SIZE);
 154
 155        if (rsdp)
 156                return rsdp;
 157
 158        /*
 159         * Region 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
 160         */
 161        rsdp = acpi_tb_scan_memory_for_rsdp(__va(HI_RSDP_WINDOW_BASE),
 162                                               HI_RSDP_WINDOW_SIZE);
 163
 164        
 165                                             
 166        if (rsdp)
 167                return rsdp;
 168
 169        printk(KERN_ERR "ACPI: System description tables not found\n");
 170        return NULL;
 171}
 172
 173
 174/*
 175 * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
 176 * to map the target physical address. The problem is that set_fixmap()
 177 * provides a single page, and it is possible that the page is not
 178 * sufficient.
 179 * By using this area, we can map up to MAX_IO_APICS pages temporarily,
 180 * i.e. until the next __va_range() call.
 181 *
 182 * Important Safety Note:  The fixed I/O APIC page numbers are *subtracted*
 183 * from the fixed base.  That's why we start at FIX_IO_APIC_BASE_END and
 184 * count idx down while incrementing the phys address.
 185 */
 186static __init char *
 187__va_range(unsigned long phys, unsigned long size)
 188{
 189        unsigned long base, offset, mapped_size;
 190        int idx;
 191
 192        offset = phys & (PAGE_SIZE - 1);
 193        mapped_size = PAGE_SIZE - offset;
 194        set_fixmap(FIX_IO_APIC_BASE_END, phys);
 195        base = fix_to_virt(FIX_IO_APIC_BASE_END);
 196        dprintk("__va_range(0x%lx, 0x%lx): idx=%d mapped at %lx\n", phys, size,
 197                FIX_IO_APIC_BASE_END, base);
 198
 199        /*
 200         * Most cases can be covered by the below.
 201         */
 202        idx = FIX_IO_APIC_BASE_END;
 203        while (mapped_size < size) {
 204                if (--idx < FIX_IO_APIC_BASE_0)
 205                        return 0;       /* cannot handle this */
 206                phys += PAGE_SIZE;
 207                set_fixmap(idx, phys);
 208                mapped_size += PAGE_SIZE;
 209        }
 210
 211        return ((unsigned char *) base + offset);
 212}
 213
 214static int __init acpi_tables_init(void)
 215{
 216        int result = -ENODEV;
 217        acpi_table_header *header = NULL;
 218        struct acpi_table_rsdp *rsdp = NULL;
 219        struct acpi_table_rsdt *rsdt = NULL;
 220        struct acpi_table_rsdt saved_rsdt;
 221        int tables = 0;
 222        int type = 0;
 223        int i = 0;
 224
 225
 226        rsdp = (struct acpi_table_rsdp *) acpi_find_root_pointer();
 227
 228        if (!rsdp)
 229                return -ENODEV;
 230                
 231        printk(KERN_INFO "%.8s v%d [%.6s]\n", rsdp->signature, rsdp->revision,
 232               rsdp->oem_id);
 233               
 234        if (strncmp(rsdp->signature, RSDP_SIG,strlen(RSDP_SIG))) {
 235                printk(KERN_WARNING "RSDP table signature incorrect\n");
 236                return -EINVAL;
 237        }
 238
 239        rsdt = (struct acpi_table_rsdt *)
 240            __va_range(rsdp->rsdt_address, sizeof(struct acpi_table_rsdt));
 241
 242        if (!rsdt) {
 243                printk(KERN_WARNING "ACPI: Invalid root system description tables (RSDT)\n");
 244                return -ENODEV;
 245        }
 246        
 247        header = & rsdt->header;
 248        acpi_print_table_header(header);
 249        
 250        if (strncmp(header->signature, RSDT_SIG, strlen(RSDT_SIG))) {
 251                printk(KERN_WARNING "ACPI: RSDT signature incorrect\n");
 252                return -ENODEV;
 253        }
 254                
 255        /* 
 256         * The number of tables is computed by taking the 
 257         * size of all entries (header size minus total 
 258         * size of RSDT) divided by the size of each entry
 259         * (4-byte table pointers).
 260         */
 261        tables = (header->length - sizeof(acpi_table_header)) / 4;
 262                    
 263        memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt));
 264
 265        if (saved_rsdt.header.length > sizeof(saved_rsdt)) {
 266                printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", saved_rsdt.header.length);
 267                return -ENODEV;
 268        }
 269
 270        for (i = 0; i < tables; i++) {
 271                /* Map in header, then map in full table length. */
 272                header = (acpi_table_header *)
 273                            __va_range(saved_rsdt.entry[i],
 274                                       sizeof(acpi_table_header));
 275                if (!header)
 276                        break;
 277                header = (acpi_table_header *)
 278                            __va_range(saved_rsdt.entry[i], header->length);
 279                if (!header)
 280                        break;
 281
 282                acpi_print_table_header(header);
 283                
 284                if (acpi_checksum(header,header->length)) {
 285                        printk(KERN_WARNING "ACPI %s has invalid checksum\n", 
 286                                acpi_table_signatures[i]);
 287                        continue;
 288                }
 289                
 290                for (type = 0; type < ACPI_TABLE_COUNT; type++)
 291                        if (!strncmp((char *) &header->signature,
 292                             acpi_table_signatures[type],strlen(acpi_table_signatures[type])))
 293                                break;
 294
 295                if (type >= ACPI_TABLE_COUNT) {
 296                        printk(KERN_WARNING "ACPI: Unsupported table %.4s\n",
 297                               header->signature);
 298                        continue;
 299                }
 300
 301
 302                if (!acpi_boot_ops[type])
 303                        continue;
 304                        
 305                result = acpi_boot_ops[type] (header,
 306                                                 (unsigned long) saved_rsdt.
 307                                                 entry[i]);
 308        }
 309
 310        return result;
 311}
 312
 313static int total_cpus __initdata = 0;
 314int have_acpi_tables;
 315
 316extern void __init MP_processor_info(struct mpc_config_processor *);
 317
 318static void __init
 319acpi_parse_lapic(struct acpi_table_lapic *local_apic)
 320{
 321        struct mpc_config_processor proc_entry;
 322        int ix = 0;
 323
 324        if (!local_apic)
 325                return;
 326
 327        printk(KERN_INFO "LAPIC (acpi_id[0x%04x] id[0x%x] enabled[%d])\n",
 328                local_apic->acpi_id, local_apic->id, local_apic->flags.enabled);
 329
 330        printk(KERN_INFO "CPU %d (0x%02x00)", total_cpus, local_apic->id);
 331
 332        if (local_apic->flags.enabled) {
 333                printk(" enabled");
 334                ix = local_apic->id;
 335                if (ix >= MAX_APICS) {
 336                        printk(KERN_WARNING
 337                               "Processor #%d INVALID - (Max ID: %d).\n", ix,
 338                               MAX_APICS);
 339                        return;
 340                }
 341                /* 
 342                 * Fill in the info we want to save.  Not concerned about 
 343                 * the processor ID.  Processor features aren't present in 
 344                 * the table.
 345                 */
 346                proc_entry.mpc_type = MP_PROCESSOR;
 347                proc_entry.mpc_apicid = local_apic->id;
 348                proc_entry.mpc_cpuflag = CPU_ENABLED;
 349                if (proc_entry.mpc_apicid == boot_cpu_physical_apicid) {
 350                        printk(" (BSP)");
 351                        proc_entry.mpc_cpuflag |= CPU_BOOTPROCESSOR;
 352                }
 353                proc_entry.mpc_cpufeature =
 354                    (boot_cpu_data.x86 << 8) | 
 355                    (boot_cpu_data.x86_model << 4) | 
 356                     boot_cpu_data.x86_mask;
 357                proc_entry.mpc_featureflag = boot_cpu_data.x86_capability[0];
 358                proc_entry.mpc_reserved[0] = 0;
 359                proc_entry.mpc_reserved[1] = 0;
 360                proc_entry.mpc_apicver = 0x10;  /* integrated APIC */
 361                MP_processor_info(&proc_entry);
 362        } else {
 363                printk(" disabled");
 364        }
 365        printk("\n");
 366
 367        total_cpus++;
 368        return;
 369}
 370
 371static void __init
 372acpi_parse_ioapic(struct acpi_table_ioapic *ioapic)
 373{
 374
 375        if (!ioapic)
 376                return;
 377
 378        printk(KERN_INFO
 379               "IOAPIC (id[0x%x] address[0x%x] global_irq_base[0x%x])\n",
 380               ioapic->id, ioapic->address, ioapic->global_irq_base);
 381
 382        if (nr_ioapics >= MAX_IO_APICS) {
 383                printk(KERN_WARNING
 384                       "Max # of I/O APICs (%d) exceeded (found %d).\n",
 385                       MAX_IO_APICS, nr_ioapics);
 386/*              panic("Recompile kernel with bigger MAX_IO_APICS!\n");   */
 387        }
 388}
 389
 390
 391/* Interrupt source overrides inform the machine about exceptions
 392   to the normal "PIC" mode interrupt routing */
 393   
 394static void __init
 395acpi_parse_int_src_ovr(struct acpi_table_int_src_ovr *intsrc)
 396{
 397        if (!intsrc)
 398                return;
 399
 400        printk(KERN_INFO
 401               "INT_SRC_OVR (bus[%d] irq[0x%x] global_irq[0x%x] polarity[0x%x] trigger[0x%x])\n",
 402               intsrc->bus, intsrc->bus_irq, intsrc->global_irq,
 403               intsrc->flags.polarity, intsrc->flags.trigger);
 404}
 405
 406/*
 407 * At this point, we look at the interrupt assignment entries in the MPS
 408 * table.
 409 */ 
 410 
 411static void __init acpi_parse_nmi_src(struct acpi_table_nmi_src *nmisrc)
 412{
 413        if (!nmisrc)
 414                return;
 415
 416        printk(KERN_INFO
 417               "NMI_SRC (polarity[0x%x] trigger[0x%x] global_irq[0x%x])\n",
 418               nmisrc->flags.polarity, nmisrc->flags.trigger,
 419               nmisrc->global_irq);
 420
 421}
 422static void __init
 423acpi_parse_lapic_nmi(struct acpi_table_lapic_nmi *localnmi)
 424{
 425        if (!localnmi)
 426                return;
 427
 428        printk(KERN_INFO
 429               "LAPIC_NMI (acpi_id[0x%04x] polarity[0x%x] trigger[0x%x] lint[0x%x])\n",
 430               localnmi->acpi_id, localnmi->flags.polarity,
 431               localnmi->flags.trigger, localnmi->lint);
 432}
 433static void __init
 434acpi_parse_lapic_addr_ovr(struct acpi_table_lapic_addr_ovr *lapic_addr_ovr)
 435{
 436        if (!lapic_addr_ovr)
 437                return;
 438
 439        printk(KERN_INFO "LAPIC_ADDR_OVR (address[0x%lx])\n",
 440               (unsigned long) lapic_addr_ovr->address);
 441
 442}
 443
 444static void __init
 445acpi_parse_plat_int_src(struct acpi_table_plat_int_src *plintsrc)
 446{
 447        if (!plintsrc)
 448                return;
 449
 450        printk(KERN_INFO
 451               "PLAT_INT_SRC (polarity[0x%x] trigger[0x%x] type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
 452               plintsrc->flags.polarity, plintsrc->flags.trigger,
 453               plintsrc->type, plintsrc->id, plintsrc->eid,
 454               plintsrc->iosapic_vector, plintsrc->global_irq);
 455}
 456static int __init
 457acpi_parse_madt(acpi_table_header * header, unsigned long phys)
 458{
 459
 460        struct acpi_table_madt *madt;       
 461        acpi_madt_entry_header *entry_header;
 462        int table_size;
 463        
 464        madt = (struct acpi_table_madt *) __va_range(phys, header->length);
 465
 466        if (!madt)
 467                return -EINVAL;
 468
 469        table_size = (int) (header->length - sizeof(*madt));
 470        entry_header =
 471            (acpi_madt_entry_header *) ((void *) madt + sizeof(*madt));
 472
 473        while (entry_header && (table_size > 0)) {
 474                switch (entry_header->type) {
 475                case ACPI_MADT_LAPIC:
 476                        acpi_parse_lapic((struct acpi_table_lapic *)
 477                                         entry_header);
 478                        break;
 479                case ACPI_MADT_IOAPIC:
 480                        acpi_parse_ioapic((struct acpi_table_ioapic *)
 481                                          entry_header);
 482                        break;
 483                case ACPI_MADT_INT_SRC_OVR:
 484                        acpi_parse_int_src_ovr((struct acpi_table_int_src_ovr *)
 485                                               entry_header);
 486                        break;
 487                case ACPI_MADT_NMI_SRC:
 488                        acpi_parse_nmi_src((struct acpi_table_nmi_src *)
 489                                           entry_header);
 490                        break;
 491                case ACPI_MADT_LAPIC_NMI:
 492                        acpi_parse_lapic_nmi((struct acpi_table_lapic_nmi *)
 493                                             entry_header);
 494                        break;
 495                case ACPI_MADT_LAPIC_ADDR_OVR:
 496                        acpi_parse_lapic_addr_ovr((struct
 497                                                   acpi_table_lapic_addr_ovr *)
 498                                                  entry_header);
 499                        break;
 500                case ACPI_MADT_PLAT_INT_SRC:
 501                        acpi_parse_plat_int_src((struct acpi_table_plat_int_src
 502                                                 *) entry_header);
 503                        break;
 504                default:
 505                        printk(KERN_WARNING
 506                               "Unsupported MADT entry type 0x%x\n",
 507                               entry_header->type);
 508                        break;
 509                }
 510                table_size -= entry_header->length;
 511                entry_header =
 512                    (acpi_madt_entry_header *) ((void *) entry_header +
 513                                                entry_header->length);
 514        }
 515
 516        if (!total_cpus) {
 517                printk("ACPI: No Processors found in the APCI table.\n");
 518                return -EINVAL;
 519        }
 520
 521        printk(KERN_INFO "%d CPUs total\n", total_cpus);
 522
 523        if (madt->lapic_address)
 524                mp_lapic_addr = madt->lapic_address;
 525        else
 526                mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
 527
 528        printk(KERN_INFO "Local APIC address %x\n", madt->lapic_address);
 529
 530        return 0;
 531}
 532
 533extern int enable_acpi_smp_table;
 534
 535/*
 536 * Configure the processor info using MADT in the ACPI tables. If we fail to
 537 * configure that, then we use the MPS tables.
 538 */
 539void __init
 540config_acpi_tables(void)
 541{
 542
 543        memset(&acpi_boot_ops, 0, sizeof(acpi_boot_ops));
 544        acpi_boot_ops[ACPI_APIC] = acpi_parse_madt;
 545
 546        /*
 547         * Only do this when requested, either because of CPU/Bios type or from the command line
 548         */
 549
 550        if (enable_acpi_smp_table && !acpi_tables_init()) {
 551                have_acpi_tables = 1;
 552                printk("Enabling the CPU's according to the ACPI table\n");
 553        }
 554}
 555
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.