boot.c 45.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 *  boot.c - Architecture-Specific Low-Level ACPI Boot Support
 *
 *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *  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>
#include <linux/acpi.h>
28
#include <linux/acpi_pmtmr.h>
Linus Torvalds's avatar
Linus Torvalds committed
29
#include <linux/efi.h>
30
#include <linux/cpumask.h>
Linus Torvalds's avatar
Linus Torvalds committed
31
#include <linux/module.h>
32
#include <linux/dmi.h>
33
#include <linux/irq.h>
34 35
#include <linux/bootmem.h>
#include <linux/ioport.h>
36
#include <linux/pci.h>
Linus Torvalds's avatar
Linus Torvalds committed
37 38 39 40 41 42

#include <asm/pgtable.h>
#include <asm/io_apic.h>
#include <asm/apic.h>
#include <asm/io.h>
#include <asm/mpspec.h>
43
#include <asm/smp.h>
Linus Torvalds's avatar
Linus Torvalds committed
44

45
static int __initdata acpi_force = 0;
46
u32 acpi_rsdt_forced;
47 48 49 50 51 52 53
#ifdef	CONFIG_ACPI
int acpi_disabled = 0;
#else
int acpi_disabled = 1;
#endif
EXPORT_SYMBOL(acpi_disabled);

Linus Torvalds's avatar
Linus Torvalds committed
54
#ifdef	CONFIG_X86_64
Ingo Molnar's avatar
Ingo Molnar committed
55
# include <asm/proto.h>
Len Brown's avatar
Len Brown committed
56
#endif				/* X86 */
Linus Torvalds's avatar
Linus Torvalds committed
57 58 59

#define BAD_MADT_ENTRY(entry, end) (					    \
		(!entry) || (unsigned long)entry + sizeof(*entry) > end ||  \
60
		((struct acpi_subtable_header *)entry)->length < sizeof(*entry))
Linus Torvalds's avatar
Linus Torvalds committed
61 62 63

#define PREFIX			"ACPI: "

Andrew Morton's avatar
Andrew Morton committed
64
int acpi_noirq;				/* skip ACPI IRQ initialization */
65 66
int acpi_pci_disabled;		/* skip ACPI PCI scan and IRQ initialization */
EXPORT_SYMBOL(acpi_pci_disabled);
Linus Torvalds's avatar
Linus Torvalds committed
67 68 69 70 71 72
int acpi_ht __initdata = 1;	/* enable HT */

int acpi_lapic;
int acpi_ioapic;
int acpi_strict;

73
u8 acpi_sci_flags __initdata;
Linus Torvalds's avatar
Linus Torvalds committed
74 75
int acpi_sci_override_gsi __initdata;
int acpi_skip_timer_override __initdata;
76
int acpi_use_timer_override __initdata;
Linus Torvalds's avatar
Linus Torvalds committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91

#ifdef CONFIG_X86_LOCAL_APIC
static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE;
#endif

#ifndef __HAVE_ARCH_CMPXCHG
#warning ACPI uses CMPXCHG, i486 and later hardware
#endif

/* --------------------------------------------------------------------------
                              Boot-time Configuration
   -------------------------------------------------------------------------- */

/*
 * The default interrupt routing model is PIC (8259).  This gets
Simon Arlott's avatar
Simon Arlott committed
92
 * overridden if IOAPICs are enumerated (below).
Linus Torvalds's avatar
Linus Torvalds committed
93
 */
Len Brown's avatar
Len Brown committed
94
enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC;
Linus Torvalds's avatar
Linus Torvalds committed
95 96 97 98 99 100 101 102 103 104 105 106 107 108


/*
 * 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.
 */
109
char *__init __acpi_map_table(unsigned long phys, unsigned long size)
Linus Torvalds's avatar
Linus Torvalds committed
110 111
{

Yinghai Lu's avatar
Yinghai Lu committed
112 113 114
	if (!phys || !size)
		return NULL;

115 116 117 118 119 120
	return early_ioremap(phys, size);
}
void __init __acpi_unmap_table(char *map, unsigned long size)
{
	if (!map || !size)
		return;
Linus Torvalds's avatar
Linus Torvalds committed
121

122
	early_iounmap(map, size);
Linus Torvalds's avatar
Linus Torvalds committed
123 124 125
}

#ifdef CONFIG_PCI_MMCONFIG
126 127 128

static int acpi_mcfg_64bit_base_addr __initdata = FALSE;

129
/* The physical address of the MMCONFIG aperture.  Set from ACPI tables. */
130
struct acpi_mcfg_allocation *pci_mmcfg_config;
131 132
int pci_mmcfg_config_num;

133 134 135 136 137 138 139 140
static int __init acpi_mcfg_oem_check(struct acpi_table_mcfg *mcfg)
{
	if (!strcmp(mcfg->header.oem_id, "SGI"))
		acpi_mcfg_64bit_base_addr = TRUE;

	return 0;
}

141
int __init acpi_parse_mcfg(struct acpi_table_header *header)
Linus Torvalds's avatar
Linus Torvalds committed
142 143
{
	struct acpi_table_mcfg *mcfg;
144 145
	unsigned long i;
	int config_size;
Linus Torvalds's avatar
Linus Torvalds committed
146

147
	if (!header)
Linus Torvalds's avatar
Linus Torvalds committed
148 149
		return -EINVAL;

150
	mcfg = (struct acpi_table_mcfg *)header;
Linus Torvalds's avatar
Linus Torvalds committed
151

152 153
	/* how many config structures do we have */
	pci_mmcfg_config_num = 0;
154
	i = header->length - sizeof(struct acpi_table_mcfg);
155
	while (i >= sizeof(struct acpi_mcfg_allocation)) {
156
		++pci_mmcfg_config_num;
157
		i -= sizeof(struct acpi_mcfg_allocation);
158 159 160
	};
	if (pci_mmcfg_config_num == 0) {
		printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
Linus Torvalds's avatar
Linus Torvalds committed
161 162 163
		return -ENODEV;
	}

164 165 166 167 168 169 170 171
	config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
	pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
	if (!pci_mmcfg_config) {
		printk(KERN_WARNING PREFIX
		       "No memory for MCFG config tables\n");
		return -ENOMEM;
	}

172
	memcpy(pci_mmcfg_config, &mcfg[1], config_size);
173 174 175

	acpi_mcfg_oem_check(mcfg);

176
	for (i = 0; i < pci_mmcfg_config_num; ++i) {
177 178
		if ((pci_mmcfg_config[i].address > 0xFFFFFFFF) &&
		    !acpi_mcfg_64bit_base_addr) {
179 180
			printk(KERN_ERR PREFIX
			       "MMCONFIG not in low 4GB of memory\n");
181 182
			kfree(pci_mmcfg_config);
			pci_mmcfg_config_num = 0;
183 184 185
			return -ENODEV;
		}
	}
Linus Torvalds's avatar
Linus Torvalds committed
186 187 188

	return 0;
}
Len Brown's avatar
Len Brown committed
189
#endif				/* CONFIG_PCI_MMCONFIG */
Linus Torvalds's avatar
Linus Torvalds committed
190 191

#ifdef CONFIG_X86_LOCAL_APIC
192
static int __init acpi_parse_madt(struct acpi_table_header *table)
Linus Torvalds's avatar
Linus Torvalds committed
193
{
Len Brown's avatar
Len Brown committed
194
	struct acpi_table_madt *madt = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
195

196
	if (!cpu_has_apic)
Linus Torvalds's avatar
Linus Torvalds committed
197 198
		return -EINVAL;

199
	madt = (struct acpi_table_madt *)table;
Linus Torvalds's avatar
Linus Torvalds committed
200 201 202 203 204
	if (!madt) {
		printk(KERN_WARNING PREFIX "Unable to map MADT\n");
		return -ENODEV;
	}

205 206
	if (madt->address) {
		acpi_lapic_addr = (u64) madt->address;
Linus Torvalds's avatar
Linus Torvalds committed
207 208

		printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
209
		       madt->address);
Linus Torvalds's avatar
Linus Torvalds committed
210 211
	}

212 213
	default_acpi_madt_oem_check(madt->header.oem_id,
				    madt->header.oem_table_id);
Len Brown's avatar
Len Brown committed
214

Linus Torvalds's avatar
Linus Torvalds committed
215 216 217
	return 0;
}

218 219
static void __cpuinit acpi_register_lapic(int id, u8 enabled)
{
Yinghai Lu's avatar
Yinghai Lu committed
220 221
	unsigned int ver = 0;

222 223 224 225 226
	if (!enabled) {
		++disabled_cpus;
		return;
	}

Yinghai Lu's avatar
Yinghai Lu committed
227 228 229 230
	if (boot_cpu_physical_apicid != -1U)
		ver = apic_version[boot_cpu_physical_apicid];

	generic_processor_info(id, ver);
231 232
}

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
static int __init
acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
{
	struct acpi_madt_local_x2apic *processor = NULL;

	processor = (struct acpi_madt_local_x2apic *)header;

	if (BAD_MADT_ENTRY(processor, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

#ifdef CONFIG_X86_X2APIC
	/*
	 * We need to register disabled CPU as well to permit
	 * counting disabled CPUs. This allows us to size
	 * cpus_possible_map more accurately, to permit
	 * to not preallocating memory for all NR_CPUS
	 * when we use CPU hotplug.
	 */
	acpi_register_lapic(processor->local_apic_id,	/* APIC ID */
			    processor->lapic_flags & ACPI_MADT_ENABLED);
#else
	printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
#endif

	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
262
static int __init
263
acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
264
{
265
	struct acpi_madt_local_apic *processor = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
266

267
	processor = (struct acpi_madt_local_apic *)header;
Linus Torvalds's avatar
Linus Torvalds committed
268 269 270 271 272 273

	if (BAD_MADT_ENTRY(processor, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

274 275 276 277 278 279 280
	/*
	 * We need to register disabled CPU as well to permit
	 * counting disabled CPUs. This allows us to size
	 * cpus_possible_map more accurately, to permit
	 * to not preallocating memory for all NR_CPUS
	 * when we use CPU hotplug.
	 */
281 282
	acpi_register_lapic(processor->id,	/* APIC ID */
			    processor->lapic_flags & ACPI_MADT_ENABLED);
Linus Torvalds's avatar
Linus Torvalds committed
283 284 285 286

	return 0;
}

287 288 289 290 291 292 293 294 295 296 297 298
static int __init
acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end)
{
	struct acpi_madt_local_sapic *processor = NULL;

	processor = (struct acpi_madt_local_sapic *)header;

	if (BAD_MADT_ENTRY(processor, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

299 300
	acpi_register_lapic((processor->id << 8) | processor->eid,/* APIC ID */
			    processor->lapic_flags & ACPI_MADT_ENABLED);
301 302 303 304

	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
305
static int __init
306
acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
Len Brown's avatar
Len Brown committed
307
			  const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
308
{
309
	struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
310

311
	lapic_addr_ovr = (struct acpi_madt_local_apic_override *)header;
Linus Torvalds's avatar
Linus Torvalds committed
312 313 314 315 316 317 318 319 320

	if (BAD_MADT_ENTRY(lapic_addr_ovr, end))
		return -EINVAL;

	acpi_lapic_addr = lapic_addr_ovr->address;

	return 0;
}

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
static int __init
acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
		      const unsigned long end)
{
	struct acpi_madt_local_x2apic_nmi *x2apic_nmi = NULL;

	x2apic_nmi = (struct acpi_madt_local_x2apic_nmi *)header;

	if (BAD_MADT_ENTRY(x2apic_nmi, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

	if (x2apic_nmi->lint != 1)
		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");

	return 0;
}

Linus Torvalds's avatar
Linus Torvalds committed
340
static int __init
341
acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
342
{
343
	struct acpi_madt_local_apic_nmi *lapic_nmi = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
344

345
	lapic_nmi = (struct acpi_madt_local_apic_nmi *)header;
Linus Torvalds's avatar
Linus Torvalds committed
346 347 348 349 350 351 352 353 354 355 356 357

	if (BAD_MADT_ENTRY(lapic_nmi, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

	if (lapic_nmi->lint != 1)
		printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");

	return 0;
}

Len Brown's avatar
Len Brown committed
358
#endif				/*CONFIG_X86_LOCAL_APIC */
Linus Torvalds's avatar
Linus Torvalds committed
359

360
#ifdef CONFIG_X86_IO_APIC
Linus Torvalds's avatar
Linus Torvalds committed
361 362

static int __init
363
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
364
{
365
	struct acpi_madt_io_apic *ioapic = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
366

367
	ioapic = (struct acpi_madt_io_apic *)header;
Linus Torvalds's avatar
Linus Torvalds committed
368 369 370

	if (BAD_MADT_ENTRY(ioapic, end))
		return -EINVAL;
Len Brown's avatar
Len Brown committed
371

Linus Torvalds's avatar
Linus Torvalds committed
372 373
	acpi_table_print_madt_entry(header);

Len Brown's avatar
Len Brown committed
374 375 376
	mp_register_ioapic(ioapic->id,
			   ioapic->address, ioapic->global_irq_base);

Linus Torvalds's avatar
Linus Torvalds committed
377 378 379 380 381 382
	return 0;
}

/*
 * Parse Interrupt Source Override for the ACPI SCI
 */
383
static void __init acpi_sci_ioapic_setup(u32 gsi, u16 polarity, u16 trigger)
Linus Torvalds's avatar
Linus Torvalds committed
384 385 386 387 388 389 390 391
{
	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= */
392 393
	if (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK)
		trigger = (acpi_sci_flags & ACPI_MADT_TRIGGER_MASK) >> 2;
Linus Torvalds's avatar
Linus Torvalds committed
394

395 396
	if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
		polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
Linus Torvalds's avatar
Linus Torvalds committed
397 398

	/*
Len Brown's avatar
Len Brown committed
399
	 * mp_config_acpi_legacy_irqs() already setup IRQs < 16
Linus Torvalds's avatar
Linus Torvalds committed
400 401 402
	 * If GSI is < 16, this will update its flags,
	 * else it will create a new mp_irqs[] entry.
	 */
403
	mp_override_legacy_irq(gsi, polarity, trigger, gsi);
Linus Torvalds's avatar
Linus Torvalds committed
404 405 406

	/*
	 * stash over-ride to indicate we've been here
407
	 * and for later update of acpi_gbl_FADT
Linus Torvalds's avatar
Linus Torvalds committed
408
	 */
409
	acpi_sci_override_gsi = gsi;
Linus Torvalds's avatar
Linus Torvalds committed
410 411 412 413
	return;
}

static int __init
414
acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
Len Brown's avatar
Len Brown committed
415
		       const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
416
{
417
	struct acpi_madt_interrupt_override *intsrc = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
418

419
	intsrc = (struct acpi_madt_interrupt_override *)header;
Linus Torvalds's avatar
Linus Torvalds committed
420 421 422 423 424 425

	if (BAD_MADT_ENTRY(intsrc, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

426
	if (intsrc->source_irq == acpi_gbl_FADT.sci_interrupt) {
427
		acpi_sci_ioapic_setup(intsrc->global_irq,
428 429
				      intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
				      (intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2);
Linus Torvalds's avatar
Linus Torvalds committed
430 431 432 433
		return 0;
	}

	if (acpi_skip_timer_override &&
434
	    intsrc->source_irq == 0 && intsrc->global_irq == 2) {
Len Brown's avatar
Len Brown committed
435 436
		printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n");
		return 0;
Linus Torvalds's avatar
Linus Torvalds committed
437 438
	}

439 440 441 442
	mp_override_legacy_irq(intsrc->source_irq,
				intsrc->inti_flags & ACPI_MADT_POLARITY_MASK,
				(intsrc->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2,
				intsrc->global_irq);
Linus Torvalds's avatar
Linus Torvalds committed
443 444 445 446 447

	return 0;
}

static int __init
448
acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end)
Linus Torvalds's avatar
Linus Torvalds committed
449
{
450
	struct acpi_madt_nmi_source *nmi_src = NULL;
Linus Torvalds's avatar
Linus Torvalds committed
451

452
	nmi_src = (struct acpi_madt_nmi_source *)header;
Linus Torvalds's avatar
Linus Torvalds committed
453 454 455 456 457 458 459 460 461 462 463

	if (BAD_MADT_ENTRY(nmi_src, end))
		return -EINVAL;

	acpi_table_print_madt_entry(header);

	/* TBD: Support nimsrc entries? */

	return 0;
}

Len Brown's avatar
Len Brown committed
464
#endif				/* CONFIG_X86_IO_APIC */
Linus Torvalds's avatar
Linus Torvalds committed
465 466 467

/*
 * acpi_pic_sci_set_trigger()
468
 *
Linus Torvalds's avatar
Linus Torvalds committed
469 470 471 472 473 474 475
 * use ELCR to set PIC-mode trigger type for SCI
 *
 * If a PIC-mode SCI is not recognized or gives spurious IRQ7's
 * it may require Edge Trigger -- use "acpi_sci=edge"
 *
 * 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.
Simon Arlott's avatar
Simon Arlott committed
476 477
 * ECLR1 is IRQs 0-7 (IRQ 0, 1, 2 must be 0)
 * ECLR2 is IRQs 8-15 (IRQ 8, 13 must be 0)
Linus Torvalds's avatar
Linus Torvalds committed
478 479
 */

Len Brown's avatar
Len Brown committed
480
void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
Linus Torvalds's avatar
Linus Torvalds committed
481 482 483 484 485 486 487 488
{
	unsigned int mask = 1 << irq;
	unsigned int old, new;

	/* Real old ELCR mask */
	old = inb(0x4d0) | (inb(0x4d1) << 8);

	/*
Simon Arlott's avatar
Simon Arlott committed
489
	 * If we use ACPI to set PCI IRQs, then we should clear ELCR
Linus Torvalds's avatar
Linus Torvalds committed
490 491 492 493 494 495 496 497 498 499
	 * since we will set it correctly as we enable the PCI irq
	 * routing.
	 */
	new = acpi_noirq ? old : 0;

	/*
	 * Update SCI information in the ELCR, it isn't in the PCI
	 * routing tables..
	 */
	switch (trigger) {
Len Brown's avatar
Len Brown committed
500
	case 1:		/* Edge - clear */
Linus Torvalds's avatar
Linus Torvalds committed
501 502
		new &= ~mask;
		break;
Len Brown's avatar
Len Brown committed
503
	case 3:		/* Level - set */
Linus Torvalds's avatar
Linus Torvalds committed
504 505 506 507 508 509 510 511 512 513 514 515 516 517
		new |= mask;
		break;
	}

	if (old == new)
		return;

	printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old);
	outb(new, 0x4d0);
	outb(new >> 8, 0x4d1);
}

int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
{
518
	*irq = gsi;
Linus Torvalds's avatar
Linus Torvalds committed
519 520 521
	return 0;
}

522 523 524 525
/*
 * success: return IRQ number (>=0)
 * failure: return < 0
 */
526
int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
Linus Torvalds's avatar
Linus Torvalds committed
527 528 529 530 531 532 533 534 535
{
	unsigned int irq;
	unsigned int plat_gsi = gsi;

#ifdef CONFIG_PCI
	/*
	 * Make sure all (legacy) PCI IRQs are set as level-triggered.
	 */
	if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
536
		if (triggering == ACPI_LEVEL_SENSITIVE)
Len Brown's avatar
Len Brown committed
537
			eisa_set_level_irq(gsi);
Linus Torvalds's avatar
Linus Torvalds committed
538 539 540 541 542
	}
#endif

#ifdef CONFIG_X86_IO_APIC
	if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
543
		plat_gsi = mp_register_gsi(dev, gsi, triggering, polarity);
Linus Torvalds's avatar
Linus Torvalds committed
544 545 546 547 548
	}
#endif
	acpi_gsi_to_irq(plat_gsi, &irq);
	return irq;
}
Len Brown's avatar
Len Brown committed
549

Linus Torvalds's avatar
Linus Torvalds committed
550 551 552 553
/*
 *  ACPI based hotplug support for CPU
 */
#ifdef CONFIG_ACPI_HOTPLUG_CPU
554 555

static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
Linus Torvalds's avatar
Linus Torvalds committed
556
{
557 558
	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
	union acpi_object *obj;
559
	struct acpi_madt_local_apic *lapic;
560
	cpumask_var_t tmp_map, new_map;
561 562
	u8 physid;
	int cpu;
563
	int retval = -ENOMEM;
564 565 566 567 568 569 570 571 572 573 574 575 576 577

	if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
		return -EINVAL;

	if (!buffer.length || !buffer.pointer)
		return -EINVAL;

	obj = buffer.pointer;
	if (obj->type != ACPI_TYPE_BUFFER ||
	    obj->buffer.length < sizeof(*lapic)) {
		kfree(buffer.pointer);
		return -EINVAL;
	}

578
	lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
579

580 581
	if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
	    !(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
582 583 584 585 586 587 588 589 590 591
		kfree(buffer.pointer);
		return -EINVAL;
	}

	physid = lapic->id;

	kfree(buffer.pointer);
	buffer.length = ACPI_ALLOCATE_BUFFER;
	buffer.pointer = NULL;

592 593 594 595 596 597 598
	if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
		goto out;

	if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
		goto free_tmp_map;

	cpumask_copy(tmp_map, cpu_present_mask);
599
	acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED);
600 601 602 603 604

	/*
	 * If mp_register_lapic successfully generates a new logical cpu
	 * number, then the following will get us exactly what was mapped
	 */
605 606
	cpumask_andnot(new_map, cpu_present_mask, tmp_map);
	if (cpumask_empty(new_map)) {
607
		printk ("Unable to map lapic to logical cpu number\n");
608 609
		retval = -EINVAL;
		goto free_new_map;
610 611
	}

612
	cpu = cpumask_first(new_map);
613 614

	*pcpu = cpu;
615 616 617 618 619 620 621 622
	retval = 0;

free_new_map:
	free_cpumask_var(new_map);
free_tmp_map:
	free_cpumask_var(tmp_map);
out:
	return retval;
Linus Torvalds's avatar
Linus Torvalds committed
623 624
}

625 626 627 628 629
/* wrapper to silence section mismatch warning */
int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
{
	return _acpi_map_lsapic(handle, pcpu);
}
Len Brown's avatar
Len Brown committed
630
EXPORT_SYMBOL(acpi_map_lsapic);
Linus Torvalds's avatar
Linus Torvalds committed
631

Len Brown's avatar
Len Brown committed
632
int acpi_unmap_lsapic(int cpu)
Linus Torvalds's avatar
Linus Torvalds committed
633
{
634
	per_cpu(x86_cpu_to_apicid, cpu) = -1;
635
	set_cpu_present(cpu, false);
636 637 638
	num_processors--;

	return (0);
Linus Torvalds's avatar
Linus Torvalds committed
639
}
Len Brown's avatar
Len Brown committed
640

Linus Torvalds's avatar
Linus Torvalds committed
641
EXPORT_SYMBOL(acpi_unmap_lsapic);
Len Brown's avatar
Len Brown committed
642
#endif				/* CONFIG_ACPI_HOTPLUG_CPU */
Linus Torvalds's avatar
Linus Torvalds committed
643

Len Brown's avatar
Len Brown committed
644
int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
645 646 647 648
{
	/* TBD */
	return -EINVAL;
}
Len Brown's avatar
Len Brown committed
649

650 651
EXPORT_SYMBOL(acpi_register_ioapic);

Len Brown's avatar
Len Brown committed
652
int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
653 654 655 656
{
	/* TBD */
	return -EINVAL;
}
Len Brown's avatar
Len Brown committed
657

658 659
EXPORT_SYMBOL(acpi_unregister_ioapic);

660
static int __init acpi_parse_sbf(struct acpi_table_header *table)
Linus Torvalds's avatar
Linus Torvalds committed
661
{
662
	struct acpi_table_boot *sb;
Linus Torvalds's avatar
Linus Torvalds committed
663

664
	sb = (struct acpi_table_boot *)table;
Linus Torvalds's avatar
Linus Torvalds committed
665 666 667 668 669
	if (!sb) {
		printk(KERN_WARNING PREFIX "Unable to map SBF\n");
		return -ENODEV;
	}

670
	sbf_port = sb->cmos_index;	/* Save CMOS port */
Linus Torvalds's avatar
Linus Torvalds committed
671 672 673 674 675

	return 0;
}

#ifdef CONFIG_HPET_TIMER
676
#include <asm/hpet.h>
Linus Torvalds's avatar
Linus Torvalds committed
677

678 679
static struct __initdata resource *hpet_res;

680
static int __init acpi_parse_hpet(struct acpi_table_header *table)
Linus Torvalds's avatar
Linus Torvalds committed
681 682 683
{
	struct acpi_table_hpet *hpet_tbl;

684
	hpet_tbl = (struct acpi_table_hpet *)table;
Linus Torvalds's avatar
Linus Torvalds committed
685 686 687 688 689
	if (!hpet_tbl) {
		printk(KERN_WARNING PREFIX "Unable to map HPET\n");
		return -ENODEV;
	}

690
	if (hpet_tbl->address.space_id != ACPI_SPACE_MEM) {
Linus Torvalds's avatar
Linus Torvalds committed
691 692 693 694
		printk(KERN_WARNING PREFIX "HPET timers must be located in "
		       "memory.\n");
		return -1;
	}
695

696
	hpet_address = hpet_tbl->address.address;
Thomas Gleixner's avatar
Thomas Gleixner committed
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728

	/*
	 * Some broken BIOSes advertise HPET at 0x0. We really do not
	 * want to allocate a resource there.
	 */
	if (!hpet_address) {
		printk(KERN_WARNING PREFIX
		       "HPET id: %#x base: %#lx is invalid\n",
		       hpet_tbl->id, hpet_address);
		return 0;
	}
#ifdef CONFIG_X86_64
	/*
	 * Some even more broken BIOSes advertise HPET at
	 * 0xfed0000000000000 instead of 0xfed00000. Fix it up and add
	 * some noise:
	 */
	if (hpet_address == 0xfed0000000000000UL) {
		if (!hpet_force_user) {
			printk(KERN_WARNING PREFIX "HPET id: %#x "
			       "base: 0xfed0000000000000 is bogus\n "
			       "try hpet=force on the kernel command line to "
			       "fix it up to 0xfed00000.\n", hpet_tbl->id);
			hpet_address = 0;
			return 0;
		}
		printk(KERN_WARNING PREFIX
		       "HPET id: %#x base: 0xfed0000000000000 fixed up "
		       "to 0xfed00000.\n", hpet_tbl->id);
		hpet_address >>= 32;
	}
#endif
Len Brown's avatar
Len Brown committed
729
	printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
730
	       hpet_tbl->id, hpet_address);
Linus Torvalds's avatar
Linus Torvalds committed
731

732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	/*
	 * Allocate and initialize the HPET firmware resource for adding into
	 * the resource tree during the lateinit timeframe.
	 */
#define HPET_RESOURCE_NAME_SIZE 9
	hpet_res = alloc_bootmem(sizeof(*hpet_res) + HPET_RESOURCE_NAME_SIZE);

	hpet_res->name = (void *)&hpet_res[1];
	hpet_res->flags = IORESOURCE_MEM;
	snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
		 hpet_tbl->sequence);

	hpet_res->start = hpet_address;
	hpet_res->end = hpet_address + (1 * 1024) - 1;

Linus Torvalds's avatar
Linus Torvalds committed
747 748
	return 0;
}
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763

/*
 * hpet_insert_resource inserts the HPET resources used into the resource
 * tree.
 */
static __init int hpet_insert_resource(void)
{
	if (!hpet_res)
		return 1;

	return insert_resource(&iomem_resource, hpet_res);
}

late_initcall(hpet_insert_resource);

Linus Torvalds's avatar
Linus Torvalds committed
764 765 766 767
#else
#define	acpi_parse_hpet	NULL
#endif

768
static int __init acpi_parse_fadt(struct acpi_table_header *table)
Linus Torvalds's avatar
Linus Torvalds committed
769
{
Jason Davis's avatar
Jason Davis committed
770

Linus Torvalds's avatar
Linus Torvalds committed
771 772
#ifdef CONFIG_X86_PM_TIMER
	/* detect the location of the ACPI PM Timer */
773
	if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) {
Linus Torvalds's avatar
Linus Torvalds committed
774
		/* FADT rev. 2 */
775
		if (acpi_gbl_FADT.xpm_timer_block.space_id !=
Len Brown's avatar
Len Brown committed
776
		    ACPI_ADR_SPACE_SYSTEM_IO)
Linus Torvalds's avatar
Linus Torvalds committed
777 778
			return 0;

779
		pmtmr_ioport = acpi_gbl_FADT.xpm_timer_block.address;
780 781 782 783 784 785
		/*
		 * "X" fields are optional extensions to the original V1.0
		 * fields, so we must selectively expand V1.0 fields if the
		 * corresponding X field is zero.
	 	 */
		if (!pmtmr_ioport)
786
			pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
Linus Torvalds's avatar
Linus Torvalds committed
787 788
	} else {
		/* FADT rev. 1 */
789
		pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
Linus Torvalds's avatar
Linus Torvalds committed
790 791
	}
	if (pmtmr_ioport)
Len Brown's avatar
Len Brown committed
792 793
		printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
		       pmtmr_ioport);
Linus Torvalds's avatar
Linus Torvalds committed
794 795 796 797 798 799 800 801 802
#endif
	return 0;
}

#ifdef	CONFIG_X86_LOCAL_APIC
/*
 * Parse LAPIC entries in MADT
 * returns 0 on success, < 0 on error
 */
803 804 805 806 807 808

static void __init acpi_register_lapic_address(unsigned long address)
{
	mp_lapic_addr = address;

	set_fixmap_nocache(FIX_APIC_BASE, address);
Yinghai Lu's avatar
Yinghai Lu committed
809
	if (boot_cpu_physical_apicid == -1U) {
810
		boot_cpu_physical_apicid  = read_apic_id();
Yinghai Lu's avatar
Yinghai Lu committed
811 812 813
		apic_version[boot_cpu_physical_apicid] =
			 GET_APIC_VERSION(apic_read(APIC_LVR));
	}
814 815
}

816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
{
	int count;

	if (!cpu_has_apic)
		return -ENODEV;

	/*
	 * 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).
	 */

	count =
	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
				  acpi_parse_lapic_addr_ovr, 0);
	if (count < 0) {
		printk(KERN_ERR PREFIX
		       "Error parsing LAPIC address override entry\n");
		return count;
	}

	acpi_register_lapic_address(acpi_lapic_addr);

	return count;
}

Len Brown's avatar
Len Brown committed
842
static int __init acpi_parse_madt_lapic_entries(void)
Linus Torvalds's avatar
Linus Torvalds committed
843 844
{
	int count;
845
	int x2count = 0;
Linus Torvalds's avatar
Linus Torvalds committed
846

847 848 849
	if (!cpu_has_apic)
		return -ENODEV;

850
	/*
Linus Torvalds's avatar
Linus Torvalds committed
851 852 853 854
	 * 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).
	 */

Len Brown's avatar
Len Brown committed
855
	count =
856
	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
Len Brown's avatar
Len Brown committed
857
				  acpi_parse_lapic_addr_ovr, 0);
Linus Torvalds's avatar
Linus Torvalds committed
858
	if (count < 0) {
Len Brown's avatar
Len Brown committed
859 860
		printk(KERN_ERR PREFIX
		       "Error parsing LAPIC address override entry\n");
Linus Torvalds's avatar
Linus Torvalds committed
861 862 863
		return count;
	}

864
	acpi_register_lapic_address(acpi_lapic_addr);
Linus Torvalds's avatar
Linus Torvalds committed
865

866 867 868
	count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_SAPIC,
				      acpi_parse_sapic, MAX_APICS);

869 870 871
	if (!count) {
		x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC,
						acpi_parse_x2apic, MAX_APICS);
872 873
		count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC,
					      acpi_parse_lapic, MAX_APICS);
874 875
	}
	if (!count && !x2count) {
Linus Torvalds's avatar
Linus Torvalds committed
876 877 878
		printk(KERN_ERR PREFIX "No LAPIC entries present\n");
		/* TBD: Cleanup to allow fallback to MPS */
		return -ENODEV;
879
	} else if (count < 0 || x2count < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
880 881 882 883 884
		printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
		/* TBD: Cleanup to allow fallback to MPS */
		return count;
	}

885 886 887
	x2count =
	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
				  acpi_parse_x2apic_nmi, 0);
Len Brown's avatar
Len Brown committed
888
	count =
889
	    acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
890
	if (count < 0 || x2count < 0) {
Linus Torvalds's avatar
Linus Torvalds committed
891 892 893 894 895 896
		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
		/* TBD: Cleanup to allow fallback to MPS */
		return count;
	}
	return 0;
}
Len Brown's avatar
Len Brown committed
897
#endif				/* CONFIG_X86_LOCAL_APIC */
Linus Torvalds's avatar
Linus Torvalds committed
898

899
#ifdef	CONFIG_X86_IO_APIC
900 901
#define MP_ISA_BUS		0

902
#ifdef CONFIG_X86_ES7000
903 904 905
extern int es7000_plat;
#endif

906 907 908 909 910 911
static struct {
	int apic_id;
	int gsi_base;
	int gsi_end;
	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
} mp_ioapic_routing[MAX_IO_APICS];
912

913
int mp_find_ioapic(int gsi)
914 915 916 917 918 919 920 921 922 923 924 925 926 927
{
	int i = 0;

	/* Find the IOAPIC that manages this GSI. */
	for (i = 0; i < nr_ioapics; i++) {
		if ((gsi >= mp_ioapic_routing[i].gsi_base)
		    && (gsi <= mp_ioapic_routing[i].gsi_end))
			return i;
	}

	printk(KERN_ERR "ERROR: Unable to locate IOAPIC for GSI %d\n", gsi);
	return -1;
}

928 929 930 931 932 933 934 935 936 937
int mp_find_ioapic_pin(int ioapic, int gsi)
{
	if (WARN_ON(ioapic == -1))
		return -1;
	if (WARN_ON(gsi > mp_ioapic_routing[ioapic].gsi_end))
		return -1;

	return gsi - mp_ioapic_routing[ioapic].gsi_base;
}

938 939 940 941 942 943 944 945 946 947 948 949 950
static u8 __init uniq_ioapic_id(u8 id)
{
#ifdef CONFIG_X86_32
	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
		return io_apic_get_unique_id(nr_ioapics, id);
	else
		return id;
#else
	int i;
	DECLARE_BITMAP(used, 256);
	bitmap_zero(used, 256);
	for (i = 0; i < nr_ioapics; i++) {
951 952
		struct mpc_ioapic *ia = &mp_ioapics[i];
		__set_bit(ia->apicid, used);
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
	}
	if (!test_bit(id, used))
		return id;
	return find_first_zero_bit(used, 256);
#endif
}

static int bad_ioapic(unsigned long address)
{
	if (nr_ioapics >= MAX_IO_APICS) {
		printk(KERN_ERR "ERROR: Max # of I/O APICs (%d) exceeded "
		       "(found %d)\n", MAX_IO_APICS, nr_ioapics);
		panic("Recompile kernel with bigger MAX_IO_APICS!\n");
	}
	if (!address) {
		printk(KERN_ERR "WARNING: Bogus (zero) I/O APIC address"
		       " found in table, skipping!\n");
		return 1;
	}
	return 0;
}

void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
{
	int idx = 0;

	if (bad_ioapic(address))
		return;

	idx = nr_ioapics;

984 985 986
	mp_ioapics[idx].type = MP_IOAPIC;
	mp_ioapics[idx].flags = MPC_APIC_USABLE;
	mp_ioapics[idx].apicaddr = address;
987 988

	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
989
	mp_ioapics[idx].apicid = uniq_ioapic_id(id);
990
#ifdef CONFIG_X86_32
991
	mp_ioapics[idx].apicver = io_apic_get_version(idx);
992
#else
993
	mp_ioapics[idx].apicver = 0;
994 995 996 997 998
#endif
	/*
	 * Build basic GSI lookup table to facilitate gsi->io_apic lookups
	 * and to prevent reprogramming of IOAPIC pins (PCI GSIs).
	 */
999
	mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
1000 1001 1002 1003
	mp_ioapic_routing[idx].gsi_base = gsi_base;
	mp_ioapic_routing[idx].gsi_end = gsi_base +
	    io_apic_get_redir_entries(idx);

1004 1005 1006
	printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, "
	       "GSI %d-%d\n", idx, mp_ioapics[idx].apicid,
	       mp_ioapics[idx].apicver, mp_ioapics[idx].apicaddr,
1007 1008 1009 1010 1011
	       mp_ioapic_routing[idx].gsi_base, mp_ioapic_routing[idx].gsi_end);

	nr_ioapics++;
}

1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
int __init acpi_probe_gsi(void)
{
	int idx;
	int gsi;
	int max_gsi = 0;

	if (acpi_disabled)
		return 0;

	if (!acpi_ioapic)
		return 0;

	max_gsi = 0;
	for (idx = 0; idx < nr_ioapics; idx++) {
		gsi = mp_ioapic_routing[idx].gsi_end;

		if (gsi > max_gsi)
			max_gsi = gsi;
	}

	return max_gsi + 1;
}

1035 1036
static void assign_to_mp_irq(struct mpc_intsrc *m,
				    struct mpc_intsrc *mp_irq)
1037
{
1038
	memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
1039 1040
}

1041 1042
static int mp_irq_cmp(struct mpc_intsrc *mp_irq,
				struct mpc_intsrc *m)
1043
{
1044
	return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
1045 1046
}

1047
static void save_mp_irq(struct mpc_intsrc *m)
1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060
{
	int i;

	for (i = 0; i < mp_irq_entries; i++) {
		if (!mp_irq_cmp(&mp_irqs[i], m))
			return;
	}

	assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
	if (++mp_irq_entries == MAX_IRQ_SOURCES)
		panic("Max # of irq sources exceeded!!\n");
}

1061 1062
void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
{
1063 1064
	int ioapic;
	int pin;
1065
	struct mpc_intsrc mp_irq;
1066 1067 1068 1069 1070 1071 1072

	/*
	 * Convert 'gsi' to 'ioapic.pin'.
	 */
	ioapic = mp_find_ioapic(gsi);
	if (ioapic < 0)
		return;
1073
	pin = mp_find_ioapic_pin(ioapic, gsi);
1074 1075 1076 1077 1078 1079 1080 1081 1082

	/*
	 * TBD: This check is for faulty timer entries, where the override
	 *      erroneously sets the trigger to level, resulting in a HUGE
	 *      increase of timer interrupts!
	 */
	if ((bus_irq == 0) && (trigger == 3))
		trigger = 1;

1083 1084 1085 1086 1087 1088 1089
	mp_irq.type = MP_INTSRC;
	mp_irq.irqtype = mp_INT;
	mp_irq.irqflag = (trigger << 2) | polarity;
	mp_irq.srcbus = MP_ISA_BUS;
	mp_irq.srcbusirq = bus_irq;	/* IRQ */
	mp_irq.dstapic = mp_ioapics[ioapic].apicid; /* APIC ID */
	mp_irq.dstirq = pin;	/* INTIN# */
1090

1091
	save_mp_irq(&mp_irq);
1092 1093 1094 1095
}

void __init mp_config_acpi_legacy_irqs(void)
{
1096 1097 1098
	int i;
	int ioapic;
	unsigned int dstapic;
1099
	struct mpc_intsrc mp_irq;
1100 1101 1102 1103 1104 1105 1106 1107

#if defined (CONFIG_MCA) || defined (CONFIG_EISA)
	/*
	 * Fabricate the legacy ISA bus (bus #31).
	 */
	mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
#endif
	set_bit(MP_ISA_BUS, mp_bus_not_pci);
1108
	pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
1109

1110
#ifdef CONFIG_X86_ES7000