Commit c7105e2d authored by James Bottomley's avatar James Bottomley

Split x86 into a generic component and a visws component

parent a925c40f
......@@ -86,13 +86,24 @@ ifdef CONFIG_MCYRIXIII
CFLAGS += -march=i586
endif
ifdef CONFIG_VISWS
MACHINE := visws
else
MACHINE := generic
endif
HEAD := arch/i386/kernel/head.o arch/i386/kernel/init_task.o
SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib
SUBDIRS += arch/i386/kernel arch/i386/mm arch/i386/lib \
arch/i386/$(MACHINE)
CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o \
arch/i386/$(MACHINE)/$(MACHINE).o $(CORE_FILES)
CORE_FILES := arch/i386/kernel/kernel.o arch/i386/mm/mm.o $(CORE_FILES)
LIBS := $(TOPDIR)/arch/i386/lib/lib.a $(LIBS) $(TOPDIR)/arch/i386/lib/lib.a
CFLAGS += -I$(TOPDIR)/arch/i386/$(MACHINE)
ifdef CONFIG_MATH_EMULATION
SUBDIRS += arch/i386/math-emu
DRIVERS += arch/i386/math-emu/math.o
......
......@@ -417,6 +417,14 @@ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
fi
fi
if [ "$CONFIG_X86_LOCAL_APIC" = "y" ]; then
define_bool CONFIG_X86_EXTRA_IRQS y
fi
endmenu
source lib/Config.in
if [ "$CONFIG_SMP" = "y" ]; then
define_bool CONFIG_X86_SMP y
fi
\ No newline at end of file
#
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
.S.o:
$(CC) $(AFLAGS) -traditional -c $< -o $*.o
all: generic.o
O_TARGET := generic.o
EXTRA_CFLAGS += -I../kernel
export-objs :=
obj-y := setup.o
obj-$(CONFIG_PCI) += pci-pc.o pci-irq.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o
include $(TOPDIR)/Rules.make
/* defines for inline arch setup functions */
static inline void do_timer_interrupt_hook(struct pt_regs *regs)
{
do_timer(regs);
/*
* In the SMP case we use the local APIC timer interrupt to do the
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
#ifndef CONFIG_X86_LOCAL_APIC
if (!user_mode(regs))
x86_do_profile(regs->eip);
#else
if (!using_apic_timer)
smp_local_timer_interrupt(regs);
#endif
}
......@@ -67,7 +67,7 @@ unsigned long phys_cpu_present_map;
* Intel MP BIOS table parsing routines:
*/
#ifndef CONFIG_X86_VISWS_APIC
/*
* Checksum an MP configuration block.
*/
......@@ -770,7 +770,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
return 0;
}
void __init find_intel_smp (void)
void __init find_smp_config (void)
{
unsigned int address;
......@@ -808,37 +808,3 @@ void __init find_intel_smp (void)
printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
}
#else
/*
* The Visual Workstation is Intel MP compliant in the hardware
* sense, but it doesnt have a BIOS(-configuration table).
* No problem for Linux.
*/
void __init find_visws_smp(void)
{
smp_found_config = 1;
phys_cpu_present_map |= 2; /* or in id 1 */
apic_version[1] |= 0x10; /* integrated APIC */
apic_version[0] |= 0x10;
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
}
#endif
/*
* - Intel MP Configuration Table
* - or SGI Visual Workstation configuration
*/
void __init find_smp_config (void)
{
#ifdef CONFIG_X86_LOCAL_APIC
find_intel_smp();
#endif
#ifdef CONFIG_VISWS
find_visws_smp();
#endif
}
/*
* Machine specific setup for generic
*/
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/arch_hooks.h>
void __init pre_intr_init_hook(void)
{
init_ISA_irqs();
}
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
void __init intr_init_hook(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
apic_intr_init();
#endif
setup_irq(2, &irq2);
}
void __init pre_setup_arch_hook(void)
{
}
void __init trap_init_hook(void)
{
}
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
void __init time_init_hook(void)
{
setup_irq(0, &irq0);
}
......@@ -21,27 +21,15 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
pci-dma.o i386_ksyms.o i387.o bluesmoke.o dmi_scan.o
ifdef CONFIG_PCI
obj-y += pci-i386.o
ifdef CONFIG_VISWS
obj-y += pci-visws.o
else
obj-y += pci-pc.o pci-irq.o
endif
endif
obj-$(CONFIG_PCI) += pci-i386.o
obj-$(CONFIG_MCA) += mca.o
obj-$(CONFIG_MTRR) += mtrr.o
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o apic.o nmi.o
obj-$(CONFIG_X86_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o acpitable.o
ifdef CONFIG_VISWS
obj-y += setup-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
endif
include $(TOPDIR)/Rules.make
......@@ -29,6 +29,32 @@
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/pgalloc.h>
#include <asm/desc.h>
#include <asm/arch_hooks.h>
/*
* every pentium local APIC has two 'local interrupts', with a
* soft-definable vector attached to both interrupts, one of
* which is a timer interrupt, the other one is error counter
* overflow. Linux uses the local APIC timer interrupt to get
* a much simpler SMP time architecture:
*/
BUILD_SMP_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
void __init apic_intr_init(void)
{
#ifdef CONFIG_SMP
smp_intr_init();
#endif
/* self generated IPI for local APIC timer */
set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
/* IPI vectors for APIC spurious and error interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
}
/* Using APIC to generate smp_local_timer_interrupt? */
int using_apic_timer = 0;
......
......@@ -21,6 +21,7 @@
#include <asm/delay.h>
#include <asm/desc.h>
#include <asm/apic.h>
#include <asm/arch_hooks.h>
#include <linux/irq.h>
......@@ -52,7 +53,7 @@ BUILD_COMMON_IRQ()
*/
BUILD_16_IRQS(0x0)
#ifdef CONFIG_X86_IO_APIC
#ifdef CONFIG_X86_EXTRA_IRQS
/*
* The IO-APIC gives us many more interrupt sources. Most of these
* are unused but an SMP system is supposed to have enough memory ...
......@@ -72,31 +73,6 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd)
#undef BUILD_16_IRQS
#undef BI
/*
* The following vectors are part of the Linux architecture, there
* is no hardware IRQ pin equivalent for them, they are triggered
* through the ICC by us (IPIs)
*/
#ifdef CONFIG_SMP
BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
#endif
/*
* every pentium local APIC has two 'local interrupts', with a
* soft-definable vector attached to both interrupts, one of
* which is a timer interrupt, the other one is error counter
* overflow. Linux uses the local APIC timer interrupt to get
* a much simpler SMP time architecture:
*/
#ifdef CONFIG_X86_LOCAL_APIC
BUILD_SMP_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
#endif
#define IRQ(x,y) \
IRQ##x##y##_interrupt
......@@ -109,7 +85,7 @@ BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
void (*interrupt[NR_IRQS])(void) = {
IRQLIST_16(0x0),
#ifdef CONFIG_X86_IO_APIC
#ifdef CONFIG_X86_EXTRA_IRQS
IRQLIST_16(0x1), IRQLIST_16(0x2), IRQLIST_16(0x3),
IRQLIST_16(0x4), IRQLIST_16(0x5), IRQLIST_16(0x6), IRQLIST_16(0x7),
IRQLIST_16(0x8), IRQLIST_16(0x9), IRQLIST_16(0xa), IRQLIST_16(0xb),
......@@ -403,15 +379,6 @@ static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
*/
static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL };
/*
* IRQ2 is cascade interrupt to second interrupt controller
*/
#ifndef CONFIG_VISWS
static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
#endif
void __init init_ISA_irqs (void)
{
int i;
......@@ -444,11 +411,8 @@ void __init init_IRQ(void)
{
int i;
#ifndef CONFIG_X86_VISWS_APIC
init_ISA_irqs();
#else
init_VISWS_APIC_irqs();
#endif
pre_intr_init_hook();
/*
* Cover the whole vector space, no vector can escape
* us. (some of these will be overridden and become
......@@ -460,34 +424,7 @@ void __init init_IRQ(void)
set_intr_gate(vector, interrupt[i]);
}
#ifdef CONFIG_SMP
/*
* IRQ0 must be given a fixed assignment and initialized,
* because it's used before the IO-APIC is set up.
*/
set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
*/
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
/* IPI for invalidation */
set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
/* self generated IPI for local APIC timer */
set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
/* IPI vectors for APIC spurious and error interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
#endif
intr_init_hook();
/*
* Set the clock to HZ Hz, we already have a valid
......@@ -497,10 +434,6 @@ void __init init_IRQ(void)
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
#ifndef CONFIG_VISWS
setup_irq(2, &irq2);
#endif
/*
* External FPU? Set up irq13 if so, for
* original braindamaged IBM FERR coupling.
......
......@@ -113,6 +113,7 @@
#include <asm/dma.h>
#include <asm/mpspec.h>
#include <asm/mmu_context.h>
#include <asm/arch_hooks.h>
/*
* Machine setup..
......@@ -674,9 +675,7 @@ void __init setup_arch(char **cmdline_p)
unsigned long start_pfn, max_low_pfn;
int i;
#ifdef CONFIG_VISWS
visws_get_board_type_and_rev();
#endif
pre_setup_arch_hook();
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
......
......@@ -48,6 +48,8 @@
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
#include <asm/smpboot.h>
#include <asm/desc.h>
#include <asm/arch_hooks.h>
/* Set if we find a B stepping CPU */
static int smp_b_stepping;
......@@ -1249,3 +1251,35 @@ void __init smp_boot_cpus(void)
smp_done:
zap_low_mappings();
}
extern void (*interrupt[NR_IRQS])(void);
/*
* The following vectors are part of the Linux architecture, there
* is no hardware IRQ pin equivalent for them, they are triggered
* through the ICC by us (IPIs)
*/
BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
void __init smp_intr_init()
{
/*
* IRQ0 must be given a fixed assignment and initialized,
* because it's used before the IO-APIC is set up.
*/
set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
/*
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
*/
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
/* IPI for invalidation */
set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
}
This diff is collapsed.
......@@ -55,8 +55,8 @@
#include <linux/timex.h>
#include <linux/config.h>
#include <asm/fixmap.h>
#include <asm/cobalt.h>
#include <asm/arch_hooks.h>
#include "do_timer.h"
/*
* for x86_do_profile()
......@@ -409,23 +409,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg
}
#endif
#ifdef CONFIG_VISWS
/* Clear the interrupt */
co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
#endif
do_timer(regs);
/*
* In the SMP case we use the local APIC timer interrupt to do the
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
#ifndef CONFIG_X86_LOCAL_APIC
if (!user_mode(regs))
x86_do_profile(regs->eip);
#else
if (!using_apic_timer)
smp_local_timer_interrupt(regs);
#endif
do_timer_interrupt_hook(regs);
/*
* If we have an externally synchronized Linux clock, then update
......@@ -466,7 +450,7 @@ static int use_tsc;
* Time Stamp Counter value at the time of the timer interrupt, so that
* we later on can estimate the time of day more exactly.
*/
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int count;
......@@ -556,8 +540,6 @@ unsigned long get_cmos_time(void)
return mktime(year, mon, day, hour, min, sec);
}
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
/* ------ Calibrate the TSC -------
* Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset().
* Too much 64-bit arithmetic here to do this cleanly in C, and for
......@@ -570,6 +552,7 @@ static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NUL
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
#ifdef CONFIG_X86_TSC
static unsigned long __init calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
......@@ -634,6 +617,7 @@ static unsigned long __init calibrate_tsc(void)
bad_ctc:
return 0;
}
#endif /* CONFIG_X86_TSC */
void __init time_init(void)
{
......@@ -656,6 +640,7 @@ void __init time_init(void)
* to disk; this won't break the kernel, though, 'cuz we're
* smart. See arch/i386/kernel/apm.c.
*/
#ifdef CONFIG_X86_TSC
/*
* Firstly we have to do a CPU check for chips with
* a potentially buggy TSC. At this point we haven't run
......@@ -696,22 +681,7 @@ void __init time_init(void)
}
}
}
#endif /* CONFIG_X86_TSC */
#ifdef CONFIG_VISWS
printk("Starting Cobalt Timer system clock\n");
/* Set the countdown value */
co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
/* Start the timer */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
/* Enable (unmask) the timer interrupt */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
setup_irq(CO_IRQ_TIMER, &irq0);
#else
setup_irq(0, &irq0);
#endif
time_init_hook();
}
......@@ -40,12 +40,7 @@
#include <asm/smp.h>
#include <asm/pgalloc.h>
#ifdef CONFIG_X86_VISWS_APIC
#include <asm/fixmap.h>
#include <asm/cobalt.h>
#include <asm/lithium.h>
#endif
#include <asm/arch_hooks.h>
#include <linux/irq.h>
#include <linux/module.h>
......@@ -877,96 +872,6 @@ void set_ldt_desc(unsigned int n, void *addr, unsigned int size)
_set_tssldt_desc(gdt_table+__LDT(n), (int)addr, ((size << 3)-1), 0x82);
}
#ifdef CONFIG_X86_VISWS_APIC
/*
* On Rev 005 motherboards legacy device interrupt lines are wired directly
* to Lithium from the 307. But the PROM leaves the interrupt type of each
* 307 logical device set appropriate for the 8259. Later we'll actually use
* the 8259, but for now we have to flip the interrupt types to
* level triggered, active lo as required by Lithium.
*/
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
#define VAL 0x2f /* The value to read/write */
static void
superio_outb(int dev, int reg, int val)
{
outb(DEV, REG);
outb(dev, VAL);
outb(reg, REG);
outb(val, VAL);
}
static int __attribute__ ((unused))
superio_inb(int dev, int reg)
{
outb(DEV, REG);
outb(dev, VAL);
outb(reg, REG);
return inb(VAL);
}
#define FLOP 3 /* floppy logical device */
#define PPORT 4 /* parallel logical device */
#define UART5 5 /* uart2 logical device (not wired up) */
#define UART6 6 /* uart1 logical device (THIS is the serial port!) */
#define IDEST 0x70 /* int. destination (which 307 IRQ line) reg. */
#define ITYPE 0x71 /* interrupt type register */
/* interrupt type bits */
#define LEVEL 0x01 /* bit 0, 0 == edge triggered */
#define ACTHI 0x02 /* bit 1, 0 == active lo */
static void
superio_init(void)
{
if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
superio_outb(UART6, IDEST, 0); /* 0 means no intr propagated */
printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
}
}
static void
lithium_init(void)
{
set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
printk("Lithium PCI Bridge A, Bus Number: %d\n",
li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
/* XXX blindly enables all interrupts */
li_pcia_write16(LI_PCI_INTEN, 0xffff);
li_pcib_write16(LI_PCI_INTEN, 0xffff);
}
static void
cobalt_init(void)
{
/*
* On normal SMP PC this is used only with SMP, but we have to
* use it and set it up here to start the Cobalt clock
*/
set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
printk("Local APIC ID %lx\n", apic_read(APIC_ID));
printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
/* Enable Cobalt APIC being careful to NOT change the ID! */
co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
}
#endif
void __init trap_init(void)
{
#ifdef CONFIG_EISA
......@@ -1013,9 +918,5 @@ void __init trap_init(void)
*/
cpu_init();
#ifdef CONFIG_X86_VISWS_APIC
superio_init();
lithium_init();
cobalt_init();
#endif
trap_init_hook();
}
#
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
# removes any old dependencies. DON'T put your own dependencies here
# unless it's something special (ie not a .c file).
#
# Note 2! The CFLAGS definitions are now in the main makefile...
.S.o:
$(CC) $(AFLAGS) -traditional -c $< -o $*.o
all: visws.o
O_TARGET := visws.o
EXTRA_CFLAGS += -I../kernel
export-objs :=
obj-y := setup.o traps.o
obj-$(CONFIG_PCI) += pci-visws.o
obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o
obj-$(CONFIG_X86_LOCAL_APIC) += mpparse.o
include $(TOPDIR)/Rules.make
/* defines for inline arch setup functions */
#include <asm/fixmap.h>
#include <asm/cobalt.h>
static inline void do_timer_interrupt_hook(struct pt_regs *regs)
{
/* Clear the interrupt */
co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
do_timer(regs);
/*
* In the SMP case we use the local APIC timer interrupt to do the
* profiling, except when we simulate SMP mode on a uniprocessor
* system, in that case we have to call the local interrupt handler.
*/
#ifndef CONFIG_X86_LOCAL_APIC
if (!user_mode(regs))
x86_do_profile(regs->eip);
#else
if (!using_apic_timer)
smp_local_timer_interrupt(regs);
#endif
}
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/bootmem.h>
#include <linux/smp_lock.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <asm/smp.h>
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/pgalloc.h>
/* Have we found an MP table */
int smp_found_config;
/*
* Various Linux-internal data structures created from the
* MP-table.
*/
int apic_version [MAX_APICS];
int mp_bus_id_to_type [MAX_MP_BUSSES];
int mp_bus_id_to_node [MAX_MP_BUSSES];
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_current_pci_id;
/* I/O APIC entries */
struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
/* # of MP IRQ source entries */
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
int mp_irq_entries;
int nr_ioapics;
int pic_mode;
unsigned long mp_lapic_addr;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
unsigned int boot_cpu_logical_apicid = -1U;
/* Internal processor count */
static unsigned int num_processors;
/* Bitmask of physically existing CPUs */
unsigned long phys_cpu_present_map;
/*
* The Visual Workstation is Intel MP compliant in the hardware
* sense, but it doesnt have a BIOS(-configuration table).
* No problem for Linux.
*/
void __init find_smp_config(void)
{
smp_found_config = 1;
phys_cpu_present_map |= 2; /* or in id 1 */
apic_version[1] |= 0x10; /* integrated APIC */
apic_version[0] |= 0x10;
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
}
......@@ -3,6 +3,16 @@
* Split out from setup.c by davej@suse.de
*/
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/fixmap.h>
#include <asm/cobalt.h>
#include <asm/arch_hooks.h>
#include <asm/io.h>
char visws_board_type = -1;
char visws_board_rev = -1;
......@@ -122,5 +132,39 @@ void __init visws_get_board_type_and_rev(void)
visws_board_type == VISWS_320 ? "320" :
(visws_board_type == VISWS_540 ? "540" :
"unknown"), visws_board_rev);
}
}
void __init pre_intr_init_hook(void)
{
init_VISWS_APIC_irqs();
}
void __init intr_init_hook(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
apic_intr_init();
#endif
}
void __init pre_setup_arch_hook()
{
visws_get_board_type_and_rev();
}
static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL};
void __init time_init_hook(void)
{
printk("Starting Cobalt Timer system clock\n");
/* Set the countdown value */
co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
/* Start the timer */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
/* Enable (unmask) the timer interrupt */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
setup_irq(CO_IRQ_TIMER, &irq0);
}
/* VISWS traps */
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/debugreg.h>
#include <asm/desc.h>
#include <asm/i387.h>
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/arch_hooks.h>
#ifdef CONFIG_X86_VISWS_APIC
#include <asm/fixmap.h>
#include <asm/cobalt.h>
#include <asm/lithium.h>
#endif
#ifdef CONFIG_X86_VISWS_APIC
/*
* On Rev 005 motherboards legacy device interrupt lines are wired directly
* to Lithium from the 307. But the PROM leaves the interrupt type of each
* 307 logical device set appropriate for the 8259. Later we'll actually use
* the 8259, but for now we have to flip the interrupt types to
* level triggered, active lo as required by Lithium.
*/
#define REG 0x2e /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
#define VAL 0x2f /* The value to read/write */
static void
superio_outb(int dev, int reg, int val)
{
outb(DEV, REG);
outb(dev, VAL);
outb(reg, REG);
outb(val, VAL);
}
static int __attribute__ ((unused))
superio_inb(int dev, int reg)
{
outb(DEV, REG);
outb(dev, VAL);
outb(reg, REG);
return inb(VAL);
}
#define FLOP 3 /* floppy logical device */
#define PPORT 4 /* parallel logical device */
#define UART5 5 /* uart2 logical device (not wired up) */
#define UART6 6 /* uart1 logical device (THIS is the serial port!) */
#define IDEST 0x70 /* int. destination (which 307 IRQ line) reg. */
#define ITYPE 0x71 /* interrupt type register */
/* interrupt type bits */
#define LEVEL 0x01 /* bit 0, 0 == edge triggered */
#define ACTHI 0x02 /* bit 1, 0 == active lo */
static __init void
superio_init(void)
{
if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
superio_outb(UART6, IDEST, 0); /* 0 means no intr propagated */
printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
}
}
static __init void
lithium_init(void)
{
set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
printk("Lithium PCI Bridge A, Bus Number: %d\n",
li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
/* XXX blindly enables all interrupts */
li_pcia_write16(LI_PCI_INTEN, 0xffff);
li_pcib_write16(LI_PCI_INTEN, 0xffff);
}
static __init void
cobalt_init(void)
{
/*
* On normal SMP PC this is used only with SMP, but we have to
* use it and set it up here to start the Cobalt clock
*/
set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
printk("Local APIC ID %lx\n", apic_read(APIC_ID));
printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
/* Enable Cobalt APIC being careful to NOT change the ID! */
co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
}
#endif
void __init trap_init_hook()
{
#ifdef CONFIG_X86_VISWS_APIC
superio_init();
lithium_init();
cobalt_init();
#endif
}
#ifndef _ASM_ARCH_HOOKS_H
#define _ASM_ARCH_HOOKS_H
/*
* linux/include/asm/arch_hooks.h
*
* define the architecture specific hooks
*/
/* these aren't arch hooks, they are generic routines
* that can be used by the hooks */
extern void init_ISA_irqs(void);
extern void apic_intr_init(void);
extern void smp_intr_init(void);
extern void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/* these are the defined hooks */
extern void intr_init_hook(void);
extern void pre_intr_init_hook(void);
extern void pre_setup_arch_hook(void);
extern void trap_init_hook(void);
extern void time_init_hook(void);
#endif
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