Commit e19ca5df authored by David Mosberger's avatar David Mosberger

Manual merge with Paul's 2.4.18 ACPI update.

parent 889ac863
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
* 'IA-64 Extensions to ACPI Specification' Revision 0.6 * 'IA-64 Extensions to ACPI Specification' Revision 0.6
* *
* Copyright (C) 1999 VA Linux Systems * Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999, 2000 Walt Drummond <drummond@valinux.com> * Copyright (C) 1999,2000 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2000, 2002 Hewlett-Packard Co. * Copyright (C) 2000 Hewlett-Packard Co.
* David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
* Copyright (C) 2000 Intel Corp. * Copyright (C) 2000 Intel Corp.
* Copyright (C) 2000, 2001 J.I. Lee <jung-ik.lee@intel.com> * Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
* ACPI based kernel configuration manager. * ACPI based kernel configuration manager.
* ACPI 2.0 & IA64 ext 0.71 * ACPI 2.0 & IA64 ext 0.71
*/ */
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/acpi.h>
#ifdef CONFIG_SERIAL_ACPI #ifdef CONFIG_SERIAL_ACPI
#include <linux/acpi_serial.h> #include <linux/acpi_serial.h>
#endif #endif
...@@ -45,8 +44,6 @@ int platform_irq_list[ACPI_MAX_PLATFORM_IRQS]; ...@@ -45,8 +44,6 @@ int platform_irq_list[ACPI_MAX_PLATFORM_IRQS];
int __initdata available_cpus; int __initdata available_cpus;
int __initdata total_cpus; int __initdata total_cpus;
int __initdata pcat_compat;
void (*pm_idle) (void); void (*pm_idle) (void);
void (*pm_power_off) (void); void (*pm_power_off) (void);
...@@ -59,34 +56,9 @@ asm (".weak iosapic_version"); ...@@ -59,34 +56,9 @@ asm (".weak iosapic_version");
const char * const char *
acpi_get_sysname (void) acpi_get_sysname (void)
{ {
/* the following should go away once we have an ACPI parser: */
#ifdef CONFIG_IA64_GENERIC #ifdef CONFIG_IA64_GENERIC
if (efi.acpi20) { return "hpsim";
acpi20_rsdp_t *rsdp20;
acpi_xsdt_t *xsdt;
acpi_desc_table_hdr_t *hdrp;
rsdp20 = efi.acpi20;
if (strncmp(rsdp20->signature,
ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
printk("ACPI 2.0 RSDP signature incorrect, default to DIG compatible\n");
return "dig";
}
xsdt = __va(rsdp20->xsdt);
hdrp = &xsdt->header;
if (strncmp(hdrp->signature,
ACPI_XSDT_SIG, ACPI_XSDT_SIG_LEN)) {
printk("ACPI 2.0 XSDT signature incorrect, default to DIG compatible\n");
return "dig";
}
if (!strcmp(hdrp->oem_id, "HP")) {
printk("Enabling Hewlett Packard zx1 chipset support\n");
return "hpzx1";
}
}
return "dig";
#else #else
# if defined (CONFIG_IA64_HP_SIM) # if defined (CONFIG_IA64_HP_SIM)
return "hpsim"; return "hpsim";
...@@ -94,14 +66,13 @@ acpi_get_sysname (void) ...@@ -94,14 +66,13 @@ acpi_get_sysname (void)
return "sn1"; return "sn1";
# elif defined (CONFIG_IA64_SGI_SN2) # elif defined (CONFIG_IA64_SGI_SN2)
return "sn2"; return "sn2";
# elif defined (CONFIG_IA64_HP_ZX1)
return "hpzx1";
# elif defined (CONFIG_IA64_DIG) # elif defined (CONFIG_IA64_DIG)
return "dig"; return "dig";
# else # else
# error Unknown platform. Fix acpi.c. # error Unknown platform. Fix acpi.c.
# endif # endif
#endif #endif
} }
/* /*
...@@ -322,16 +293,6 @@ acpi20_parse_madt (acpi_madt_t *madt) ...@@ -322,16 +293,6 @@ acpi20_parse_madt (acpi_madt_t *madt)
} else } else
printk("Lapic address set to default 0x%lx\n", ipi_base_addr); printk("Lapic address set to default 0x%lx\n", ipi_base_addr);
/*
* The PCAT_COMPAT flag indicates that the system has a dual-8259 compatible
* setup.
*/
#ifdef CONFIG_ITANIUM
pcat_compat = 1; /* fw on some Itanium systems is broken... */
#else
pcat_compat = (madt->flags & MADT_PCAT_COMPAT);
#endif
p = (char *) (madt + 1); p = (char *) (madt + 1);
end = p + (madt->header.length - sizeof(acpi_madt_t)); end = p + (madt->header.length - sizeof(acpi_madt_t));
...@@ -358,7 +319,17 @@ acpi20_parse_madt (acpi_madt_t *madt) ...@@ -358,7 +319,17 @@ acpi20_parse_madt (acpi_madt_t *madt)
case ACPI20_ENTRY_IO_SAPIC: case ACPI20_ENTRY_IO_SAPIC:
iosapic = (acpi_entry_iosapic_t *) p; iosapic = (acpi_entry_iosapic_t *) p;
if (iosapic_init) if (iosapic_init)
iosapic_init(iosapic->address, iosapic->irq_base, pcat_compat); /*
* The PCAT_COMPAT flag indicates that the system has a
* dual-8259 compatible setup.
*/
iosapic_init(iosapic->address, iosapic->irq_base,
#ifdef CONFIG_ITANIUM
1 /* fw on some Itanium systems is broken... */
#else
(madt->flags & MADT_PCAT_COMPAT)
#endif
);
break; break;
case ACPI20_ENTRY_PLATFORM_INT_SOURCE: case ACPI20_ENTRY_PLATFORM_INT_SOURCE:
...@@ -430,7 +401,7 @@ acpi20_parse (acpi20_rsdp_t *rsdp20) ...@@ -430,7 +401,7 @@ acpi20_parse (acpi20_rsdp_t *rsdp20)
# ifdef CONFIG_ACPI # ifdef CONFIG_ACPI
acpi_xsdt_t *xsdt; acpi_xsdt_t *xsdt;
acpi_desc_table_hdr_t *hdrp; acpi_desc_table_hdr_t *hdrp;
acpi_madt_t *madt = NULL; acpi_madt_t *madt;
int tables, i; int tables, i;
if (strncmp(rsdp20->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) { if (strncmp(rsdp20->signature, ACPI_RSDP_SIG, ACPI_RSDP_SIG_LEN)) {
...@@ -706,74 +677,3 @@ acpi_parse (acpi_rsdp_t *rsdp) ...@@ -706,74 +677,3 @@ acpi_parse (acpi_rsdp_t *rsdp)
# endif /* CONFIG_ACPI */ # endif /* CONFIG_ACPI */
return 1; return 1;
} }
#ifdef CONFIG_ACPI
#include "../drivers/acpi/include/platform/acgcc.h"
#include "../drivers/acpi/include/actypes.h"
#include "../drivers/acpi/include/acexcep.h"
#include "../drivers/acpi/include/acpixf.h"
#include "../drivers/acpi/include/actbl.h"
#include "../drivers/acpi/include/acconfig.h"
#include "../drivers/acpi/include/acmacros.h"
#include "../drivers/acpi/include/aclocal.h"
#include "../drivers/acpi/include/acobject.h"
#include "../drivers/acpi/include/acstruct.h"
#include "../drivers/acpi/include/acnamesp.h"
#include "../drivers/acpi/include/acutils.h"
/**
* acpi_get_crs - Return the current resource settings for a device
* obj: A handle for this device
* buf: A buffer to be populated by this call.
*
* Pass a valid handle, typically obtained by walking the namespace and a
* pointer to an allocated buffer, and this function will fill in the buffer
* with a list of acpi_resource structures.
*/
acpi_status acpi_get_crs(acpi_handle obj, acpi_buffer *buf)
{
acpi_status result;
buf->length = 0;
buf->pointer = NULL;
result = acpi_get_current_resources(obj, buf);
if (result != AE_BUFFER_OVERFLOW)
return result;
buf->pointer = kmalloc(buf->length, GFP_KERNEL);
if (!buf->pointer)
return -ENOMEM;
result = acpi_get_current_resources(obj, buf);
return result;
}
acpi_resource *acpi_get_crs_next(acpi_buffer *buf, int *offset)
{
acpi_resource *res;
if (*offset >= buf->length)
return NULL;
res = buf->pointer + *offset;
*offset += res->length;
return res;
}
acpi_resource_data *acpi_get_crs_type(acpi_buffer *buf, int *offset, int type)
{
for (;;) {
acpi_resource *res = acpi_get_crs_next(buf, offset);
if (!res)
return NULL;
if (res->id == type)
return &res->data;
}
}
void acpi_dispose_crs(acpi_buffer *buf)
{
kfree(buf->pointer);
}
#endif /* CONFIG_ACPI */
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in * 02/01/07 E. Focht <efocht@ess.nec.de> Redirectable interrupt vectors in
* iosapic_set_affinity(), initializations for * iosapic_set_affinity(), initializations for
* /proc/irq/#/smp_affinity * /proc/irq/#/smp_affinity
* 02/04/02 P. Diefenbaugh Cleaned up ACPI PCI IRQ routing.
*/ */
/* /*
* Here is what the interrupt logic between a PCI device and the CPU looks like: * Here is what the interrupt logic between a PCI device and the CPU looks like:
...@@ -56,9 +57,8 @@ ...@@ -56,9 +57,8 @@
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/acpi.h>
#include <asm/acpi-ext.h>
#include <asm/acpikcfg.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/io.h> #include <asm/io.h>
...@@ -92,11 +92,37 @@ static struct iosapic_irq { ...@@ -92,11 +92,37 @@ static struct iosapic_irq {
unsigned char trigger : 1; /* trigger mode (see iosapic.h) */ unsigned char trigger : 1; /* trigger mode (see iosapic.h) */
} iosapic_irq[IA64_NUM_VECTORS]; } iosapic_irq[IA64_NUM_VECTORS];
static struct iosapic {
char *addr; /* base address of IOSAPIC */
unsigned char pcat_compat; /* 8259 compatibility flag */
unsigned char base_irq; /* first irq assigned to this IOSAPIC */
unsigned short max_pin; /* max input pin supported in this IOSAPIC */
} iosapic_lists[256] __initdata;
static int num_iosapic = 0;
/*
* Find an IOSAPIC associated with an IRQ
*/
static inline int __init
find_iosapic (unsigned int irq)
{
int i;
for (i = 0; i < num_iosapic; i++) {
if ((irq - iosapic_lists[i].base_irq) < iosapic_lists[i].max_pin)
return i;
}
return -1;
}
/* /*
* Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no * Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no
* entry exists, return -1. * entry exists, return -1.
*/ */
int static int
iosapic_irq_to_vector (int irq) iosapic_irq_to_vector (int irq)
{ {
int vector; int vector;
...@@ -479,7 +505,7 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector, ...@@ -479,7 +505,7 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector,
int vector; int vector;
switch (int_type) { switch (int_type) {
case ACPI20_ENTRY_PIS_PMI: case ACPI_INTERRUPT_PMI:
vector = iosapic_vector; vector = iosapic_vector;
/* /*
* since PMI vector is alloc'd by FW(ACPI) not by kernel, * since PMI vector is alloc'd by FW(ACPI) not by kernel,
...@@ -488,14 +514,14 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector, ...@@ -488,14 +514,14 @@ iosapic_register_platform_irq (u32 int_type, u32 global_vector,
iosapic_reassign_vector(vector); iosapic_reassign_vector(vector);
delivery = IOSAPIC_PMI; delivery = IOSAPIC_PMI;
break; break;
case ACPI20_ENTRY_PIS_CPEI: case ACPI_INTERRUPT_INIT:
vector = IA64_PCE_VECTOR;
delivery = IOSAPIC_LOWEST_PRIORITY;
break;
case ACPI20_ENTRY_PIS_INIT:
vector = ia64_alloc_irq(); vector = ia64_alloc_irq();
delivery = IOSAPIC_INIT; delivery = IOSAPIC_INIT;
break; break;
case ACPI_INTERRUPT_CPEI:
vector = IA64_PCE_VECTOR;
delivery = IOSAPIC_LOWEST_PRIORITY;
break;
default: default:
printk("iosapic_register_platform_irq(): invalid int type\n"); printk("iosapic_register_platform_irq(): invalid int type\n");
return -1; return -1;
...@@ -542,31 +568,41 @@ iosapic_register_legacy_irq (unsigned long irq, ...@@ -542,31 +568,41 @@ iosapic_register_legacy_irq (unsigned long irq,
void __init void __init
iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat) iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat)
{ {
int i, irq, max_pin, vector, pin; int irq, max_pin, vector, pin;
unsigned int ver; unsigned int ver;
char *addr; char *addr;
static int first_time = 1; static int first_time = 1;
if (first_time) { if (first_time) {
first_time = 0; first_time = 0;
for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) for (vector = 0; vector < IA64_NUM_VECTORS; ++vector)
iosapic_irq[vector].pin = -1; /* mark as unused */ iosapic_irq[vector].pin = -1; /* mark as unused */
}
if (pcat_compat) {
/* /*
* Fetch the PCI interrupt routing table: * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
* enabled.
*/ */
acpi_cf_get_pci_vectors(&pci_irq.route, &pci_irq.num_routes); printk("%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);
outb(0xff, 0xA1);
outb(0xff, 0x21);
} }
addr = ioremap(phys_addr, 0); addr = ioremap(phys_addr, 0);
ver = iosapic_version(addr); ver = iosapic_version(addr);
max_pin = (ver >> 16) & 0xff; max_pin = (ver >> 16) & 0xff;
iosapic_lists[num_iosapic].addr = addr;
iosapic_lists[num_iosapic].pcat_compat = pcat_compat;
iosapic_lists[num_iosapic].base_irq = base_irq;
iosapic_lists[num_iosapic].max_pin = max_pin;
num_iosapic++;
printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n", printk("IOSAPIC: version %x.%x, address 0x%lx, IRQs 0x%02x-0x%02x\n",
(ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin); (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, base_irq, base_irq + max_pin);
if ((base_irq == 0) && pcat_compat) if ((base_irq == 0) && pcat_compat) {
/* /*
* Map the legacy ISA devices into the IOSAPIC data. Some of these may * Map the legacy ISA devices into the IOSAPIC data. Some of these may
* get reprogrammed later on with data from the ACPI Interrupt Source * get reprogrammed later on with data from the ACPI Interrupt Source
...@@ -590,11 +626,37 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat) ...@@ -590,11 +626,37 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat)
/* program the IOSAPIC routing table: */ /* program the IOSAPIC routing table: */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff); set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
} }
}
}
void __init
iosapic_init_pci_irq (void)
{
int i, index, vector, pin;
int base_irq, max_pin, pcat_compat;
unsigned int irq;
char *addr;
if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes))
return;
for (i = 0; i < pci_irq.num_routes; i++) { for (i = 0; i < pci_irq.num_routes; i++) {
irq = pci_irq.route[i].irq; irq = pci_irq.route[i].irq;
if ((irq < (int)base_irq) || (irq > (int)(base_irq + max_pin))) index = find_iosapic(irq);
if (index < 0) {
printk("PCI: IRQ %u has no IOSAPIC mapping\n", irq);
continue;
}
addr = iosapic_lists[index].addr;
base_irq = iosapic_lists[index].base_irq;
max_pin = iosapic_lists[index].max_pin;
pcat_compat = iosapic_lists[index].pcat_compat;
pin = irq - base_irq;
if ((unsigned) pin > max_pin)
/* the interrupt route is for another controller... */ /* the interrupt route is for another controller... */
continue; continue;
...@@ -607,18 +669,13 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat) ...@@ -607,18 +669,13 @@ iosapic_init (unsigned long phys_addr, unsigned int base_irq, int pcat_compat)
vector = ia64_alloc_irq(); vector = ia64_alloc_irq();
} }
register_irq(irq, vector, irq - base_irq, register_irq(irq, vector, pin, IOSAPIC_LOWEST_PRIORITY, 0, 0, base_irq, addr);
/* IOSAPIC_POL_LOW, IOSAPIC_LEVEL */
IOSAPIC_LOWEST_PRIORITY, 0, 0, base_irq, addr);
# ifdef DEBUG_IRQ_ROUTING #ifdef DEBUG_IRQ_ROUTING
printk("PCI: (B%d,I%d,P%d) -> IOSAPIC irq 0x%02x -> vector 0x%02x\n", printk("PCI: (B%d,I%d,P%d) -> IOSAPIC irq 0x%02x -> vector 0x%02x\n",
pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin, pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin,
iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector); iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
# endif #endif
/* program the IOSAPIC routing table: */
set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
} }
} }
...@@ -631,6 +688,11 @@ iosapic_pci_fixup (int phase) ...@@ -631,6 +688,11 @@ iosapic_pci_fixup (int phase)
struct hw_interrupt_type *irq_type; struct hw_interrupt_type *irq_type;
irq_desc_t *idesc; irq_desc_t *idesc;
if (phase == 0) {
iosapic_init_pci_irq();
return;
}
if (phase != 1) if (phase != 1)
return; return;
...@@ -670,10 +732,10 @@ iosapic_pci_fixup (int phase) ...@@ -670,10 +732,10 @@ iosapic_pci_fixup (int phase)
irq_type = &irq_type_iosapic_level; irq_type = &irq_type_iosapic_level;
idesc = irq_desc(vector); idesc = irq_desc(vector);
if (idesc->handler != irq_type){ if (idesc->handler != irq_type) {
if (idesc->handler != &no_irq_type) if (idesc->handler != &no_irq_type)
printk("iosapic_pci_fixup: changing vector 0x%02x from " printk("iosapic_pci_fixup: changing vector 0x%02x "
"%s to %s\n", vector, "from %s to %s\n", vector,
idesc->handler->typename, idesc->handler->typename,
irq_type->typename); irq_type->typename);
idesc->handler = irq_type; idesc->handler = irq_type;
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/acpi.h>
#include <asm/machvec.h> #include <asm/machvec.h>
#include <asm/page.h> #include <asm/page.h>
...@@ -51,7 +52,6 @@ ...@@ -51,7 +52,6 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/acpi-ext.h>
#undef MCA_PRT_XTRA_DATA #undef MCA_PRT_XTRA_DATA
...@@ -497,7 +497,7 @@ ia64_mca_init(void) ...@@ -497,7 +497,7 @@ ia64_mca_init(void)
{ {
irq_desc_t *desc; irq_desc_t *desc;
unsigned int irq; unsigned int irq;
int cpev = acpi_request_vector(ACPI20_ENTRY_PIS_CPEI); int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI);
if (cpev >= 0) { if (cpev >= 0) {
for (irq = 0; irq < NR_IRQS; ++irq) for (irq = 0; irq < NR_IRQS; ++irq)
......
...@@ -42,101 +42,183 @@ ...@@ -42,101 +42,183 @@
extern void ia64_mca_check_errors( void ); extern void ia64_mca_check_errors( void );
#endif #endif
struct pci_fixup pcibios_fixups[];
struct pci_ops *pci_root_ops;
int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
/* /*
* This interrupt-safe spinlock protects all accesses to PCI * Low-level SAL-based PCI configuration access functions. Note that SAL
* configuration space. * calls are already serialized (via sal_lock), so we don't need another
* synchronization mechanism here. Not using segment number (yet).
*/ */
static spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
struct pci_fixup pcibios_fixups[] = { #define PCI_SAL_ADDRESS(bus, dev, fn, reg) \
{ 0 } ((u64)(bus << 16) | (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg))
};
/* Macro to build a PCI configuration address to be passed as a parameter to SAL. */ static int
pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value)
{
int result = 0;
u64 data = 0;
#define PCI_CONFIG_ADDRESS(dev, where) \ if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
(((u64) dev->bus->number << 16) | ((u64) (dev->devfn & 0xff) << 8) | (where & 0xff)) return -EINVAL;
result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, &data);
*value = (u32) data;
return result;
}
static int static int
pci_conf_read_config_byte(struct pci_dev *dev, int where, u8 *value) pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value)
{ {
s64 status; if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255))
u64 lval; return -EINVAL;
status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 1, &lval); return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(bus, dev, fn, reg), len, value);
*value = lval;
return status;
} }
static int static int
pci_conf_read_config_word(struct pci_dev *dev, int where, u16 *value) pci_sal_read_config_byte (struct pci_dev *dev, int where, u8 *value)
{ {
s64 status; int result = 0;
u64 lval; u32 data = 0;
if (!value)
return -EINVAL;
result = pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 1, &data);
status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 2, &lval); *value = (u8) data;
*value = lval;
return status; return result;
} }
static int static int
pci_conf_read_config_dword(struct pci_dev *dev, int where, u32 *value) pci_sal_read_config_word (struct pci_dev *dev, int where, u16 *value)
{ {
s64 status; int result = 0;
u64 lval; u32 data = 0;
if (!value)
return -EINVAL;
status = ia64_sal_pci_config_read(PCI_CONFIG_ADDRESS(dev, where), 4, &lval); result = pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
*value = lval; PCI_FUNC(dev->devfn), where, 2, &data);
return status;
*value = (u16) data;
return result;
} }
static int static int
pci_conf_write_config_byte (struct pci_dev *dev, int where, u8 value) pci_sal_read_config_dword (struct pci_dev *dev, int where, u32 *value)
{ {
return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 1, value); if (!value)
return -EINVAL;
return pci_sal_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 4, value);
} }
static int static int
pci_conf_write_config_word (struct pci_dev *dev, int where, u16 value) pci_sal_write_config_byte (struct pci_dev *dev, int where, u8 value)
{ {
return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 2, value); return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 1, value);
} }
static int static int
pci_conf_write_config_dword (struct pci_dev *dev, int where, u32 value) pci_sal_write_config_word (struct pci_dev *dev, int where, u16 value)
{ {
return ia64_sal_pci_config_write(PCI_CONFIG_ADDRESS(dev, where), 4, value); return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), where, 2, value);
} }
struct pci_ops pci_conf = { static int
pci_conf_read_config_byte, pci_sal_write_config_dword (struct pci_dev *dev, int where, u32 value)
pci_conf_read_config_word, {
pci_conf_read_config_dword, return pci_sal_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
pci_conf_write_config_byte, PCI_FUNC(dev->devfn), where, 4, value);
pci_conf_write_config_word, }
pci_conf_write_config_dword
struct pci_ops pci_sal_ops = {
pci_sal_read_config_byte,
pci_sal_read_config_word,
pci_sal_read_config_dword,
pci_sal_write_config_byte,
pci_sal_write_config_word,
pci_sal_write_config_dword
}; };
/* /*
* Initialization. Uses the SAL interface * Initialization. Uses the SAL interface
*/ */
struct pci_bus *
pcibios_scan_root(int seg, int bus)
{
struct list_head *list = NULL;
struct pci_bus *pci_bus = NULL;
list_for_each(list, &pci_root_buses) {
pci_bus = pci_bus_b(list);
if (pci_bus->number == bus) {
/* Already scanned */
printk("PCI: Bus (%02x:%02x) already probed\n", seg, bus);
return pci_bus;
}
}
printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
return pci_scan_bus(bus, pci_root_ops, NULL);
}
void __init
pcibios_config_init (void)
{
if (pci_root_ops)
return;
printk("PCI: Using SAL to access configuration space\n");
pci_root_ops = &pci_sal_ops;
pci_config_read = pci_sal_read;
pci_config_write = pci_sal_write;
return;
}
void __init void __init
pcibios_init (void) pcibios_init (void)
{ {
# define PCI_BUSES_TO_SCAN 255 # define PCI_BUSES_TO_SCAN 255
int i; int i = 0;
#ifdef CONFIG_IA64_MCA #ifdef CONFIG_IA64_MCA
ia64_mca_check_errors(); /* For post-failure MCA error logging */ ia64_mca_check_errors(); /* For post-failure MCA error logging */
#endif #endif
platform_pci_fixup(0); /* phase 0 initialization (before PCI bus has been scanned) */ pcibios_config_init();
platform_pci_fixup(0); /* phase 0 fixups (before buses scanned) */
printk("PCI: Probing PCI hardware\n"); printk("PCI: Probing PCI hardware\n");
for (i = 0; i < PCI_BUSES_TO_SCAN; i++) for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
pci_scan_bus(i, &pci_conf, NULL); pci_scan_bus(i, pci_root_ops, NULL);
platform_pci_fixup(1); /* phase 1 fixups (after buses scanned) */
platform_pci_fixup(1); /* phase 1 initialization (after PCI bus has been scanned) */
return; return;
} }
...@@ -186,7 +268,14 @@ pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * r ...@@ -186,7 +268,14 @@ pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * r
int int
pcibios_enable_device (struct pci_dev *dev) pcibios_enable_device (struct pci_dev *dev)
{ {
if (!dev)
return -EINVAL;
/* Not needed, since we enable all devices at startup. */ /* Not needed, since we enable all devices at startup. */
printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq,
dev->slot_name);
return 0; return 0;
} }
...@@ -233,8 +322,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma, ...@@ -233,8 +322,7 @@ pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT, if (remap_page_range(vma, vma->vm_start, vma->vm_pgoff << PAGE_SHIFT,
vma->vm_end - vma->vm_start, vma->vm_end - vma->vm_start, vma->vm_page_prot))
vma->vm_page_prot))
return -EAGAIN; return -EAGAIN;
return 0; return 0;
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/console.h> #include <linux/console.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -30,7 +31,6 @@ ...@@ -30,7 +31,6 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <asm/acpi-ext.h>
#include <asm/ia32.h> #include <asm/ia32.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/machvec.h> #include <asm/machvec.h>
...@@ -317,13 +317,12 @@ setup_arch (char **cmdline_p) ...@@ -317,13 +317,12 @@ setup_arch (char **cmdline_p)
#endif #endif
/* /*
* Set `iobase' to the appropriate address in region 6 * Set `iobase' to the appropriate address in region 6 (uncached access range).
* (uncached access range)
* *
* The EFI memory map is the "prefered" location to get the I/O port * The EFI memory map is the "preferred" location to get the I/O port space base,
* space base, rather the relying on AR.KR0. This should become more * rather the relying on AR.KR0. This should become more clear in future SAL
* clear in future SAL specs. We'll fall back to getting it out of * specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
* AR.KR0 if no appropriate entry is found in the memory map. * found in the memory map.
*/ */
phys_iobase = efi_get_iobase(); phys_iobase = efi_get_iobase();
if (phys_iobase) if (phys_iobase)
...@@ -342,14 +341,9 @@ setup_arch (char **cmdline_p) ...@@ -342,14 +341,9 @@ setup_arch (char **cmdline_p)
cpu_init(); /* initialize the bootstrap CPU */ cpu_init(); /* initialize the bootstrap CPU */
if (efi.acpi20) { #ifdef CONFIG_ACPI_BOOT
/* Parse the ACPI 2.0 tables */ acpi_boot_init(*cmdline_p);
acpi20_parse(efi.acpi20); #endif
} else if (efi.acpi) {
/* Parse the ACPI tables */
acpi_parse(efi.acpi);
}
#ifdef CONFIG_VT #ifdef CONFIG_VT
# if defined(CONFIG_DUMMY_CONSOLE) # if defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con; conswitchp = &dummy_con;
......
#ifndef _ASM_IA64_ACPI_EXT_H
#define _ASM_IA64_ACPI_EXT_H
/*
* Advanced Configuration and Power Infterface
* Based on 'ACPI Specification 1.0b' Febryary 2, 1999
* and 'IA-64 Extensions to the ACPI Specification' Rev 0.6
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2000 Intel Corp.
* Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
* ACPI 2.0 specification
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/mm.h>
#pragma pack(1)
#define ACPI_RSDP_SIG "RSD PTR " /* Trailing space required */
#define ACPI_RSDP_SIG_LEN 8
typedef struct {
char signature[8];
u8 checksum;
char oem_id[6];
u8 revision;
u32 rsdt;
u32 length;
struct acpi_xsdt *xsdt;
u8 ext_checksum;
u8 reserved[3];
} acpi20_rsdp_t;
typedef struct {
char signature[4];
u32 length;
u8 revision;
u8 checksum;
char oem_id[6];
char oem_table_id[8];
u32 oem_revision;
u32 creator_id;
u32 creator_revision;
} acpi_desc_table_hdr_t;
#define ACPI_RSDT_SIG "RSDT"
#define ACPI_RSDT_SIG_LEN 4
typedef struct {
acpi_desc_table_hdr_t header;
u8 reserved[4];
u32 entry_ptrs[1]; /* Not really . . . */
} acpi20_rsdt_t;
#define ACPI_XSDT_SIG "XSDT"
#define ACPI_XSDT_SIG_LEN 4
typedef struct acpi_xsdt {
acpi_desc_table_hdr_t header;
unsigned long entry_ptrs[1]; /* Not really . . . */
} acpi_xsdt_t;
/* Common structures for ACPI 2.0 and 0.71 */
typedef struct acpi_entry_iosapic {
u8 type;
u8 length;
u8 id;
u8 reserved;
u32 irq_base; /* start of IRQ's this IOSAPIC is responsible for. */
unsigned long address; /* Address of this IOSAPIC */
} acpi_entry_iosapic_t;
/* Local SAPIC flags */
#define LSAPIC_ENABLED (1<<0)
#define LSAPIC_PERFORMANCE_RESTRICTED (1<<1)
#define LSAPIC_PRESENT (1<<2)
/* Defines legacy IRQ->pin mapping */
typedef struct {
u8 type;
u8 length;
u8 bus; /* Constant 0 == ISA */
u8 isa_irq; /* ISA IRQ # */
u32 pin; /* called vector in spec; really IOSAPIC pin number */
u16 flags; /* Edge/Level trigger & High/Low active */
} acpi_entry_int_override_t;
#define INT_OVERRIDE_ACTIVE_LOW 0x03
#define INT_OVERRIDE_LEVEL_TRIGGER 0x0d
/* IA64 ext 0.71 */
typedef struct {
char signature[8];
u8 checksum;
char oem_id[6];
char reserved; /* Must be 0 */
struct acpi_rsdt *rsdt;
} acpi_rsdp_t;
typedef struct acpi_rsdt {
acpi_desc_table_hdr_t header;
u8 reserved[4];
unsigned long entry_ptrs[1]; /* Not really . . . */
} acpi_rsdt_t;
#define ACPI_SAPIC_SIG "SPIC"
#define ACPI_SAPIC_SIG_LEN 4
typedef struct {
acpi_desc_table_hdr_t header;
u8 reserved[4];
unsigned long interrupt_block;
} acpi_sapic_t;
/* SAPIC structure types */
#define ACPI_ENTRY_LOCAL_SAPIC 0
#define ACPI_ENTRY_IO_SAPIC 1
#define ACPI_ENTRY_INT_SRC_OVERRIDE 2
#define ACPI_ENTRY_PLATFORM_INT_SOURCE 3 /* Unimplemented */
typedef struct acpi_entry_lsapic {
u8 type;
u8 length;
u16 acpi_processor_id;
u16 flags;
u8 id;
u8 eid;
} acpi_entry_lsapic_t;
typedef struct {
u8 type;
u8 length;
u16 flags;
u8 int_type;
u8 id;
u8 eid;
u8 iosapic_vector;
u8 reserved[4];
u32 global_vector;
} acpi_entry_platform_src_t;
/* ACPI 2.0 with 1.3 errata specific structures */
#define ACPI_MADT_SIG "APIC"
#define ACPI_MADT_SIG_LEN 4
typedef struct {
acpi_desc_table_hdr_t header;
u32 lapic_address;
u32 flags;
} acpi_madt_t;
/* acpi 2.0 MADT flags */
#define MADT_PCAT_COMPAT (1<<0)
/* acpi 2.0 MADT structure types */
#define ACPI20_ENTRY_LOCAL_APIC 0
#define ACPI20_ENTRY_IO_APIC 1
#define ACPI20_ENTRY_INT_SRC_OVERRIDE 2
#define ACPI20_ENTRY_NMI_SOURCE 3
#define ACPI20_ENTRY_LOCAL_APIC_NMI 4
#define ACPI20_ENTRY_LOCAL_APIC_ADDR_OVERRIDE 5
#define ACPI20_ENTRY_IO_SAPIC 6
#define ACPI20_ENTRY_LOCAL_SAPIC 7
#define ACPI20_ENTRY_PLATFORM_INT_SOURCE 8
typedef struct acpi20_entry_lsapic {
u8 type;
u8 length;
u8 acpi_processor_id;
u8 id;
u8 eid;
u8 reserved[3];
u32 flags;
} acpi20_entry_lsapic_t;
typedef struct acpi20_entry_lapic_addr_override {
u8 type;
u8 length;
u8 reserved[2];
unsigned long lapic_address;
} acpi20_entry_lapic_addr_override_t;
typedef struct {
u8 type;
u8 length;
u16 flags;
u8 int_type;
u8 id;
u8 eid;
u8 iosapic_vector;
u32 global_vector;
} acpi20_entry_platform_src_t;
/* constants for interrupt routing API for device drivers */
#define ACPI20_ENTRY_PIS_PMI 1
#define ACPI20_ENTRY_PIS_INIT 2
#define ACPI20_ENTRY_PIS_CPEI 3
#define ACPI_MAX_PLATFORM_IRQS 4
#define ACPI_SPCRT_SIG "SPCR"
#define ACPI_SPCRT_SIG_LEN 4
#define ACPI_DBGPT_SIG "DBGP"
#define ACPI_DBGPT_SIG_LEN 4
extern int acpi20_parse(acpi20_rsdp_t *);
extern int acpi20_early_parse(acpi20_rsdp_t *);
extern int acpi_parse(acpi_rsdp_t *);
extern const char *acpi_get_sysname (void);
extern int acpi_request_vector(u32 int_type);
extern void (*acpi_idle) (void); /* power-management idle function, if any */
#ifdef CONFIG_NUMA
extern cnodeid_t paddr_to_nid(unsigned long paddr);
#endif
/*
* ACPI 2.0 SRAT Table
* http://www.microsoft.com/HWDEV/design/SRAT.htm
*/
typedef struct acpi_srat {
acpi_desc_table_hdr_t header;
u32 table_revision;
u64 reserved;
} acpi_srat_t;
typedef struct srat_cpu_affinity {
u8 type;
u8 length;
u8 proximity_domain;
u8 apic_id;
u32 flags;
u8 local_sapic_eid;
u8 reserved[7];
} srat_cpu_affinity_t;
typedef struct srat_memory_affinity {
u8 type;
u8 length;
u8 proximity_domain;
u8 reserved[5];
u32 base_addr_lo;
u32 base_addr_hi;
u32 length_lo;
u32 length_hi;
u32 memory_type;
u32 flags;
u64 reserved2;
} srat_memory_affinity_t;
/* ACPI 2.0 SRAT structure */
#define ACPI_SRAT_SIG "SRAT"
#define ACPI_SRAT_SIG_LEN 4
#define ACPI_SRAT_REVISION 1
#define SRAT_CPU_STRUCTURE 0
#define SRAT_MEMORY_STRUCTURE 1
/* Only 1 flag for cpu affinity structure! */
#define SRAT_CPU_FLAGS_ENABLED 0x00000001
#define SRAT_MEMORY_FLAGS_ENABLED 0x00000001
#define SRAT_MEMORY_FLAGS_HOTREMOVABLE 0x00000002
/* ACPI 2.0 address range types */
#define ACPI_ADDRESS_RANGE_MEMORY 1
#define ACPI_ADDRESS_RANGE_RESERVED 2
#define ACPI_ADDRESS_RANGE_ACPI 3
#define ACPI_ADDRESS_RANGE_NVS 4
#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */
#define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */
#define MAX_PXM_DOMAINS (256)
#ifdef CONFIG_DISCONTIGMEM
/*
* List of node memory chunks. Filled when parsing SRAT table to
* obtain information about memory nodes.
*/
struct node_memory_chunk_s {
unsigned long start_paddr;
unsigned long size;
int pxm; // proximity domain of node
int nid; // which cnode contains this chunk?
int bank; // which mem bank on this node
};
extern struct node_memory_chunk_s node_memory_chunk[PLAT_MAXCLUMPS]; // temporary?
struct node_cpuid_s {
u16 phys_id; /* id << 8 | eid */
int pxm; // proximity domain of cpu
int nid;
};
extern struct node_cpuid_s node_cpuid[NR_CPUS];
extern int pxm_to_nid_map[MAX_PXM_DOMAINS]; /* _PXM to logical node ID map */
extern int nid_to_pxm_map[PLAT_MAX_COMPACT_NODES]; /* logical node ID to _PXM map */
extern int numnodes; /* total number of nodes in system */
extern int num_memory_chunks; /* total number of memory chunks */
/*
* ACPI 2.0 SLIT Table
* http://devresource.hp.com/devresource/Docs/TechPapers/IA64/slit.pdf
*/
typedef struct acpi_slit {
acpi_desc_table_hdr_t header;
u64 localities;
u8 entries[1]; /* dummy, real size = locality^2 */
} acpi_slit_t;
extern u8 acpi20_slit[PLAT_MAX_COMPACT_NODES * PLAT_MAX_COMPACT_NODES];
#define ACPI_SLIT_SIG "SLIT"
#define ACPI_SLIT_SIG_LEN 4
#define ACPI_SLIT_REVISION 1
#define ACPI_SLIT_LOCAL 10
#endif /* CONFIG_DISCONTIGMEM */
#pragma pack()
#endif /* _ASM_IA64_ACPI_EXT_H */
/*
* asm-ia64/acpi.h
*
* Copyright (C) 1999 VA Linux Systems
* Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
* Copyright (C) 2000,2001 J.I. Lee <jung-ik.lee@intel.com>
* Copyright (C) 2001,2002 Paul Diefenbaugh <paul.s.diefenbaugh@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
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef _ASM_ACPI_H
#define _ASM_ACPI_H
#ifdef __KERNEL__
#define __acpi_map_table(phys_addr, size) __va(phys_addr)
int acpi_boot_init (char *cdline);
int acpi_find_rsdp (unsigned long *phys_addr);
int acpi_request_vector (u32 int_type);
int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
int acpi_get_interrupt_model(int *type);
#ifdef CONFIG_DISCONTIGMEM
#define NODE_ARRAY_INDEX(x) ((x) / 8) /* 8 bits/char */
#define NODE_ARRAY_OFFSET(x) ((x) % 8) /* 8 bits/char */
#define MAX_PXM_DOMAINS (256)
#endif /* CONFIG_DISCONTIGMEM */
#endif /*__KERNEL__*/
#endif /*_ASM_ACPI_H*/
#ifndef _ASM_IA64_ACPIKCFG_H
#define _ASM_IA64_ACPIKCFG_H
/*
* acpikcfg.h - ACPI based Kernel Configuration Manager External Interfaces
*
* Copyright (C) 2000 Intel Corp.
* Copyright (C) 2000 J.I. Lee <jung-ik.lee@intel.com>
*/
u32 __init acpi_cf_init (void * rsdp);
u32 __init acpi_cf_terminate (void );
u32 __init
acpi_cf_get_pci_vectors (
struct pci_vector_struct **vectors,
int *num_pci_vectors
);
#ifdef CONFIG_ACPI_KERNEL_CONFIG_DEBUG
void __init
acpi_cf_print_pci_vectors (
struct pci_vector_struct *vectors,
int num_pci_vectors
);
#endif
#endif /* _ASM_IA64_ACPIKCFG_H */
...@@ -20,6 +20,11 @@ ...@@ -20,6 +20,11 @@
#define PCIBIOS_MIN_IO 0x1000 #define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
void pcibios_config_init(void);
struct pci_bus * pcibios_scan_root(int seg, int bus);
extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
struct pci_dev; struct pci_dev;
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment