patch-2.3.40 linux/arch/i386/kernel/io_apic.c
Next file: linux/arch/i386/kernel/irq.c
Previous file: linux/arch/i386/kernel/i8259.c
Back to the patch index
Back to the overall index
- Lines: 307
- Date:
Thu Jan 20 09:51:42 2000
- Orig file:
v2.3.39/linux/arch/i386/kernel/io_apic.c
- Orig date:
Tue Dec 7 09:32:40 1999
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
@@ -1,7 +1,7 @@
/*
* Intel IO-APIC support for multi-Pentium hosts.
*
- * Copyright (C) 1997, 1998, 1999 Ingo Molnar, Hajnalka Szabo
+ * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
*
* Many thanks to Stig Venaas for trying out countless experimental
* patches and reporting/debugging problems patiently!
@@ -13,105 +13,42 @@
* and Ingo Molnar <mingo@redhat.com>
*/
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/config.h>
+#include <linux/smp_lock.h>
+
#include <asm/io.h>
+#include <asm/smp.h>
#include <asm/desc.h>
-#include <linux/irq.h>
-
-#undef __init
-#define __init
-
-/*
- * volatile is justified in this case, IO-APIC register contents
- * might change spontaneously, GCC should not cache it
- */
-#define IO_APIC_BASE(idx) ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
-
-extern int nmi_watchdog;
-
-/*
- * The structure of the IO-APIC:
- */
-
-struct IO_APIC_reg_00 {
- __u32 __reserved_2 : 24,
- ID : 4,
- __reserved_1 : 4;
-} __attribute__ ((packed));
-
-struct IO_APIC_reg_01 {
- __u32 version : 8,
- __reserved_2 : 8,
- entries : 8,
- __reserved_1 : 8;
-} __attribute__ ((packed));
-
-struct IO_APIC_reg_02 {
- __u32 __reserved_2 : 24,
- arbitration : 4,
- __reserved_1 : 4;
-} __attribute__ ((packed));
-
/*
* # of IO-APICs and # of IRQ routing registers
*/
int nr_ioapics = 0;
int nr_ioapic_registers[MAX_IO_APICS];
-enum ioapic_irq_destination_types {
- dest_Fixed = 0,
- dest_LowestPrio = 1,
- dest_SMI = 2,
- dest__reserved_1 = 3,
- dest_NMI = 4,
- dest_INIT = 5,
- dest__reserved_2 = 6,
- dest_ExtINT = 7
-};
+/* I/O APIC entries */
+struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
-struct IO_APIC_route_entry {
- __u32 vector : 8,
- delivery_mode : 3, /* 000: FIXED
- * 001: lowest prio
- * 111: ExtINT
- */
- dest_mode : 1, /* 0: physical, 1: logical */
- delivery_status : 1,
- polarity : 1,
- irr : 1,
- trigger : 1, /* 0: edge, 1: level */
- mask : 1, /* 0: enabled, 1: disabled */
- __reserved_2 : 15;
-
- union { struct { __u32
- __reserved_1 : 24,
- physical_dest : 4,
- __reserved_2 : 4;
- } physical;
-
- struct { __u32
- __reserved_1 : 24,
- logical_dest : 8;
- } logical;
- } dest;
+/* # of MP IRQ source entries */
+struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-} __attribute__ ((packed));
+/* MP IRQ source entries */
+int mp_irq_entries = 0;
+
+/* non-0 if default (table-less) MP configuration */
+int mpc_default_type = 0;
/*
- * MP-BIOS irq configuration table structures:
+ * Rough estimation of how many shared IRQs there are, can
+ * be changed anytime.
*/
-
-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];/* I/O APIC entries */
-int mp_irq_entries = 0; /* # of MP IRQ source entries */
-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
- /* MP IRQ source entries */
-int mpc_default_type = 0; /* non-0 if default (table-less)
- MP configuration */
-
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
+#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
/*
* This is performance-critical, we want to do it O(1)
@@ -120,43 +57,6 @@
* between pins and IRQs.
*/
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
- *IO_APIC_BASE(apic) = reg;
- return *(IO_APIC_BASE(apic)+4);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
- *IO_APIC_BASE(apic) = reg;
- *(IO_APIC_BASE(apic)+4) = value;
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- */
-static inline void io_apic_modify(unsigned int apic, unsigned int value)
-{
- *(IO_APIC_BASE(apic)+4) = value;
-}
-
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
- (void) *(IO_APIC_BASE(apic)+4);
-}
-
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-#define MAX_PLUS_SHARED_IRQS NR_IRQS
-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
-
static struct irq_pin_list {
int apic, pin, next;
} irq_2_pin[PIN_MAP_SIZE];
@@ -239,6 +139,7 @@
#define MAX_PIRQS 8
int pirq_entries [MAX_PIRQS];
int pirqs_enabled;
+int skip_ioapic_setup = 0;
static int __init ioapic_setup(char *str)
{
@@ -997,7 +898,7 @@
}
}
-static void __init setup_ioapic_id(void)
+static void __init setup_ioapic_default_id(void)
{
struct IO_APIC_reg_00 reg_00;
@@ -1012,7 +913,7 @@
* system must have a unique ID or we get lots of nice
* 'stuck on smp_invalidate_needed IPI wait' messages.
*/
- if (cpu_present_map & (1<<0x2))
+ if (phys_cpu_present_map & (1<<0x2))
panic("APIC ID 2 already used");
/*
@@ -1031,6 +932,47 @@
panic("could not set ID");
}
+/*
+ * function to set the IO-APIC physical IDs based on the
+ * values stored in the MPC table.
+ *
+ * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999
+ */
+
+static void __init setup_ioapic_ids_from_mpc (void)
+{
+ struct IO_APIC_reg_00 reg_00;
+ int apic;
+
+ /*
+ * Set the IOAPIC ID to the value stored in the MPC table.
+ */
+ for (apic = 0; apic < nr_ioapics; apic++) {
+
+ /* Read the register 0 value */
+ *(int *)®_00 = io_apic_read(apic, 0);
+
+ /*
+ * Read the right value from the MPC table and
+ * write it into the ID register.
+ */
+ printk("...changing IO-APIC physical APIC ID to %d ...",
+ mp_ioapics[apic].mpc_apicid);
+
+ reg_00.ID = mp_ioapics[apic].mpc_apicid;
+ io_apic_write(apic, 0, *(int *)®_00);
+
+ /*
+ * Sanity check
+ */
+ *(int *)®_00 = io_apic_read(apic, 0);
+ if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
+ panic("could not set ID!\n");
+ else
+ printk(" ok.\n");
+ }
+}
+
static void __init construct_default_ISA_mptable(void)
{
int i, pos = 0;
@@ -1071,7 +1013,7 @@
mp_irqs[0].mpc_dstirq = 2;
}
- setup_ioapic_id();
+ setup_ioapic_default_id();
}
/*
@@ -1320,6 +1262,8 @@
pin1 = find_timer_pin(mp_INT);
pin2 = find_timer_pin(mp_ExtINT);
+ printk("..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2);
+
/*
* Ok, does IRQ0 through the IOAPIC work?
*/
@@ -1405,8 +1349,8 @@
{
enable_IO_APIC();
- printk("ENABLING IO-APIC IRQs\n");
io_apic_irqs = ~PIC_IRQS;
+ printk("ENABLING IO-APIC IRQs\n");
/*
* If there are no explicit MP IRQ entries, it's either one of the
@@ -1422,8 +1366,25 @@
* Set up the IO-APIC IRQ routing table by parsing the MP-BIOS
* mptable:
*/
+ setup_ioapic_ids_from_mpc();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
check_timer();
print_IO_APIC();
}
+
+#ifndef CONFIG_SMP
+/*
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
+ */
+void IO_APIC_init_uniprocessor (void)
+{
+ if (!smp_found_config)
+ return;
+ phys_cpu_present_map = 0xff;
+ setup_local_APIC();
+ setup_IO_APIC();
+ setup_APIC_clocks();
+}
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)