ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / kernel / acpi.c
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-2003 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  *  Copyright (C) 2001 Jenna Hall <jenna.s.hall@intel.com>
12  *  Copyright (C) 2001 Takayoshi Kochi <t-kochi@bq.jp.nec.com>
13  *  Copyright (C) 2002 Erich Focht <efocht@ess.nec.de>
14  *
15  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16  *
17  *  This program is free software; you can redistribute it and/or modify
18  *  it under the terms of the GNU General Public License as published by
19  *  the Free Software Foundation; either version 2 of the License, or
20  *  (at your option) any later version.
21  *
22  *  This program is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  *  GNU General Public License for more details.
26  *
27  *  You should have received a copy of the GNU General Public License
28  *  along with this program; if not, write to the Free Software
29  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  *
31  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32  */
33
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/init.h>
37 #include <linux/kernel.h>
38 #include <linux/sched.h>
39 #include <linux/smp.h>
40 #include <linux/string.h>
41 #include <linux/types.h>
42 #include <linux/irq.h>
43 #include <linux/acpi.h>
44 #include <linux/efi.h>
45 #include <linux/mmzone.h>
46 #include <asm/io.h>
47 #include <asm/iosapic.h>
48 #include <asm/machvec.h>
49 #include <asm/page.h>
50 #include <asm/system.h>
51 #include <asm/numa.h>
52 #include <asm/sal.h>
53 #include <asm/cyclone.h>
54
55
56 #define PREFIX                  "ACPI: "
57
58 void (*pm_idle) (void);
59 EXPORT_SYMBOL(pm_idle);
60 void (*pm_power_off) (void);
61
62 unsigned char acpi_kbd_controller_present = 1;
63 unsigned char acpi_legacy_devices;
64
65 const char *
66 acpi_get_sysname (void)
67 {
68 #ifdef CONFIG_IA64_GENERIC
69         unsigned long rsdp_phys;
70         struct acpi20_table_rsdp *rsdp;
71         struct acpi_table_xsdt *xsdt;
72         struct acpi_table_header *hdr;
73
74         rsdp_phys = acpi_find_rsdp();
75         if (!rsdp_phys) {
76                 printk(KERN_ERR "ACPI 2.0 RSDP not found, default to \"dig\"\n");
77                 return "dig";
78         }
79
80         rsdp = (struct acpi20_table_rsdp *) __va(rsdp_phys);
81         if (strncmp(rsdp->signature, RSDP_SIG, sizeof(RSDP_SIG) - 1)) {
82                 printk(KERN_ERR "ACPI 2.0 RSDP signature incorrect, default to \"dig\"\n");
83                 return "dig";
84         }
85
86         xsdt = (struct acpi_table_xsdt *) __va(rsdp->xsdt_address);
87         hdr = &xsdt->header;
88         if (strncmp(hdr->signature, XSDT_SIG, sizeof(XSDT_SIG) - 1)) {
89                 printk(KERN_ERR "ACPI 2.0 XSDT signature incorrect, default to \"dig\"\n");
90                 return "dig";
91         }
92
93         if (!strcmp(hdr->oem_id, "HP")) {
94                 return "hpzx1";
95         }
96         else if (!strcmp(hdr->oem_id, "SGI")) {
97                 return "sn2";
98         }
99
100         return "dig";
101 #else
102 # if defined (CONFIG_IA64_HP_SIM)
103         return "hpsim";
104 # elif defined (CONFIG_IA64_HP_ZX1)
105         return "hpzx1";
106 # elif defined (CONFIG_IA64_SGI_SN2)
107         return "sn2";
108 # elif defined (CONFIG_IA64_DIG)
109         return "dig";
110 # else
111 #       error Unknown platform.  Fix acpi.c.
112 # endif
113 #endif
114 }
115
116 #ifdef CONFIG_ACPI_BOOT
117
118 #define ACPI_MAX_PLATFORM_INTERRUPTS    256
119
120 /* Array to record platform interrupt vectors for generic interrupt routing. */
121 int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = {
122         [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1
123 };
124
125 enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
126
127 /*
128  * Interrupt routing API for device drivers.  Provides interrupt vector for
129  * a generic platform event.  Currently only CPEI is implemented.
130  */
131 int
132 acpi_request_vector (u32 int_type)
133 {
134         int vector = -1;
135
136         if (int_type < ACPI_MAX_PLATFORM_INTERRUPTS) {
137                 /* corrected platform error interrupt */
138                 vector = platform_intr_list[int_type];
139         } else
140                 printk(KERN_ERR "acpi_request_vector(): invalid interrupt type\n");
141         return vector;
142 }
143
144 char *
145 __acpi_map_table (unsigned long phys_addr, unsigned long size)
146 {
147         return __va(phys_addr);
148 }
149
150 /* --------------------------------------------------------------------------
151                             Boot-time Table Parsing
152    -------------------------------------------------------------------------- */
153
154 static int                      total_cpus __initdata;
155 static int                      available_cpus __initdata;
156 struct acpi_table_madt *        acpi_madt __initdata;
157 static u8                       has_8259;
158
159
160 static int __init
161 acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
162 {
163         struct acpi_table_lapic_addr_ovr *lapic;
164
165         lapic = (struct acpi_table_lapic_addr_ovr *) header;
166         if (!lapic)
167                 return -EINVAL;
168
169         acpi_table_print_madt_entry(header);
170
171         if (lapic->address) {
172                 iounmap((void *) ipi_base_addr);
173                 ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
174         }
175         return 0;
176 }
177
178
179 static int __init
180 acpi_parse_lsapic (acpi_table_entry_header *header)
181 {
182         struct acpi_table_lsapic *lsapic;
183
184         lsapic = (struct acpi_table_lsapic *) header;
185         if (!lsapic)
186                 return -EINVAL;
187
188         acpi_table_print_madt_entry(header);
189
190         printk(KERN_INFO "CPU %d (0x%04x)", total_cpus, (lsapic->id << 8) | lsapic->eid);
191
192         if (!lsapic->flags.enabled)
193                 printk(" disabled");
194         else {
195                 printk(" enabled");
196 #ifdef CONFIG_SMP
197                 smp_boot_data.cpu_phys_id[available_cpus] = (lsapic->id << 8) | lsapic->eid;
198                 if (hard_smp_processor_id()
199                     == (unsigned int) smp_boot_data.cpu_phys_id[available_cpus])
200                         printk(" (BSP)");
201 #endif
202                 ++available_cpus;
203         }
204
205         printk("\n");
206
207         total_cpus++;
208         return 0;
209 }
210
211
212 static int __init
213 acpi_parse_lapic_nmi (acpi_table_entry_header *header)
214 {
215         struct acpi_table_lapic_nmi *lacpi_nmi;
216
217         lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
218         if (!lacpi_nmi)
219                 return -EINVAL;
220
221         acpi_table_print_madt_entry(header);
222
223         /* TBD: Support lapic_nmi entries */
224         return 0;
225 }
226
227
228 static int __init
229 acpi_parse_iosapic (acpi_table_entry_header *header)
230 {
231         struct acpi_table_iosapic *iosapic;
232
233         iosapic = (struct acpi_table_iosapic *) header;
234         if (!iosapic)
235                 return -EINVAL;
236
237         acpi_table_print_madt_entry(header);
238
239         iosapic_init(iosapic->address, iosapic->global_irq_base);
240
241         return 0;
242 }
243
244
245 static int __init
246 acpi_parse_plat_int_src (acpi_table_entry_header *header)
247 {
248         struct acpi_table_plat_int_src *plintsrc;
249         int vector;
250
251         plintsrc = (struct acpi_table_plat_int_src *) header;
252         if (!plintsrc)
253                 return -EINVAL;
254
255         acpi_table_print_madt_entry(header);
256
257         /*
258          * Get vector assignment for this interrupt, set attributes,
259          * and program the IOSAPIC routing table.
260          */
261         vector = iosapic_register_platform_intr(plintsrc->type,
262                                                 plintsrc->global_irq,
263                                                 plintsrc->iosapic_vector,
264                                                 plintsrc->eid,
265                                                 plintsrc->id,
266                                                 (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
267                                                 (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
268
269         platform_intr_list[plintsrc->type] = vector;
270         return 0;
271 }
272
273
274 static int __init
275 acpi_parse_int_src_ovr (acpi_table_entry_header *header)
276 {
277         struct acpi_table_int_src_ovr *p;
278
279         p = (struct acpi_table_int_src_ovr *) header;
280         if (!p)
281                 return -EINVAL;
282
283         acpi_table_print_madt_entry(header);
284
285         iosapic_override_isa_irq(p->bus_irq, p->global_irq,
286                                  (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
287                                  (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
288         return 0;
289 }
290
291
292 static int __init
293 acpi_parse_nmi_src (acpi_table_entry_header *header)
294 {
295         struct acpi_table_nmi_src *nmi_src;
296
297         nmi_src = (struct acpi_table_nmi_src*) header;
298         if (!nmi_src)
299                 return -EINVAL;
300
301         acpi_table_print_madt_entry(header);
302
303         /* TBD: Support nimsrc entries */
304         return 0;
305 }
306
307 /* Hook from generic ACPI tables.c */
308 void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
309 {
310         if (!strncmp(oem_id, "IBM", 3) &&
311             (!strncmp(oem_table_id, "SERMOW", 6))){
312
313                 /* Unfortunatly ITC_DRIFT is not yet part of the
314                  * official SAL spec, so the ITC_DRIFT bit is not
315                  * set by the BIOS on this hardware.
316                  */
317                 sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT;
318
319                 /*Start cyclone clock*/
320                 cyclone_setup(0);
321         }
322 }
323
324 static int __init
325 acpi_parse_madt (unsigned long phys_addr, unsigned long size)
326 {
327         if (!phys_addr || !size)
328                 return -EINVAL;
329
330         acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
331
332         /* remember the value for reference after free_initmem() */
333 #ifdef CONFIG_ITANIUM
334         has_8259 = 1; /* Firmware on old Itanium systems is broken */
335 #else
336         has_8259 = acpi_madt->flags.pcat_compat;
337 #endif
338         iosapic_system_init(has_8259);
339
340         /* Get base address of IPI Message Block */
341
342         if (acpi_madt->lapic_address)
343                 ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
344
345         printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
346
347         acpi_madt_oem_check(acpi_madt->header.oem_id,
348                 acpi_madt->header.oem_table_id);
349
350         return 0;
351 }
352
353
354 #ifdef CONFIG_ACPI_NUMA
355
356 #undef SLIT_DEBUG
357
358 #define PXM_FLAG_LEN ((MAX_PXM_DOMAINS + 1)/32)
359
360 static int __initdata srat_num_cpus;                    /* number of cpus */
361 static u32 __initdata pxm_flag[PXM_FLAG_LEN];
362 #define pxm_bit_set(bit)        (set_bit(bit,(void *)pxm_flag))
363 #define pxm_bit_test(bit)       (test_bit(bit,(void *)pxm_flag))
364 /* maps to convert between proximity domain and logical node ID */
365 int __initdata pxm_to_nid_map[MAX_PXM_DOMAINS];
366 int __initdata nid_to_pxm_map[MAX_NUMNODES];
367 static struct acpi_table_slit __initdata *slit_table;
368
369 /*
370  * ACPI 2.0 SLIT (System Locality Information Table)
371  * http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
372  */
373 void __init
374 acpi_numa_slit_init (struct acpi_table_slit *slit)
375 {
376         u32 len;
377
378         len = sizeof(struct acpi_table_header) + 8
379                 + slit->localities * slit->localities;
380         if (slit->header.length != len) {
381                 printk(KERN_ERR "ACPI 2.0 SLIT: size mismatch: %d expected, %d actual\n",
382                        len, slit->header.length);
383                 memset(numa_slit, 10, sizeof(numa_slit));
384                 return;
385         }
386         slit_table = slit;
387 }
388
389 void __init
390 acpi_numa_processor_affinity_init (struct acpi_table_processor_affinity *pa)
391 {
392         /* record this node in proximity bitmap */
393         pxm_bit_set(pa->proximity_domain);
394
395         node_cpuid[srat_num_cpus].phys_id = (pa->apic_id << 8) | (pa->lsapic_eid);
396         /* nid should be overridden as logical node id later */
397         node_cpuid[srat_num_cpus].nid = pa->proximity_domain;
398         srat_num_cpus++;
399 }
400
401 void __init
402 acpi_numa_memory_affinity_init (struct acpi_table_memory_affinity *ma)
403 {
404         unsigned long paddr, size;
405         u8 pxm;
406         struct node_memblk_s *p, *q, *pend;
407
408         pxm = ma->proximity_domain;
409
410         /* fill node memory chunk structure */
411         paddr = ma->base_addr_hi;
412         paddr = (paddr << 32) | ma->base_addr_lo;
413         size = ma->length_hi;
414         size = (size << 32) | ma->length_lo;
415
416         /* Ignore disabled entries */
417         if (!ma->flags.enabled)
418                 return;
419
420         /* record this node in proximity bitmap */
421         pxm_bit_set(pxm);
422
423         /* Insertion sort based on base address */
424         pend = &node_memblk[num_node_memblks];
425         for (p = &node_memblk[0]; p < pend; p++) {
426                 if (paddr < p->start_paddr)
427                         break;
428         }
429         if (p < pend) {
430                 for (q = pend - 1; q >= p; q--)
431                         *(q + 1) = *q;
432         }
433         p->start_paddr = paddr;
434         p->size = size;
435         p->nid = pxm;
436         num_node_memblks++;
437 }
438
439 void __init
440 acpi_numa_arch_fixup (void)
441 {
442         int i, j, node_from, node_to;
443
444         /* If there's no SRAT, fix the phys_id */
445         if (srat_num_cpus == 0) {
446                 node_cpuid[0].phys_id = hard_smp_processor_id();
447                 return;
448         }
449
450         /* calculate total number of nodes in system from PXM bitmap */
451         numnodes = 0;           /* init total nodes in system */
452
453         memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map));
454         memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map));
455         for (i = 0; i < MAX_PXM_DOMAINS; i++) {
456                 if (pxm_bit_test(i)) {
457                         pxm_to_nid_map[i] = numnodes;
458                         node_set_online(numnodes);
459                         nid_to_pxm_map[numnodes++] = i;
460                 }
461         }
462
463         /* set logical node id in memory chunk structure */
464         for (i = 0; i < num_node_memblks; i++)
465                 node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid];
466
467         /* assign memory bank numbers for each chunk on each node */
468         for (i = 0; i < numnodes; i++) {
469                 int bank;
470
471                 bank = 0;
472                 for (j = 0; j < num_node_memblks; j++)
473                         if (node_memblk[j].nid == i)
474                                 node_memblk[j].bank = bank++;
475         }
476
477         /* set logical node id in cpu structure */
478         for (i = 0; i < srat_num_cpus; i++)
479                 node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid];
480
481         printk(KERN_INFO "Number of logical nodes in system = %d\n", numnodes);
482         printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks);
483
484         if (!slit_table) return;
485         memset(numa_slit, -1, sizeof(numa_slit));
486         for (i=0; i<slit_table->localities; i++) {
487                 if (!pxm_bit_test(i))
488                         continue;
489                 node_from = pxm_to_nid_map[i];
490                 for (j=0; j<slit_table->localities; j++) {
491                         if (!pxm_bit_test(j))
492                                 continue;
493                         node_to = pxm_to_nid_map[j];
494                         node_distance(node_from, node_to) =
495                                 slit_table->entry[i*slit_table->localities + j];
496                 }
497         }
498
499 #ifdef SLIT_DEBUG
500         printk("ACPI 2.0 SLIT locality table:\n");
501         for (i = 0; i < numnodes; i++) {
502                 for (j = 0; j < numnodes; j++)
503                         printk("%03d ", node_distance(i,j));
504                 printk("\n");
505         }
506 #endif
507 }
508 #endif /* CONFIG_ACPI_NUMA */
509
510 unsigned int
511 acpi_register_gsi (u32 gsi, int polarity, int trigger)
512 {
513         return acpi_register_irq(gsi, polarity, trigger);
514 }
515 EXPORT_SYMBOL(acpi_register_gsi);
516
517 static int __init
518 acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
519 {
520         struct acpi_table_header *fadt_header;
521         struct fadt_descriptor_rev2 *fadt;
522
523         if (!phys_addr || !size)
524                 return -EINVAL;
525
526         fadt_header = (struct acpi_table_header *) __va(phys_addr);
527         if (fadt_header->revision != 3)
528                 return -ENODEV;         /* Only deal with ACPI 2.0 FADT */
529
530         fadt = (struct fadt_descriptor_rev2 *) fadt_header;
531
532         if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
533                 acpi_kbd_controller_present = 0;
534
535         if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
536                 acpi_legacy_devices = 1;
537
538         acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
539         return 0;
540 }
541
542
543 unsigned long __init
544 acpi_find_rsdp (void)
545 {
546         unsigned long rsdp_phys = 0;
547
548         if (efi.acpi20)
549                 rsdp_phys = __pa(efi.acpi20);
550         else if (efi.acpi)
551                 printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
552         return rsdp_phys;
553 }
554
555
556 int __init
557 acpi_boot_init (void)
558 {
559
560         /*
561          * MADT
562          * ----
563          * Parse the Multiple APIC Description Table (MADT), if exists.
564          * Note that this table provides platform SMP configuration
565          * information -- the successor to MPS tables.
566          */
567
568         if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) {
569                 printk(KERN_ERR PREFIX "Can't find MADT\n");
570                 goto skip_madt;
571         }
572
573         /* Local APIC */
574
575         if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr, 0) < 0)
576                 printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
577
578         if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic, NR_CPUS) < 1)
579                 printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
580
581         if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi, 0) < 0)
582                 printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
583
584         /* I/O APIC */
585
586         if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic, NR_IOSAPICS) < 1)
587                 printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n");
588
589         /* System-Level Interrupt Routing */
590
591         if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src, ACPI_MAX_PLATFORM_INTERRUPTS) < 0)
592                 printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
593
594         if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr, 0) < 0)
595                 printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
596
597         if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src, 0) < 0)
598                 printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
599   skip_madt:
600
601         /*
602          * FADT says whether a legacy keyboard controller is present.
603          * The FADT also contains an SCI_INT line, by which the system
604          * gets interrupts such as power and sleep buttons.  If it's not
605          * on a Legacy interrupt, it needs to be setup.
606          */
607         if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1)
608                 printk(KERN_ERR PREFIX "Can't find FADT\n");
609
610 #ifdef CONFIG_SMP
611         if (available_cpus == 0) {
612                 printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n");
613                 printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id());
614                 smp_boot_data.cpu_phys_id[available_cpus] = hard_smp_processor_id();
615                 available_cpus = 1; /* We've got at least one of these, no? */
616         }
617         smp_boot_data.cpu_count = available_cpus;
618
619         smp_build_cpu_map();
620 # ifdef CONFIG_ACPI_NUMA
621         if (srat_num_cpus == 0) {
622                 int cpu, i = 1;
623                 for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++)
624                         if (smp_boot_data.cpu_phys_id[cpu] != hard_smp_processor_id())
625                                 node_cpuid[i++].phys_id = smp_boot_data.cpu_phys_id[cpu];
626         }
627         build_cpu_to_node_map();
628 # endif
629 #endif
630         /* Make boot-up look pretty */
631         printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
632         return 0;
633 }
634
635 /* deprecated in favor of acpi_gsi_to_irq */
636 int
637 acpi_irq_to_vector (u32 gsi)
638 {
639         if (has_8259 && gsi < 16)
640                 return isa_irq_to_vector(gsi);
641
642         return gsi_to_vector(gsi);
643 }
644
645 int
646 acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
647 {
648         int vector;
649
650         if (has_8259 && gsi < 16)
651                 *irq = isa_irq_to_vector(gsi);
652         else {
653                 vector = gsi_to_vector(gsi);
654                 if (vector == -1)
655                         return -1;
656
657                 *irq = vector;
658         }
659         return 0;
660 }
661
662 int
663 acpi_register_irq (u32 gsi, u32 polarity, u32 trigger)
664 {
665         if (has_8259 && gsi < 16)
666                 return isa_irq_to_vector(gsi);
667
668         return iosapic_register_intr(gsi,
669                         (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
670                         (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
671 }
672 EXPORT_SYMBOL(acpi_register_irq);
673
674 #endif /* CONFIG_ACPI_BOOT */