1/*
2 *  acpi.c - Architecture-Specific Low-Level ACPI Support
3 *
4 *  Copyright (C) 1999 VA Linux Systems
5 *  Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
6 *  Copyright (C) 2000, 2002 Hewlett-Packard Co.
7 *	David Mosberger-Tang <davidm@hpl.hp.com>
8 *  Copyright (C) 2000 Intel Corp.
9 *  Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
10 *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
11 *
12 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
13 *
14 *  This program is free software; you can redistribute it and/or modify
15 *  it under the terms of the GNU General Public License as published by
16 *  the Free Software Foundation; either version 2 of the License, or
17 *  (at your option) any later version.
18 *
19 *  This program is distributed in the hope that it will be useful,
20 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 *  GNU General Public License for more details.
23 *
24 *  You should have received a copy of the GNU General Public License
25 *  along with this program; if not, write to the Free Software
26 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 */
30
31#include <linux/config.h>
32#include <linux/init.h>
33#include <linux/kernel.h>
34#include <linux/sched.h>
35#include <linux/smp.h>
36#include <linux/string.h>
37#include <linux/types.h>
38#include <linux/irq.h>
39#include <linux/acpi.h>
40#include <linux/efi.h>
41#include <asm/io.h>
42#include <asm/iosapic.h>
43#include <asm/machvec.h>
44#include <asm/page.h>
45#include <asm/system.h>
46
47
48#define PREFIX			"ACPI: "
49
50asm (".weak iosapic_register_intr");
51asm (".weak iosapic_override_isa_irq");
52asm (".weak iosapic_register_platform_intr");
53asm (".weak iosapic_init");
54asm (".weak iosapic_version");
55
56void (*pm_idle) (void);
57void (*pm_power_off) (void);
58
59unsigned char acpi_kbd_controller_present = 1;
60
61const char *
62acpi_get_sysname (void)
63{
64#ifdef CONFIG_IA64_GENERIC
65	unsigned long rsdp_phys;
66	struct acpi20_table_rsdp *rsdp;
67	struct acpi_table_xsdt *xsdt;
68	struct acpi_table_header *hdr;
69
70	rsdp_phys = acpi_find_rsdp();
71	if (!rsdp_phys) {
72		printk("ACPI 2.0 RSDP not found, default to \"dig\"\n");
73		return "dig";
74	}
75
76	rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys);
77	if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) {
78		printk("ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
79		return "dig";
80	}
81
82	xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address);
83	hdr = &xsdt->header;
84	if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) {
85		printk("ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
86		return "dig";
87	}
88
89	if (!strcmp(hdr->oem_id, "HP")) {
90		return "hpzx1";
91	}
92
93	return "dig";
94#else
95# if defined (CONFIG_IA64_HP_SIM)
96	return "hpsim";
97# elif defined (CONFIG_IA64_HP_ZX1)
98	return "hpzx1";
99# elif defined (CONFIG_IA64_SGI_SN1)
100	return "sn1";
101# elif defined (CONFIG_IA64_SGI_SN2)
102	return "sn2";
103# elif defined (CONFIG_IA64_DIG)
104	return "dig";
105# elif defined (CONFIG_IA64_HP_ZX1)
106	return "hpzx1";
107# else
108#	error Unknown platform.  Fix acpi.c.
109# endif
110#endif
111}
112
113#ifdef CONFIG_ACPI
114
115/**
116 * acpi_get_crs - Return the current resource settings for a device
117 * obj: A handle for this device
118 * buf: A buffer to be populated by this call.
119 *
120 * Pass a valid handle, typically obtained by walking the namespace and a
121 * pointer to an allocated buffer, and this function will fill in the buffer
122 * with a list of acpi_resource structures.
123 */
124acpi_status
125acpi_get_crs (acpi_handle obj, acpi_buffer *buf)
126{
127	acpi_status result;
128	buf->length = 0;
129	buf->pointer = NULL;
130
131	result = acpi_get_current_resources(obj, buf);
132	if (result != AE_BUFFER_OVERFLOW)
133		return result;
134	buf->pointer = kmalloc(buf->length, GFP_KERNEL);
135	if (!buf->pointer)
136		return -ENOMEM;
137
138	return acpi_get_current_resources(obj, buf);
139}
140
141acpi_resource *
142acpi_get_crs_next (acpi_buffer *buf, int *offset)
143{
144	acpi_resource *res;
145
146	if (*offset >= buf->length)
147		return NULL;
148
149	res = buf->pointer + *offset;
150	*offset += res->length;
151	return res;
152}
153
154acpi_resource_data *
155acpi_get_crs_type (acpi_buffer *buf, int *offset, int type)
156{
157	for (;;) {
158		acpi_resource *res = acpi_get_crs_next(buf, offset);
159		if (!res)
160			return NULL;
161		if (res->id == type)
162			return &res->data;
163	}
164}
165
166void
167acpi_dispose_crs (acpi_buffer *buf)
168{
169	kfree(buf->pointer);
170}
171
172static void
173acpi_get_crs_addr (acpi_buffer *buf, int type, u64 *base, u64 *length, u64 *tra)
174{
175	int offset = 0;
176	acpi_resource_address16 *addr16;
177	acpi_resource_address32 *addr32;
178	acpi_resource_address64 *addr64;
179
180	for (;;) {
181		acpi_resource *res = acpi_get_crs_next(buf, &offset);
182		if (!res)
183			return;
184		switch (res->id) {
185			case ACPI_RSTYPE_ADDRESS16:
186				addr16 = (acpi_resource_address16 *) &res->data;
187
188				if (type == addr16->resource_type) {
189					*base = addr16->min_address_range;
190					*length = addr16->address_length;
191					*tra = addr16->address_translation_offset;
192					return;
193				}
194				break;
195			case ACPI_RSTYPE_ADDRESS32:
196				addr32 = (acpi_resource_address32 *) &res->data;
197				if (type == addr32->resource_type) {
198					*base = addr32->min_address_range;
199					*length = addr32->address_length;
200					*tra = addr32->address_translation_offset;
201					return;
202				}
203				break;
204			case ACPI_RSTYPE_ADDRESS64:
205				addr64 = (acpi_resource_address64 *) &res->data;
206				if (type == addr64->resource_type) {
207					*base = addr64->min_address_range;
208					*length = addr64->address_length;
209					*tra = addr64->address_translation_offset;
210					return;
211				}
212				break;
213		}
214	}
215}
216
217acpi_status
218acpi_get_addr_space(acpi_handle obj, u8 type, u64 *base, u64 *length, u64 *tra)
219{
220	acpi_status status;
221	acpi_buffer buf;
222
223	*base = 0;
224	*length = 0;
225	*tra = 0;
226
227	status = acpi_get_crs(obj, &buf);
228	if (ACPI_FAILURE(status)) {
229		printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
230		return status;
231	}
232
233	acpi_get_crs_addr(&buf, type, base, length, tra);
234
235	acpi_dispose_crs(&buf);
236
237	return AE_OK;
238}
239
240typedef struct {
241	u8	guid_id;
242	u8	guid[16];
243	u8	csr_base[8];
244	u8	csr_length[8];
245} acpi_hp_vendor_long;
246
247#define HP_CCSR_LENGTH 0x21
248#define HP_CCSR_TYPE 0x2
249#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \
250			      0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad)
251
252acpi_status
253acpi_hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length)
254{
255	int i, offset = 0;
256	acpi_status status;
257	acpi_buffer buf;
258	acpi_resource_vendor *res;
259	acpi_hp_vendor_long *hp_res;
260	efi_guid_t vendor_guid;
261
262	*csr_base = 0;
263	*csr_length = 0;
264
265	status = acpi_get_crs(obj, &buf);
266	if (ACPI_FAILURE(status)) {
267		printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n");
268		return status;
269	}
270
271	res = (acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR);
272	if (!res) {
273		printk(KERN_ERR PREFIX "Failed to find config space for device\n");
274		acpi_dispose_crs(&buf);
275		return AE_NOT_FOUND;
276	}
277
278	hp_res = (acpi_hp_vendor_long *)(res->reserved);
279
280	if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) {
281		printk(KERN_ERR PREFIX "Unknown Vendor data\n");
282		acpi_dispose_crs(&buf);
283		return AE_TYPE; /* Revisit error? */
284	}
285
286	memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t));
287	if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) {
288		printk(KERN_ERR PREFIX "Vendor GUID does not match\n");
289		acpi_dispose_crs(&buf);
290		return AE_TYPE; /* Revisit error? */
291	}
292
293	for (i = 0 ; i < 8 ; i++) {
294		*csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8));
295		*csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8));
296	}
297
298	acpi_dispose_crs(&buf);
299
300	return AE_OK;
301}
302#endif /* CONFIG_ACPI */
303
304#ifdef CONFIG_ACPI_BOOT
305
306#define ACPI_MAX_PLATFORM_INTERRUPTS	256
307
308/* Array to record platform interrupt vectors for generic interrupt routing. */
309int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 };
310
311enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
312
313/*
314 * Interrupt routing API for device drivers.  Provides interrupt vector for
315 * a generic platform event.  Currently only CPEI is implemented.
316 */
317int
318acpi_request_vector (u32 int_type)
319{
320	int vector = -1;
321
322	if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) {
323		/* correctable platform error interrupt */
324		vector = platform_intr_list[int_type];
325	} else
326		printk("acpi_request_vector(): invalid interrupt type\n");
327
328	return vector;
329}
330
331char *
332__acpi_map_table (unsigned long phys_addr, unsigned long size)
333{
334	return __va(phys_addr);
335}
336
337/* --------------------------------------------------------------------------
338                            Boot-time Table Parsing
339   -------------------------------------------------------------------------- */
340
341static int			total_cpus __initdata;
342static int			available_cpus __initdata;
343struct acpi_table_madt *	acpi_madt __initdata;
344static u8			has_8259;
345
346
347static int __init
348acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
349{
350	struct acpi_table_lapic_addr_ovr *lapic;
351
352	lapic = (struct acpi_table_lapic_addr_ovr *) header;
353	if (!lapic)
354		return -EINVAL;
355
356	acpi_table_print_madt_entry(header);
357
358	if (lapic->address) {
359		iounmap((void *) ipi_base_addr);
360		ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
361	}
362
363	return 0;
364}
365
366
367static int __init
368acpi_parse_lsapic (acpi_table_entry_header *header)
369{
370	struct acpi_table_lsapic *lsapic;
371
372	lsapic = (struct acpi_table_lsapic *) header;
373	if (!lsapic)
374		return -EINVAL;
375
376	acpi_table_print_madt_entry(header);
377
378	printk("CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid);
379
380	if (lsapic->flags.enabled) {
381		available_cpus++;
382		printk(" enabled");
383#ifdef CONFIG_SMP
384		smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid;
385		if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus])
386			printk(" (BSP)");
387#endif
388	}
389	else {
390		printk(" disabled");
391#ifdef CONFIG_SMP
392		smp_boot_data.cpu_phys_id[total_cpus] = -1;
393#endif
394	}
395
396	printk("\n");
397
398	total_cpus++;
399	return 0;
400}
401
402
403static int __init
404acpi_parse_lapic_nmi (acpi_table_entry_header *header)
405{
406	struct acpi_table_lapic_nmi *lacpi_nmi;
407
408	lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
409	if (!lacpi_nmi)
410		return -EINVAL;
411
412	acpi_table_print_madt_entry(header);
413
414	/* TBD: Support lapic_nmi entries */
415
416	return 0;
417}
418
419
420static int __init
421acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address)
422{
423	struct acpi_table_iosapic *iosapic;
424	int ver;
425	int max_pin;
426	char *p;
427	char *end;
428
429	if (!gsi_base || !iosapic_address)
430		return -ENODEV;
431
432	p = (char *) (acpi_madt + 1);
433	end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt));
434
435	while (p < end) {
436		if (*p == ACPI_MADT_IOSAPIC) {
437			iosapic = (struct acpi_table_iosapic *) p;
438
439			*gsi_base = iosapic->global_irq_base;
440			*iosapic_address = ioremap(iosapic->address, 0);
441
442			ver = iosapic_version(*iosapic_address);
443			max_pin = (ver >> 16) & 0xff;
444
445			if ((gsi - *gsi_base) <= max_pin)
446				return 0;	/* Found it! */
447		}
448		p += p[1];
449	}
450	return -ENODEV;
451}
452
453
454static int __init
455acpi_parse_iosapic (acpi_table_entry_header *header)
456{
457	struct acpi_table_iosapic *iosapic;
458
459	iosapic = (struct acpi_table_iosapic *) header;
460	if (!iosapic)
461		return -EINVAL;
462
463	acpi_table_print_madt_entry(header);
464
465	if (iosapic_init) {
466#ifndef CONFIG_ITANIUM
467		/* PCAT_COMPAT flag indicates dual-8259 setup */
468		iosapic_init(iosapic->address, iosapic->global_irq_base,
469			     acpi_madt->flags.pcat_compat);
470#else
471		/* Firmware on old Itanium systems is broken */
472		iosapic_init(iosapic->address, iosapic->global_irq_base, 1);
473#endif
474	}
475	return 0;
476}
477
478
479static int __init
480acpi_parse_plat_int_src (acpi_table_entry_header *header)
481{
482	struct acpi_table_plat_int_src *plintsrc;
483	int vector;
484	u32 gsi_base;
485	char *iosapic_address;
486
487	plintsrc = (struct acpi_table_plat_int_src *) header;
488	if (!plintsrc)
489		return -EINVAL;
490
491	acpi_table_print_madt_entry(header);
492
493	if (!iosapic_register_platform_intr) {
494		printk(KERN_WARNING PREFIX "No ACPI platform interrupt support\n");
495		return -ENODEV;
496	}
497
498	if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) {
499		printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
500		return -ENODEV;
501	}
502
503	/*
504	 * Get vector assignment for this interrupt, set attributes,
505	 * and program the IOSAPIC routing table.
506	 */
507	vector = iosapic_register_platform_intr(plintsrc->type,
508						plintsrc->global_irq,
509						plintsrc->iosapic_vector,
510						plintsrc->eid,
511						plintsrc->id,
512						(plintsrc->flags.polarity == 1) ? 1 : 0,
513						(plintsrc->flags.trigger == 1) ? 1 : 0,
514						gsi_base,
515						iosapic_address);
516
517	platform_intr_list[plintsrc->type] = vector;
518	return 0;
519}
520
521
522static int __init
523acpi_parse_int_src_ovr (acpi_table_entry_header *header)
524{
525	struct acpi_table_int_src_ovr *p;
526
527	p = (struct acpi_table_int_src_ovr *) header;
528	if (!p)
529		return -EINVAL;
530
531	acpi_table_print_madt_entry(header);
532
533	/* Ignore if the platform doesn't support overrides */
534	if (!iosapic_override_isa_irq)
535		return 0;
536
537	iosapic_override_isa_irq(p->bus_irq, p->global_irq,
538				 (p->flags.polarity == 1) ? 1 : 0,
539				 (p->flags.trigger == 1) ? 1 : 0);
540
541	return 0;
542}
543
544
545static int __init
546acpi_parse_nmi_src (acpi_table_entry_header *header)
547{
548	struct acpi_table_nmi_src *nmi_src;
549
550	nmi_src = (struct acpi_table_nmi_src*) header;
551	if (!nmi_src)
552		return -EINVAL;
553
554	acpi_table_print_madt_entry(header);
555
556	/* TBD: Support nimsrc entries */
557
558	return 0;
559}
560
561
562static int __init
563acpi_parse_madt (unsigned long phys_addr, unsigned long size)
564{
565	if (!phys_addr || !size)
566		return -EINVAL;
567
568	acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
569
570	/* remember the value for reference after free_initmem() */
571	has_8259 = acpi_madt->flags.pcat_compat;
572
573	/* Get base address of IPI Message Block */
574
575	if (acpi_madt->lapic_address)
576		ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
577
578	printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
579	return 0;
580}
581
582
583static int __init
584acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
585{
586	struct acpi_table_header *fadt_header;
587	fadt_descriptor_rev2 *fadt;
588	u32 sci_irq, gsi_base;
589	char *iosapic_address;
590
591	if (!phys_addr || !size)
592		return -EINVAL;
593
594	fadt_header = (struct acpi_table_header *) __va(phys_addr);
595
596	if (fadt_header->revision != 3)
597		return -ENODEV;		/* Only deal with ACPI 2.0 FADT */
598
599	fadt = (fadt_descriptor_rev2 *) fadt_header;
600
601	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
602		acpi_kbd_controller_present = 0;
603
604	sci_irq = fadt->sci_int;
605
606	if (has_8259 && sci_irq < 16)
607		return 0;	/* legacy, no setup required */
608
609	if (!iosapic_register_intr)
610		return -ENODEV;
611
612	if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address))
613		iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address);
614
615	return 0;
616}
617
618
619#ifdef CONFIG_SERIAL_ACPI
620
621#include <linux/acpi_serial.h>
622
623static int __init
624acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
625{
626	acpi_ser_t *spcr;
627	u32 gsi, gsi_base;
628	char *iosapic_address;
629
630	if (!phys_addr || !size)
631		return -EINVAL;
632
633	if (!iosapic_register_intr)
634		return -ENODEV;
635
636	/*
637	 * ACPI is able to describe serial ports that live at non-standard
638	 * memory addresses and use non-standard interrupts, either via
639	 * direct SAPIC mappings or via PCI interrupts.  We handle interrupt
640	 * routing for SAPIC-based (non-PCI) devices here.  Interrupt routing
641	 * for PCI devices will be handled when processing the PCI Interrupt
642	 * Routing Table (PRT).
643	 */
644
645	spcr = (acpi_ser_t *) __va(phys_addr);
646	setup_serial_acpi(spcr);
647
648	if (spcr->length < sizeof(acpi_ser_t))
649		/* Table not long enough for full info, thus no interrupt */
650		return -ENODEV;
651
652	if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
653	    (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) {
654
655		/* We have a UART in memory space with an SAPIC interrupt */
656
657		gsi = (spcr->global_int[3] << 24) |
658		      (spcr->global_int[2] << 16) |
659		      (spcr->global_int[1] << 8)  |
660		      (spcr->global_int[0]);
661
662		if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address))
663			iosapic_register_intr(gsi, 1, 1,
664					      gsi_base, iosapic_address);
665	}
666	return 0;
667}
668
669#endif /*CONFIG_SERIAL_ACPI*/
670
671
672unsigned long __init
673acpi_find_rsdp (void)
674{
675	unsigned long rsdp_phys = 0;
676
677	if (efi.acpi20)
678		rsdp_phys = __pa(efi.acpi20);
679	else if (efi.acpi)
680		printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
681
682	return rsdp_phys;
683}
684
685
686int __init
687acpi_boot_init (char *cmdline)
688{
689	int result;
690
691	/* Initialize the ACPI boot-time table parser */
692	result = acpi_table_init(cmdline);
693	if (result)
694		return result;
695
696	/*
697	 * MADT
698	 * ----
699	 * Parse the Multiple APIC Description Table (MADT), if exists.
700	 * Note that this table provides platform SMP configuration
701	 * information -- the successor to MPS tables.
702	 */
703
704	if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) {
705		printk(KERN_ERR PREFIX "Can't find MADT\n");
706		goto skip_madt;
707	}
708
709	/* Local APIC */
710
711	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR,
712				  acpi_parse_lapic_addr_ovr) < 0)
713		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
714
715	if (acpi_table_parse_madt(ACPI_MADT_LSAPIC,
716				  acpi_parse_lsapic) < 1)
717		printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
718
719	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI,
720				  acpi_parse_lapic_nmi) < 0)
721		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
722
723	/* I/O APIC */
724
725	if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC,
726				  acpi_parse_iosapic) < 1)
727		printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries\n");
728
729	/* System-Level Interrupt Routing */
730
731	if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC,
732				  acpi_parse_plat_int_src) < 0)
733		printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
734
735	if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR,
736				  acpi_parse_int_src_ovr) < 0)
737		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
738
739	if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC,
740				  acpi_parse_nmi_src) < 0)
741		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
742skip_madt:
743
744	/*
745	 * The FADT table contains an SCI_INT line, by which the system
746	 * gets interrupts such as power and sleep buttons.  If it's not
747	 * on a Legacy interrupt, it needs to be setup.
748	 */
749	if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
750		printk(KERN_ERR PREFIX "Can't find FADT\n");
751
752#ifdef CONFIG_SERIAL_ACPI
753	acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);
754#endif
755
756#ifdef CONFIG_SMP
757	if (available_cpus == 0) {
758		printk("ACPI: Found 0 CPUS; assuming 1\n");
759		available_cpus = 1; /* We've got at least one of these, no? */
760	}
761	smp_boot_data.cpu_count = total_cpus;
762#endif
763	/* Make boot-up look pretty */
764	printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
765	return 0;
766}
767
768
769/* --------------------------------------------------------------------------
770                             PCI Interrupt Routing
771   -------------------------------------------------------------------------- */
772
773int __init
774acpi_get_prt (struct pci_vector_struct **vectors, int *count)
775{
776	struct pci_vector_struct *vector;
777	struct list_head *node;
778	struct acpi_prt_entry *entry;
779	int i = 0;
780
781	if (!vectors || !count)
782		return -EINVAL;
783
784	*vectors = NULL;
785	*count = 0;
786
787	if (acpi_prt.count < 0) {
788		printk(KERN_ERR PREFIX "No PCI interrupt routing entries\n");
789		return -ENODEV;
790	}
791
792	/* Allocate vectors */
793
794	*vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL);
795	if (!(*vectors))
796		return -ENOMEM;
797
798	/* Convert PRT entries to IOSAPIC PCI vectors */
799
800	vector = *vectors;
801
802	list_for_each(node, &acpi_prt.entries) {
803		entry = (struct acpi_prt_entry *)node;
804		vector[i].segment = entry->id.segment;
805		vector[i].bus    = entry->id.bus;
806		vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff;
807		vector[i].pin    = entry->pin;
808		vector[i].irq    = entry->link.index;
809		i++;
810	}
811	*count = acpi_prt.count;
812	return 0;
813}
814
815/* Assume IA64 always use I/O SAPIC */
816
817int __init
818acpi_get_interrupt_model (int *type)
819{
820        if (!type)
821                return -EINVAL;
822
823	*type = ACPI_IRQ_MODEL_IOSAPIC;
824        return 0;
825}
826
827int
828acpi_irq_to_vector (u32 irq)
829{
830	if (has_8259 && irq < 16)
831		return isa_irq_to_vector(irq);
832
833	return gsi_to_vector(irq);
834}
835
836#endif /* CONFIG_ACPI_BOOT */
837