boot.c 19.3 KB
Newer Older
Andy Grover's avatar
Andy Grover committed
1
/*
2
 *  boot.c - Architecture-Specific Low-Level ACPI Boot Support
Andy Grover's avatar
Andy Grover committed
3
 *
Andy Grover's avatar
Andy Grover committed
4
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
Andy Grover's avatar
Andy Grover committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *  Copyright (C) 2001 Jun Nakajima <jun.nakajima@intel.com>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

#include <linux/init.h>
Dave Jones's avatar
Dave Jones committed
27
#include <linux/config.h>
Andy Grover's avatar
Andy Grover committed
28
#include <linux/acpi.h>
Andrew Morton's avatar
Andrew Morton committed
29
#include <linux/efi.h>
30
#include <linux/irq.h>
31
#include <linux/module.h>
Andy Grover's avatar
Andy Grover committed
32
#include <asm/pgalloc.h>
33
#include <asm/io_apic.h>
34
#include <asm/apic.h>
35
#include <asm/io.h>
36
#include <asm/irq.h>
37
#include <asm/mpspec.h>
Andy Grover's avatar
Andy Grover committed
38

39 40 41 42 43 44 45 46 47 48
#ifdef	CONFIG_X86_64

static inline void  acpi_madt_oem_check(char *oem_id, char *oem_table_id) { }
static inline void clustered_apic_check(void) { }
static inline int ioapic_setup_disabled(void) { return 0; }
#include <asm/proto.h>

#else	/* X86 */

#ifdef	CONFIG_X86_LOCAL_APIC
49 50
#include <mach_apic.h>
#include <mach_mpparse.h>
51 52 53
#endif	/* CONFIG_X86_LOCAL_APIC */

#endif	/* X86 */
Andy Grover's avatar
Andy Grover committed
54

55 56 57 58
#define BAD_MADT_ENTRY(entry, end) (					    \
		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
		((acpi_table_entry_header *)entry)->length != sizeof(*entry))

Andy Grover's avatar
Andy Grover committed
59 60
#define PREFIX			"ACPI: "

61
#ifdef CONFIG_ACPI_PCI
62
int acpi_noirq __initdata;	/* skip ACPI IRQ initialization */
63 64 65 66 67
int acpi_pci_disabled __initdata; /* skip ACPI PCI scan and IRQ initialization */
#else
int acpi_noirq __initdata = 1;
int acpi_pci_disabled __initdata = 1;
#endif
68
int acpi_ht __initdata = 1;	/* enable HT */
Andy Grover's avatar
Andy Grover committed
69

70 71
int acpi_lapic;
int acpi_ioapic;
72
int acpi_strict;
73

74 75
acpi_interrupt_flags acpi_sci_flags __initdata;
int acpi_sci_override_gsi __initdata;
76
int acpi_skip_timer_override __initdata;
77

78 79 80 81
#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#endif

82 83 84 85
#ifndef __HAVE_ARCH_CMPXCHG
#warning ACPI uses CMPXCHG, i486 and later hardware
#endif

Andy Grover's avatar
Andy Grover committed
86 87 88 89
/* --------------------------------------------------------------------------
                              Boot-time Configuration
   -------------------------------------------------------------------------- */

90 91 92 93 94
/*
 * The default interrupt routing model is PIC (8259).  This gets
 * overriden if IOAPICs are enumerated (below).
 */
enum acpi_irq_model_id		acpi_irq_model = ACPI_IRQ_MODEL_PIC;
Andy Grover's avatar
Andy Grover committed
95

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
#ifdef	CONFIG_X86_64

/* rely on all ACPI tables being in the direct mapping */
char *__acpi_map_table(unsigned long phys_addr, unsigned long size)
{
	if (!phys_addr || !size)
	return NULL;

	if (phys_addr < (end_pfn_map << PAGE_SHIFT))
		return __va(phys_addr);

	return NULL;
}

#else

Andy Grover's avatar
Andy Grover committed
112
/*
Andy Grover's avatar
ACPI:  
Andy Grover committed
113 114 115 116 117 118 119 120 121 122
 * Temporarily use the virtual area starting from FIX_IO_APIC_BASE_END,
 * to map the target physical address. The problem is that set_fixmap()
 * provides a single page, and it is possible that the page is not
 * sufficient.
 * By using this area, we can map up to MAX_IO_APICS pages temporarily,
 * i.e. until the next __va_range() call.
 *
 * Important Safety Note:  The fixed I/O APIC page numbers are *subtracted*
 * from the fixed base.  That's why we start at FIX_IO_APIC_BASE_END and
 * count idx down while incrementing the phys address.
Andy Grover's avatar
Andy Grover committed
123
 */
Andy Grover's avatar
ACPI:  
Andy Grover committed
124
char *__acpi_map_table(unsigned long phys, unsigned long size)
Andy Grover's avatar
Andy Grover committed
125
{
Andy Grover's avatar
ACPI:  
Andy Grover committed
126 127 128 129 130 131 132 133
	unsigned long base, offset, mapped_size;
	int idx;

	if (phys + size < 8*1024*1024) 
		return __va(phys); 

	offset = phys & (PAGE_SIZE - 1);
	mapped_size = PAGE_SIZE - offset;
134 135
	set_fixmap(FIX_ACPI_END, phys);
	base = fix_to_virt(FIX_ACPI_END);
Andy Grover's avatar
ACPI:  
Andy Grover committed
136 137 138 139

	/*
	 * Most cases can be covered by the below.
	 */
140
	idx = FIX_ACPI_END;
Andy Grover's avatar
ACPI:  
Andy Grover committed
141
	while (mapped_size < size) {
142
		if (--idx < FIX_ACPI_BEGIN)
Andy Grover's avatar
ACPI:  
Andy Grover committed
143 144 145 146
			return 0;	/* cannot handle this */
		phys += PAGE_SIZE;
		set_fixmap(idx, phys);
		mapped_size += PAGE_SIZE;
Andy Grover's avatar
Andy Grover committed
147 148 149 150
	}

	return ((unsigned char *) base + offset);
}
151
#endif
Andy Grover's avatar
Andy Grover committed
152

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
#ifdef CONFIG_PCI_MMCONFIG
static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
{
	struct acpi_table_mcfg *mcfg;

	if (!phys_addr || !size)
		return -EINVAL;

	mcfg = (struct acpi_table_mcfg *) __acpi_map_table(phys_addr, size);
	if (!mcfg) {
		printk(KERN_WARNING PREFIX "Unable to map MCFG\n");
		return -ENODEV;
	}

	if (mcfg->base_reserved) {
		printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
		return -ENODEV;
	}

	pci_mmcfg_base_addr = mcfg->base_address;

	return 0;
}
176 177 178
#else
#define	acpi_parse_mcfg NULL
#endif /* !CONFIG_PCI_MMCONFIG */
179

Andy Grover's avatar
Andy Grover committed
180
#ifdef CONFIG_X86_LOCAL_APIC
Andy Grover's avatar
Andy Grover committed
181 182 183 184
static int __init
acpi_parse_madt (
	unsigned long		phys_addr,
	unsigned long		size)
Andy Grover's avatar
Andy Grover committed
185
{
Andy Grover's avatar
Andy Grover committed
186
	struct acpi_table_madt	*madt = NULL;
Andy Grover's avatar
Andy Grover committed
187

Andy Grover's avatar
Andy Grover committed
188
	if (!phys_addr || !size)
Andy Grover's avatar
Andy Grover committed
189 190
		return -EINVAL;

Andy Grover's avatar
Andy Grover committed
191 192 193
	madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size);
	if (!madt) {
		printk(KERN_WARNING PREFIX "Unable to map MADT\n");
Andy Grover's avatar
Andy Grover committed
194 195 196
		return -ENODEV;
	}

197
	if (madt->lapic_address) {
Andy Grover's avatar
Andy Grover committed
198 199
		acpi_lapic_addr = (u64) madt->lapic_address;

200 201 202
		printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
			madt->lapic_address);
	}
Andy Grover's avatar
Andy Grover committed
203

204 205
	acpi_madt_oem_check(madt->header.oem_id, madt->header.oem_table_id);
	
Andy Grover's avatar
Andy Grover committed
206 207 208 209 210 211
	return 0;
}


static int __init
acpi_parse_lapic (
212
	acpi_table_entry_header *header, const unsigned long end)
Andy Grover's avatar
Andy Grover committed
213 214
{
	struct acpi_table_lapic	*processor = NULL;
Andy Grover's avatar
Andy Grover committed
215

Andy Grover's avatar
Andy Grover committed
216
	processor = (struct acpi_table_lapic*) header;
217 218

	if (BAD_MADT_ENTRY(processor, end))
Andy Grover's avatar
Andy Grover committed
219 220 221
		return -EINVAL;

	acpi_table_print_madt_entry(header);
Andy Grover's avatar
Andy Grover committed
222

223 224 225 226
	/* no utility in registering a disabled processor */
	if (processor->flags.enabled == 0)
		return 0;

Andy Grover's avatar
Andy Grover committed
227 228 229
	mp_register_lapic (
		processor->id,					   /* APIC ID */
		processor->flags.enabled);			  /* Enabled? */
Andy Grover's avatar
Andy Grover committed
230 231 232 233

	return 0;
}

Andy Grover's avatar
Andy Grover committed
234
static int __init
Andy Grover's avatar
Andy Grover committed
235
acpi_parse_lapic_addr_ovr (
236
	acpi_table_entry_header *header, const unsigned long end)
Andy Grover's avatar
Andy Grover committed
237 238 239 240
{
	struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL;

	lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header;
241 242

	if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
Andy Grover's avatar
Andy Grover committed
243 244
		return -EINVAL;

Andy Grover's avatar
Andy Grover committed
245
	acpi_lapic_addr = lapic_addr_ovr->address;
Andy Grover's avatar
Andy Grover committed
246 247 248 249

	return 0;
}

Andy Grover's avatar
Andy Grover committed
250
static int __init
Andy Grover's avatar
Andy Grover committed
251
acpi_parse_lapic_nmi (
252
	acpi_table_entry_header *header, const unsigned long end)
Andy Grover's avatar
Andy Grover committed
253
{
Andy Grover's avatar
Andy Grover committed
254
	struct acpi_table_lapic_nmi *lapic_nmi = NULL;
Andy Grover's avatar
Andy Grover committed
255

Andy Grover's avatar
Andy Grover committed
256
	lapic_nmi = (struct acpi_table_lapic_nmi*) header;
257 258

	if (BAD_MADT_ENTRY(lapic_nmi, end))
Andy Grover's avatar
Andy Grover committed
259 260 261 262
		return -EINVAL;

	acpi_table_print_madt_entry(header);

Andy Grover's avatar
Andy Grover committed
263 264
	if (lapic_nmi->lint != 1)
		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
Andy Grover's avatar
Andy Grover committed
265 266 267 268

	return 0;
}

269

Andy Grover's avatar
Andy Grover committed
270 271
#endif /*CONFIG_X86_LOCAL_APIC*/

Len Brown's avatar
Len Brown committed
272
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
273

Andy Grover's avatar
Andy Grover committed
274
static int __init
Andy Grover's avatar
Andy Grover committed
275
acpi_parse_ioapic (
276
	acpi_table_entry_header *header, const unsigned long end)
Andy Grover's avatar
Andy Grover committed
277 278
{
	struct acpi_table_ioapic *ioapic = NULL;
279

Andy Grover's avatar
Andy Grover committed
280
	ioapic = (struct acpi_table_ioapic*) header;
281 282

	if (BAD_MADT_ENTRY(ioapic, end))
Andy Grover's avatar
Andy Grover committed
283
		return -EINVAL;
284 285 286
 
	acpi_table_print_madt_entry(header);

Andy Grover's avatar
Andy Grover committed
287 288 289 290 291
	mp_register_ioapic (
		ioapic->id,
		ioapic->address,
		ioapic->global_irq_base);
 
292 293 294
	return 0;
}

295 296 297 298
/*
 * Parse Interrupt Source Override for the ACPI SCI
 */
static void
299
acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
300 301 302 303 304 305 306 307 308 309 310 311 312 313
{
	if (trigger == 0)	/* compatible SCI trigger is level */
		trigger = 3;

	if (polarity == 0)	/* compatible SCI polarity is low */
		polarity = 3;

	/* Command-line over-ride via acpi_sci= */
	if (acpi_sci_flags.trigger)
		trigger = acpi_sci_flags.trigger;

	if (acpi_sci_flags.polarity)
		polarity = acpi_sci_flags.polarity;

314 315 316 317 318 319
	/*
 	 * mp_config_acpi_legacy_irqs() already setup IRQs < 16
	 * If GSI is < 16, this will update its flags,
	 * else it will create a new mp_irqs[] entry.
	 */
	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
320 321 322 323 324

	/*
	 * stash over-ride to indicate we've been here
	 * and for later update of acpi_fadt
	 */
325
	acpi_sci_override_gsi = gsi;
326 327
	return;
}
328

Andy Grover's avatar
Andy Grover committed
329
static int __init
330
acpi_parse_int_src_ovr (
331
	acpi_table_entry_header *header, const unsigned long end)
332
{
Andy Grover's avatar
Andy Grover committed
333
	struct acpi_table_int_src_ovr *intsrc = NULL;
334

Andy Grover's avatar
Andy Grover committed
335
	intsrc = (struct acpi_table_int_src_ovr*) header;
336 337

	if (BAD_MADT_ENTRY(intsrc, end))
338
		return -EINVAL;
Andy Grover's avatar
Andy Grover committed
339 340 341

	acpi_table_print_madt_entry(header);

342
	if (intsrc->bus_irq == acpi_fadt.sci_int) {
343 344
		acpi_sci_ioapic_setup(intsrc->global_irq,
			intsrc->flags.polarity, intsrc->flags.trigger);
345 346 347
		return 0;
	}

348 349 350 351 352 353
	if (acpi_skip_timer_override &&
		intsrc->bus_irq == 0 && intsrc->global_irq == 2) {
			printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
			return 0;
	}

Andy Grover's avatar
Andy Grover committed
354 355 356 357 358
	mp_override_legacy_irq (
		intsrc->bus_irq,
		intsrc->flags.polarity,
		intsrc->flags.trigger,
		intsrc->global_irq);
359 360 361 362 363

	return 0;
}


Andy Grover's avatar
Andy Grover committed
364
static int __init
365
acpi_parse_nmi_src (
366
	acpi_table_entry_header *header, const unsigned long end)
367 368 369 370
{
	struct acpi_table_nmi_src *nmi_src = NULL;

	nmi_src = (struct acpi_table_nmi_src*) header;
371 372

	if (BAD_MADT_ENTRY(nmi_src, end))
373 374 375 376
		return -EINVAL;

	acpi_table_print_madt_entry(header);

Andy Grover's avatar
Andy Grover committed
377
	/* TBD: Support nimsrc entries? */
Andy Grover's avatar
Andy Grover committed
378 379 380 381

	return 0;
}

382
#endif /* CONFIG_X86_IO_APIC */
Andy Grover's avatar
Andy Grover committed
383

Len Brown's avatar
Len Brown committed
384
#ifdef	CONFIG_ACPI_BUS
385

Len Brown's avatar
Len Brown committed
386
/*
387 388 389
 * acpi_pic_sci_set_trigger()
 * 
 * use ELCR to set PIC-mode trigger type for SCI
390
 *
391
 * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
392
 * it may require Edge Trigger -- use "acpi_sci=edge"
Len Brown's avatar
Len Brown committed
393 394 395 396 397 398 399
 *
 * Port 0x4d0-4d1 are ECLR1 and ECLR2, the Edge/Level Control Registers
 * for the 8259 PIC.  bit[n] = 1 means irq[n] is Level, otherwise Edge.
 * ECLR1 is IRQ's 0-7 (IRQ 0, 1, 2 must be 0)
 * ECLR2 is IRQ's 8-15 (IRQ 8, 13 must be 0)
 */

400
void __init
401
acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
Len Brown's avatar
Len Brown committed
402 403 404 405 406
{
	unsigned char mask = 1 << (irq & 7);
	unsigned int port = 0x4d0 + (irq >> 3);
	unsigned char val = inb(port);

407 408
	
	printk(PREFIX "IRQ%d SCI:", irq);
Len Brown's avatar
Len Brown committed
409
	if (!(val & mask)) {
410 411
		printk(" Edge");

412
		if (trigger == 3) {
413 414 415 416 417 418
			printk(" set to Level");
			outb(val | mask, port);
		}
	} else {
		printk(" Level");

419
		if (trigger == 1) {
420
			printk(" set to Edge");
421
			outb(val & ~mask, port);
422 423 424 425 426 427
		}
	}
	printk(" Trigger.\n");
}


Len Brown's avatar
Len Brown committed
428 429
#endif /* CONFIG_ACPI_BUS */

430 431 432 433 434 435 436 437 438 439 440
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
#ifdef CONFIG_X86_IO_APIC
	if (use_pci_vector() && !platform_legacy_irq(gsi))
 		*irq = IO_APIC_VECTOR(gsi);
	else
#endif
		*irq = gsi;
	return 0;
}

441 442 443 444
unsigned int acpi_register_gsi(u32 gsi, int edge_level, int active_high_low)
{
	unsigned int irq;

445
#ifdef CONFIG_PCI
446 447 448 449
	/*
	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
	 */
	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
450 451 452
		static u16 irq_mask;
		extern void eisa_set_level_irq(unsigned int irq);

453 454 455 456 457 458
		if (edge_level == ACPI_LEVEL_SENSITIVE) {
			if ((gsi < 16) && !((1 << gsi) & irq_mask)) {
				Dprintk(KERN_DEBUG PREFIX "Setting GSI %u as level-triggered\n", gsi);
				irq_mask |= (1 << gsi);
				eisa_set_level_irq(gsi);
			}
459 460
		}
	}
461
#endif
462 463 464 465 466 467 468 469 470

#ifdef CONFIG_X86_IO_APIC
	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
		mp_register_gsi(gsi, edge_level, active_high_low);
	}
#endif
	acpi_gsi_to_irq(gsi, &irq);
	return irq;
}
471
EXPORT_SYMBOL(acpi_register_gsi);
472

Andy Grover's avatar
Andy Grover committed
473 474 475 476 477 478 479 480 481 482 483 484 485
static unsigned long __init
acpi_scan_rsdp (
	unsigned long		start,
	unsigned long		length)
{
	unsigned long		offset = 0;
	unsigned long		sig_len = sizeof("RSD PTR ") - 1;

	/*
	 * Scan all 16-byte boundaries of the physical memory region for the
	 * RSDP signature.
	 */
	for (offset = 0; offset < length; offset += 16) {
Andy Grover's avatar
Andy Grover committed
486
		if (strncmp((char *) (start + offset), "RSD PTR ", sig_len))
Andy Grover's avatar
Andy Grover committed
487 488 489 490 491 492 493
			continue;
		return (start + offset);
	}

	return 0;
}

494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
static int __init acpi_parse_sbf(unsigned long phys_addr, unsigned long size)
{
	struct acpi_table_sbf *sb;

	if (!phys_addr || !size)
	return -EINVAL;

	sb = (struct acpi_table_sbf *) __acpi_map_table(phys_addr, size);
	if (!sb) {
		printk(KERN_WARNING PREFIX "Unable to map SBF\n");
		return -ENODEV;
	}

	sbf_port = sb->sbf_cmos; /* Save CMOS port */

	return 0;
}


513 514 515 516 517 518
#ifdef CONFIG_HPET_TIMER

static int __init acpi_parse_hpet(unsigned long phys, unsigned long size)
{
	struct acpi_table_hpet *hpet_tbl;

519 520 521 522 523 524 525 526
	if (!phys || !size)
		return -EINVAL;

	hpet_tbl = (struct acpi_table_hpet *) __acpi_map_table(phys, size);
	if (!hpet_tbl) {
		printk(KERN_WARNING PREFIX "Unable to map HPET\n");
		return -ENODEV;
	}
527 528 529 530 531 532 533

	if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) {
		printk(KERN_WARNING PREFIX "HPET timers must be located in "
		       "memory.\n");
		return -1;
	}

534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
#ifdef	CONFIG_X86_64
        vxtime.hpet_address = hpet_tbl->addr.addrl |
                ((long) hpet_tbl->addr.addrh << 32);

        printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
               hpet_tbl->id, vxtime.hpet_address);
#else	/* X86 */
	{
		extern unsigned long hpet_address;

		hpet_address = hpet_tbl->addr.addrl;
		printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
			hpet_tbl->id, hpet_address);
	}
#endif	/* X86 */

550 551
	return 0;
}
552
#else
Len Brown's avatar
Len Brown committed
553
#define	acpi_parse_hpet	NULL
554
#endif
Andy Grover's avatar
Andy Grover committed
555

556
#ifdef CONFIG_X86_PM_TIMER
Andrew Morton's avatar
Andrew Morton committed
557
extern u32 pmtmr_ioport;
558
#endif
Andrew Morton's avatar
Andrew Morton committed
559 560 561 562 563 564 565 566 567 568 569

static int __init acpi_parse_fadt(unsigned long phys, unsigned long size)
{
	struct fadt_descriptor_rev2 *fadt =0;

	fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size);
	if(!fadt) {
		printk(KERN_WARNING PREFIX "Unable to map FADT\n");
		return 0;
	}

570 571 572 573 574 575 576
#ifdef	CONFIG_ACPI_INTERPRETER
	/* initialize sci_int early for INT_SRC_OVR MADT parsing */
	acpi_fadt.sci_int = fadt->sci_int;
#endif

#ifdef CONFIG_X86_PM_TIMER
	/* detect the location of the ACPI PM Timer */
Andrew Morton's avatar
Andrew Morton committed
577 578 579 580 581 582 583 584 585 586 587 588
	if (fadt->revision >= FADT2_REVISION_ID) {
		/* FADT rev. 2 */
		if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO)
			return 0;

		pmtmr_ioport = fadt->xpm_tmr_blk.address;
	} else {
		/* FADT rev. 1 */
		pmtmr_ioport = fadt->V1_pm_tmr_blk;
	}
	if (pmtmr_ioport)
		printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport);
589
#endif
Andrew Morton's avatar
Andrew Morton committed
590 591 592 593
	return 0;
}


Andy Grover's avatar
Andy Grover committed
594 595
unsigned long __init
acpi_find_rsdp (void)
Andy Grover's avatar
Andy Grover committed
596
{
Andy Grover's avatar
Andy Grover committed
597
	unsigned long		rsdp_phys = 0;
Andy Grover's avatar
Andy Grover committed
598

Andrew Morton's avatar
Andrew Morton committed
599 600 601 602 603 604
	if (efi_enabled) {
		if (efi.acpi20)
			return __pa(efi.acpi20);
		else if (efi.acpi)
			return __pa(efi.acpi);
	}
Andy Grover's avatar
Andy Grover committed
605 606 607 608
	/*
	 * Scan memory looking for the RSDP signature. First search EBDA (low
	 * memory) paragraphs and then search upper memory (E0000-FFFFF).
	 */
Andy Grover's avatar
Andy Grover committed
609 610 611
	rsdp_phys = acpi_scan_rsdp (0, 0x400);
	if (!rsdp_phys)
		rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF);
Andy Grover's avatar
Andy Grover committed
612

Andy Grover's avatar
Andy Grover committed
613
	return rsdp_phys;
Andy Grover's avatar
Andy Grover committed
614 615
}

616
#ifdef	CONFIG_X86_LOCAL_APIC
Len Brown's avatar
Len Brown committed
617
/*
618 619
 * Parse LAPIC entries in MADT
 * returns 0 on success, < 0 on error
Len Brown's avatar
Len Brown committed
620
 */
621 622
static int __init
acpi_parse_madt_lapic_entries(void)
623
{
624
	int count;
625

Andy Grover's avatar
Andy Grover committed
626 627 628 629
	/* 
	 * Note that the LAPIC address is obtained from the MADT (32-bit value)
	 * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
	 */
630

631 632
	count = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0);
	if (count < 0) {
633
		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
634
		return count;
635 636
	}

Andy Grover's avatar
Andy Grover committed
637 638
	mp_register_lapic_address(acpi_lapic_addr);

639
	count = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic,
640
				       MAX_APICS);
641
	if (!count) { 
Andy Grover's avatar
Andy Grover committed
642 643
		printk(KERN_ERR PREFIX "No LAPIC entries present\n");
		/* TBD: Cleanup to allow fallback to MPS */
644 645
		return -ENODEV;
	}
646
	else if (count < 0) {
Andy Grover's avatar
Andy Grover committed
647 648
		printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
		/* TBD: Cleanup to allow fallback to MPS */
649
		return count;
Andy Grover's avatar
Andy Grover committed
650
	}
651

652 653
	count = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0);
	if (count < 0) {
654
		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
Andy Grover's avatar
Andy Grover committed
655
		/* TBD: Cleanup to allow fallback to MPS */
656
		return count;
657
	}
658 659 660
	return 0;
}
#endif /* CONFIG_X86_LOCAL_APIC */
Andy Grover's avatar
Andy Grover committed
661

Len Brown's avatar
Len Brown committed
662
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_ACPI_INTERPRETER)
663 664 665 666 667 668 669 670
/*
 * Parse IOAPIC related entries in MADT
 * returns 0 on success, < 0 on error
 */
static int __init
acpi_parse_madt_ioapic_entries(void)
{
	int count;
671

Len Brown's avatar
Len Brown committed
672 673 674 675 676 677
	/*
	 * ACPI interpreter is required to complete interrupt setup,
	 * so if it is off, don't enumerate the io-apics with ACPI.
	 * If MPS is present, it will handle them,
	 * otherwise the system will stay in PIC mode
	 */
678
	if (acpi_disabled || acpi_noirq) {
679
		return -ENODEV;
Len Brown's avatar
Len Brown committed
680 681
        }

682 683 684
	/*
 	 * if "noapic" boot option, don't look for IO-APICs
	 */
685
	if (skip_ioapic_setup) {
686 687
		printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
			"due to 'noapic' option.\n");
688
		return -ENODEV;
689 690
	}

691 692
	count = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic, MAX_IO_APICS);
	if (!count) {
Andy Grover's avatar
Andy Grover committed
693
		printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
694 695
		return -ENODEV;
	}
696
	else if (count < 0) {
Andy Grover's avatar
Andy Grover committed
697
		printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
698
		return count;
Andy Grover's avatar
Andy Grover committed
699
	}
700

701 702
	count = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, NR_IRQ_VECTORS);
	if (count < 0) {
703
		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
Andy Grover's avatar
Andy Grover committed
704
		/* TBD: Cleanup to allow fallback to MPS */
705
		return count;
706 707
	}

708 709 710 711 712
	/*
	 * If BIOS did not supply an INT_SRC_OVR for the SCI
	 * pretend we got one so we can set the SCI flags.
	 */
	if (!acpi_sci_override_gsi)
713
		acpi_sci_ioapic_setup(acpi_fadt.sci_int, 0, 0);
714

715 716 717
	/* Fill in identity legacy mapings where no override */
	mp_config_acpi_legacy_irqs();

718 719
	count = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, NR_IRQ_VECTORS);
	if (count < 0) {
720
		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
Andy Grover's avatar
Andy Grover committed
721
		/* TBD: Cleanup to allow fallback to MPS */
722
		return count;
723 724
	}

725 726 727 728 729 730 731 732
	return 0;
}
#else
static inline int acpi_parse_madt_ioapic_entries(void)
{
	return -1;
}
#endif /* !(CONFIG_X86_IO_APIC && CONFIG_ACPI_INTERPRETER) */
Andy Grover's avatar
Andy Grover committed
733

Len Brown's avatar
Len Brown committed
734

735 736 737
static void __init
acpi_process_madt(void)
{
Andy Grover's avatar
Andy Grover committed
738
#ifdef CONFIG_X86_LOCAL_APIC
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763
	int count, error;

	count = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
	if (count == 1) {

		/*
		 * Parse MADT LAPIC entries
		 */
		error = acpi_parse_madt_lapic_entries();
		if (!error) {
			acpi_lapic = 1;

			/*
			 * Parse MADT IO-APIC entries
			 */
			error = acpi_parse_madt_ioapic_entries();
			if (!error) {
				acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
				acpi_irq_balance_set(NULL);
				acpi_ioapic = 1;

				smp_found_config = 1;
				clustered_apic_check();
			}
		}
764 765 766 767 768 769 770
		if (error == -EINVAL) {
			/*
			 * Dell Precision Workstation 410, 610 come here.
			 */
			printk(KERN_ERR PREFIX "Invalid BIOS MADT, disabling ACPI\n");
			disable_acpi();
		}
771
	}
Andy Grover's avatar
Andy Grover committed
772
#endif
773 774
	return;
}
775

776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
/*
 * acpi_boot_init()
 *  called from setup_arch(), always.
 *	1. checksums all tables
 *	2. enumerates lapics
 *	3. enumerates io-apics
 *
 * side effects:
 *	acpi_lapic = 1 if LAPIC found
 *	acpi_ioapic = 1 if IOAPIC found
 *	if (acpi_lapic && acpi_ioapic) smp_found_config = 1;
 *	if acpi_blacklisted() acpi_disabled = 1;
 *	acpi_irq_model=...
 *	...
 *
 * return value: (currently ignored)
 *	0: success
 *	!0: failure
 */
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
int __init
acpi_boot_init (void)
{
	int error;

	/*
	 * If acpi_disabled, bail out
	 * One exception: acpi=ht continues far enough to enumerate LAPICs
	 */
	if (acpi_disabled && !acpi_ht)
		 return 1;

	/* 
	 * Initialize the ACPI boot-time table parser.
	 */
	error = acpi_table_init();
	if (error) {
Len Brown's avatar
Len Brown committed
813
		disable_acpi();
814 815 816
		return error;
	}

817
	acpi_table_parse(ACPI_BOOT, acpi_parse_sbf);
818

819 820 821 822 823 824
	/*
	 * blacklist may disable ACPI entirely
	 */
	error = acpi_blacklisted();
	if (error) {
		printk(KERN_WARNING PREFIX "BIOS listed in blacklist, disabling ACPI support\n");
Len Brown's avatar
Len Brown committed
825
		disable_acpi();
826
		return error;
827
	}
828

829 830 831 832 833
	/*
	 * set sci_int and PM timer address
	 */
	acpi_table_parse(ACPI_FADT, acpi_parse_fadt);

834 835 836 837
	/*
	 * Process the Multiple APIC Description Table (MADT), if present
	 */
	acpi_process_madt();
838

839 840
	acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
	acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
841

842 843
	return 0;
}
844