| /* |
| * Machine specific setup for generic |
| */ |
| |
| #include <linux/smp.h> |
| #include <linux/init.h> |
| #include <linux/interrupt.h> |
| #include <asm/acpi.h> |
| #include <asm/arch_hooks.h> |
| #include <asm/e820.h> |
| #include <asm/setup.h> |
| |
| #ifdef CONFIG_HOTPLUG_CPU |
| #define DEFAULT_SEND_IPI (1) |
| #else |
| #define DEFAULT_SEND_IPI (0) |
| #endif |
| |
| int no_broadcast=DEFAULT_SEND_IPI; |
| |
| /** |
| * pre_intr_init_hook - initialisation prior to setting up interrupt vectors |
| * |
| * Description: |
| * Perform any necessary interrupt initialisation prior to setting up |
| * the "ordinary" interrupt call gates. For legacy reasons, the ISA |
| * interrupts should be initialised here if the machine emulates a PC |
| * in any way. |
| **/ |
| void __init pre_intr_init_hook(void) |
| { |
| init_ISA_irqs(); |
| } |
| |
| /* |
| * IRQ2 is cascade interrupt to second interrupt controller |
| */ |
| static struct irqaction irq2 = { |
| .handler = no_action, |
| .mask = CPU_MASK_NONE, |
| .name = "cascade", |
| }; |
| |
| /** |
| * intr_init_hook - post gate setup interrupt initialisation |
| * |
| * Description: |
| * Fill in any interrupts that may have been left out by the general |
| * init_IRQ() routine. interrupts having to do with the machine rather |
| * than the devices on the I/O bus (like APIC interrupts in intel MP |
| * systems) are started here. |
| **/ |
| void __init intr_init_hook(void) |
| { |
| #ifdef CONFIG_X86_LOCAL_APIC |
| apic_intr_init(); |
| #endif |
| |
| if (!acpi_ioapic) |
| setup_irq(2, &irq2); |
| } |
| |
| /** |
| * pre_setup_arch_hook - hook called prior to any setup_arch() execution |
| * |
| * Description: |
| * generally used to activate any machine specific identification |
| * routines that may be needed before setup_arch() runs. On VISWS |
| * this is used to get the board revision and type. |
| **/ |
| void __init pre_setup_arch_hook(void) |
| { |
| } |
| |
| /** |
| * trap_init_hook - initialise system specific traps |
| * |
| * Description: |
| * Called as the final act of trap_init(). Used in VISWS to initialise |
| * the various board specific APIC traps. |
| **/ |
| void __init trap_init_hook(void) |
| { |
| } |
| |
| static struct irqaction irq0 = { |
| .handler = timer_interrupt, |
| .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL, |
| .mask = CPU_MASK_NONE, |
| .name = "timer" |
| }; |
| |
| /** |
| * time_init_hook - do any specific initialisations for the system timer. |
| * |
| * Description: |
| * Must plug the system timer interrupt source at HZ into the IRQ listed |
| * in irq_vectors.h:TIMER_IRQ |
| **/ |
| void __init time_init_hook(void) |
| { |
| irq0.mask = cpumask_of_cpu(0); |
| setup_irq(0, &irq0); |
| } |
| |
| #ifdef CONFIG_MCA |
| /** |
| * mca_nmi_hook - hook into MCA specific NMI chain |
| * |
| * Description: |
| * The MCA (Microchannel Arcitecture) has an NMI chain for NMI sources |
| * along the MCA bus. Use this to hook into that chain if you will need |
| * it. |
| **/ |
| void mca_nmi_hook(void) |
| { |
| /* If I recall correctly, there's a whole bunch of other things that |
| * we can do to check for NMI problems, but that's all I know about |
| * at the moment. |
| */ |
| |
| printk("NMI generated from unknown source!\n"); |
| } |
| #endif |
| |
| static __init int no_ipi_broadcast(char *str) |
| { |
| get_option(&str, &no_broadcast); |
| printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" : |
| "IPI Broadcast"); |
| return 1; |
| } |
| |
| __setup("no_ipi_broadcast=", no_ipi_broadcast); |
| |
| static int __init print_ipi_mode(void) |
| { |
| printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" : |
| "Shortcut"); |
| return 0; |
| } |
| |
| late_initcall(print_ipi_mode); |
| |
| /** |
| * machine_specific_memory_setup - Hook for machine specific memory setup. |
| * |
| * Description: |
| * This is included late in kernel/setup.c so that it can make |
| * use of all of the static functions. |
| **/ |
| |
| char * __init machine_specific_memory_setup(void) |
| { |
| char *who; |
| |
| |
| who = "BIOS-e820"; |
| |
| /* |
| * Try to copy the BIOS-supplied E820-map. |
| * |
| * Otherwise fake a memory map; one section from 0k->640k, |
| * the next section from 1mb->appropriate_mem_k |
| */ |
| sanitize_e820_map(boot_params.e820_map, &boot_params.e820_entries); |
| if (copy_e820_map(boot_params.e820_map, boot_params.e820_entries) |
| < 0) { |
| unsigned long mem_size; |
| |
| /* compare results from other methods and take the greater */ |
| if (boot_params.alt_mem_k |
| < boot_params.screen_info.ext_mem_k) { |
| mem_size = boot_params.screen_info.ext_mem_k; |
| who = "BIOS-88"; |
| } else { |
| mem_size = boot_params.alt_mem_k; |
| who = "BIOS-e801"; |
| } |
| |
| e820.nr_map = 0; |
| add_memory_region(0, LOWMEMSIZE(), E820_RAM); |
| add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); |
| } |
| return who; |
| } |