summaryrefslogtreecommitdiffstats
path: root/arch/ppc/kernel
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /arch/ppc/kernel
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r--arch/ppc/kernel/Makefile11
-rw-r--r--arch/ppc/kernel/align.c4
-rw-r--r--arch/ppc/kernel/apus_setup.c199
-rw-r--r--arch/ppc/kernel/chrp_setup.c62
-rw-r--r--arch/ppc/kernel/feature.c249
-rw-r--r--arch/ppc/kernel/find_name.c4
-rw-r--r--arch/ppc/kernel/head.S358
-rw-r--r--arch/ppc/kernel/idle.c26
-rw-r--r--arch/ppc/kernel/irq.c561
-rw-r--r--arch/ppc/kernel/misc.S93
-rw-r--r--arch/ppc/kernel/openpic.c77
-rw-r--r--arch/ppc/kernel/pci.c18
-rw-r--r--arch/ppc/kernel/pmac_pci.c10
-rw-r--r--arch/ppc/kernel/pmac_setup.c201
-rw-r--r--arch/ppc/kernel/pmac_support.c3
-rw-r--r--arch/ppc/kernel/ppc_defs.h69
-rw-r--r--arch/ppc/kernel/ppc_htab.c150
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c18
-rw-r--r--arch/ppc/kernel/prep_pci.c66
-rw-r--r--arch/ppc/kernel/prep_setup.c96
-rw-r--r--arch/ppc/kernel/process.c39
-rw-r--r--arch/ppc/kernel/prom.c903
-rw-r--r--arch/ppc/kernel/residual.c85
-rw-r--r--arch/ppc/kernel/setup.c215
-rw-r--r--arch/ppc/kernel/signal.c14
-rw-r--r--arch/ppc/kernel/smp.c114
-rw-r--r--arch/ppc/kernel/syscalls.c2
-rw-r--r--arch/ppc/kernel/time.c9
-rw-r--r--arch/ppc/kernel/totalmp.c109
29 files changed, 2853 insertions, 912 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 6f1060560..4846d5ebb 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -11,11 +11,11 @@
$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
O_TARGET := kernel.o
-OX_OBJS := ppc_ksyms.o
+OX_OBJS := ppc_ksyms.o setup.o
O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
- bitops.o setup.o ptrace.o align.o ppc_htab.o
+ bitops.o ptrace.o align.o ppc_htab.o feature.o
ifdef CONFIG_PCI
O_OBJS += pci.o
@@ -23,6 +23,9 @@ endif
ifdef CONFIG_KGDB
O_OBJS += ppc-stub.o
endif
+ifdef CONFIG_TOTALMP
+O_OBJS += totalmp.o
+endif
ifeq ($(CONFIG_MBX),y)
O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o
@@ -31,10 +34,10 @@ ifeq ($(CONFIG_APUS),y)
O_OBJS += apus_setup.o prom.o openpic.o
else
O_OBJS += prep_time.o pmac_time.o chrp_time.o \
- pmac_setup.o pmac_support.o chrp_setup.o \
+ pmac_setup.o pmac_support.o \
prep_pci.o pmac_pci.o chrp_pci.o \
residual.o prom.o openpic.o
-OX_OBJS += prep_setup.o
+OX_OBJS += chrp_setup.o prep_setup.o
endif
endif
diff --git a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c
index 70284674b..83ee7756d 100644
--- a/arch/ppc/kernel/align.c
+++ b/arch/ppc/kernel/align.c
@@ -265,7 +265,7 @@ fix_alignment(struct pt_regs *regs)
#else
giveup_fpu();
#endif
- cvt_fd(&data.f, &current->tss.fpr[reg]);
+ cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
/* current->tss.fpr[reg] = data.f; */
break;
case ST+F+S:
@@ -275,7 +275,7 @@ fix_alignment(struct pt_regs *regs)
#else
giveup_fpu();
#endif
- cvt_df(&current->tss.fpr[reg], &data.f);
+ cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
/* data.f = current->tss.fpr[reg]; */
break;
default:
diff --git a/arch/ppc/kernel/apus_setup.c b/arch/ppc/kernel/apus_setup.c
index ea2bc5690..93c2fe2d1 100644
--- a/arch/ppc/kernel/apus_setup.c
+++ b/arch/ppc/kernel/apus_setup.c
@@ -19,6 +19,7 @@
#include <asm/amigahw.h>
#include <asm/amigappc.h>
#include <asm/pgtable.h>
+#include <asm/io.h>
unsigned long m68k_machtype;
char debug_device[6] = "";
@@ -60,6 +61,8 @@ extern struct mem_info memory[NUM_MEMINFO];/* memory description */
extern void amiga_floppy_setup(char *, int *);
extern void config_amiga(void);
+static int __60nsram = 0;
+
/*********************************************************** SETUP */
/* From arch/m68k/kernel/setup.c. */
__initfunc(void apus_setup_arch(unsigned long * memory_start_p,
@@ -75,10 +78,17 @@ __initfunc(void apus_setup_arch(unsigned long * memory_start_p,
for( p = cmd_line; p && *p; ) {
i = 0;
if (!strncmp( p, "debug=", 6 )) {
- strncpy( debug_device, p+6, sizeof(debug_device)-1 );
- debug_device[sizeof(debug_device)-1] = 0;
- if ((q = strchr( debug_device, ' ' ))) *q = 0;
- i = 1;
+ strncpy( debug_device, p+6, sizeof(debug_device)-1 );
+ debug_device[sizeof(debug_device)-1] = 0;
+ if ((q = strchr( debug_device, ' ' ))) *q = 0;
+ i = 1;
+ } else if (!strncmp( p, "60nsram", 7 )) {
+ APUS_WRITE (APUS_REG_WAITSTATE,
+ REGWAITSTATE_SETRESET
+ |REGWAITSTATE_PPCR
+ |REGWAITSTATE_PPCW);
+ __60nsram = 1;
+ i = 1;
}
if (i) {
@@ -95,63 +105,85 @@ __initfunc(void apus_setup_arch(unsigned long * memory_start_p,
config_amiga();
}
+
+void get_current_tb(unsigned long long *time)
+{
+ __asm __volatile ("1:mftbu 4 \n\t"
+ " mftb 5 \n\t"
+ " mftbu 6 \n\t"
+ " cmpw 4,6 \n\t"
+ " bne 1b \n\t"
+ " stw 4,0(%0)\n\t"
+ " stw 5,4(%0)\n\t"
+ :
+ : "r" (time)
+ : "r4", "r5", "r6");
+}
+
+
void apus_calibrate_decr(void)
{
int freq, divisor;
- unsigned char c = *(unsigned char*)ZTWO_VADDR(0xf00011);
- switch (c)
+ /* This algorithm for determining the bus speed was
+ contributed by Ralph Schmidt. */
+ unsigned long long start, stop;
+ int bus_speed;
+
{
- case 'A':
- case 'B':
- if (amiga_model == AMI_1200 || amiga_model == AMI_2000){
- freq = 1;
- } else {
- freq = 0;
- }
- break;
- case 'C':
- if (amiga_model == AMI_1200 || amiga_model == AMI_2000){
- freq = 0;
- } else {
- freq = 1;
+ unsigned long loop = amiga_eclock / 10;
+
+ get_current_tb (&start);
+ while (loop--) {
+ unsigned char tmp;
+
+ tmp = ciaa.pra;
}
- break;
- case 'D':
- freq = 1;
- break;
- default:
- freq = 0;
- printk (" *Unknown CPU speed ID ('%c')* ", c);
- break;
+ get_current_tb (&stop);
+ }
+
+ bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
+ if (AMI_1200 == amiga_model)
+ bus_speed /= 2;
+
+ if ((bus_speed >= 47) && (bus_speed < 53)) {
+ bus_speed = 50;
+ freq = 12500000;
+ } else if ((bus_speed >= 57) && (bus_speed < 63)) {
+ bus_speed = 60;
+ freq = 15000000;
+ } else if ((bus_speed >= 63) && (bus_speed < 69)) {
+ bus_speed = 66;
+ freq = 16500000;
+ } else {
+ printk ("APUS: Unable to determine bus speed (%d). "
+ "Defaulting to 50MHz", bus_speed);
+ bus_speed = 50;
+ freq = 12500000;
}
+ /* Ease diagnostics... */
{
- int speed;
- switch (freq)
- {
- case 0:
- freq = 15000000;
- speed = 60;
-
- /* Use status of left mouse button to select
- RAM speed. */
- if (!(ciaa.pra & 0x40))
- {
- APUS_WRITE (APUS_REG_WAITSTATE,
- REGWAITSTATE_SETRESET
- |REGWAITSTATE_PPCR
- |REGWAITSTATE_PPCW);
- printk (" [RAM R/W waitstate removed. "
- "(expecting 60ns RAM).] ");
+ extern int __map_without_bats;
+
+ printk ("APUS: BATs=%d, BUS=%dMHz, RAM=%dns\n",
+ (__map_without_bats) ? 0 : 1,
+ bus_speed,
+ (__60nsram) ? 60 : 70);
+
+ /* print a bit more if asked politely... */
+ if (!(ciaa.pra & 0x40)){
+ extern unsigned int bat_addrs[4][3];
+ int b;
+ for (b = 0; b < 4; ++b) {
+ printk ("APUS: BAT%d ", b);
+ printk ("%08x-%08x -> %08x\n",
+ bat_addrs[b][0],
+ bat_addrs[b][1],
+ bat_addrs[b][2]);
}
- break;
- case 1:
- freq = 16500000;
- speed = 66;
- break;
}
- printk ("PowerUp Bus Speed: %dMHz\n", speed);
+
}
freq *= 60; /* try to make freq/1e6 an integer */
@@ -222,7 +254,72 @@ unsigned long kernel_map (unsigned long phys_addr, unsigned long size,
}
return v_ret;
}
-
+
+/* From pgtable.h */
+extern __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+ pgd_t *dir = 0;
+ pmd_t *pmd = 0;
+ pte_t *pte = 0;
+
+ va &= PAGE_MASK;
+
+ dir = pgd_offset( mm, va );
+ if (dir)
+ {
+ pmd = pmd_offset(dir, va & PAGE_MASK);
+ if (pmd && pmd_present(*pmd))
+ {
+ pte = pte_offset(pmd, va);
+ }
+ }
+ return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+ unsigned int cmode )
+{
+ int mask, flags;
+
+ switch (cmode)
+ {
+ case KERNELMAP_FULL_CACHING:
+ mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+ flags = 0;
+ break;
+ case KERNELMAP_NOCACHE_SER:
+ mask = ~0;
+ flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+ break;
+ default:
+ panic ("kernel_set_cachemode() doesn't support mode %d\n",
+ cmode);
+ break;
+ }
+
+ size /= PAGE_SIZE;
+ address &= PAGE_MASK;
+ while (size--)
+ {
+ pte_t *pte;
+
+ pte = my_find_pte(init_task.mm, address);
+ if ( !pte )
+ {
+ printk("pte NULL in kernel_set_cachemode()\n");
+ return;
+ }
+
+ pte_val (*pte) &= mask;
+ pte_val (*pte) |= flags;
+ flush_tlb_page(find_vma(init_task.mm,address),address);
+
+ address += PAGE_SIZE;
+ }
+}
+
unsigned long mm_ptov (unsigned long paddr)
{
unsigned long ret;
diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c
index 748a78e00..5b373c876 100644
--- a/arch/ppc/kernel/chrp_setup.c
+++ b/arch/ppc/kernel/chrp_setup.c
@@ -11,6 +11,7 @@
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -29,6 +30,7 @@
#include <linux/blk.h>
#include <linux/ioport.h>
#include <linux/console.h>
+#include <linux/pci.h>
#include <asm/mmu.h>
#include <asm/processor.h>
@@ -37,6 +39,7 @@
#include <asm/ide.h>
#include <asm/prom.h>
#include <asm/gg2.h>
+#include <asm/pci-bridge.h>
extern void hydra_init(void);
extern void w83c553f_init(void);
@@ -189,7 +192,15 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
aux_device_present = 0xaa;
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* this is fine for chrp */
+ initrd_below_start_ok = 1;
+
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ else
+#endif
+ ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
printk("Boot arguments: %s\n", cmd_line);
@@ -203,7 +214,6 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
/* PCI bridge config space access area -
* appears to be not in devtree on longtrail. */
ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
-
/*
* Temporary fixes for PCI devices.
* -- Geert
@@ -215,8 +225,54 @@ chrp_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
* Fix the Super I/O configuration
*/
sio_init();
-
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
#endif
+ /* my starmax 6000 needs this but the longtrail shouldn't do it -- Cort */
+ if ( !strncmp("MOT", get_property(find_path_device("/"),
+ "model", NULL),3) )
+ *memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+ ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;
+ *p++ = port;
+ if (irq != NULL)
+ *irq = chrp_ide_irq;
}
+
+void chrp_ide_probe(void) {
+
+ struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+ chrp_ide_ports_known = 1;
+
+ if(pdev) {
+ chrp_ide_regbase[0]=pdev->base_address[0] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_ide_regbase[1]=pdev->base_address[2] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_idedma_regbase=pdev->base_address[4] &
+ PCI_BASE_ADDRESS_IO_MASK;
+ chrp_ide_irq=pdev->irq;
+ }
+}
+
+EXPORT_SYMBOL(chrp_ide_irq);
+EXPORT_SYMBOL(chrp_ide_ports_known);
+EXPORT_SYMBOL(chrp_ide_regbase);
+EXPORT_SYMBOL(chrp_ide_probe);
+
+#endif
diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c
new file mode 100644
index 000000000..48d8bcb39
--- /dev/null
+++ b/arch/ppc/kernel/feature.c
@@ -0,0 +1,249 @@
+/*
+ * arch/ppc/kernel/feature.c
+ *
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * 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.
+ *
+ */
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <asm/ohare.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/feature.h>
+
+#define MAX_FEATURE_REGS 2
+#undef DEBUG_FEATURE
+
+static u32 feature_bits_pbook[] = {
+ 0, /* FEATURE_null */
+ OH_SCC_RESET, /* FEATURE_Serial_reset */
+ OH_SCC_ENABLE, /* FEATURE_Serial_enable */
+ OH_SCCA_IO, /* FEATURE_Serial_IO_A */
+ OH_SCCB_IO, /* FEATURE_Serial_IO_B */
+ OH_FLOPPY_ENABLE, /* FEATURE_SWIM3_enable */
+ OH_MESH_ENABLE, /* FEATURE_MESH_enable */
+ OH_IDE_ENABLE, /* FEATURE_IDE_enable */
+ OH_VIA_ENABLE, /* FEATURE_VIA_enable */
+ OH_IDECD_POWER, /* FEATURE_CD_power */
+ OH_BAY_RESET, /* FEATURE_Mediabay_reset */
+ OH_BAY_ENABLE, /* FEATURE_Mediabay_enable */
+ OH_BAY_PCI_ENABLE, /* FEATURE_Mediabay_PCI_enable */
+ OH_BAY_IDE_ENABLE, /* FEATURE_Mediabay_IDE_enable */
+ OH_BAY_FLOPPY_ENABLE, /* FEATURE_Mediabay_floppy_enable */
+ 0, /* FEATURE_BMac_reset */
+ 0, /* FEATURE_BMac_IO_enable */
+ 0, /* FEATURE_Modem_PowerOn -> guess...*/
+ 0 /* FEATURE_Modem_Reset -> guess...*/
+};
+
+/* assume these are the same as the ohare until proven otherwise */
+static u32 feature_bits_heathrow[] = {
+ 0, /* FEATURE_null */
+ OH_SCC_RESET, /* FEATURE_Serial_reset */
+ OH_SCC_ENABLE, /* FEATURE_Serial_enable */
+ OH_SCCA_IO, /* FEATURE_Serial_IO_A */
+ OH_SCCB_IO, /* FEATURE_Serial_IO_B */
+ OH_FLOPPY_ENABLE, /* FEATURE_SWIM3_enable */
+ OH_MESH_ENABLE, /* FEATURE_MESH_enable */
+ OH_IDE_ENABLE, /* FEATURE_IDE_enable */
+ OH_VIA_ENABLE, /* FEATURE_VIA_enable */
+ OH_IDECD_POWER, /* FEATURE_CD_power */
+ OH_BAY_RESET, /* FEATURE_Mediabay_reset */
+ OH_BAY_ENABLE, /* FEATURE_Mediabay_enable */
+ OH_BAY_PCI_ENABLE, /* FEATURE_Mediabay_PCI_enable */
+ OH_BAY_IDE_ENABLE, /* FEATURE_Mediabay_IDE_enable */
+ OH_BAY_FLOPPY_ENABLE, /* FEATURE_Mediabay_floppy_enable */
+ 0x80000000, /* FEATURE_BMac_reset */
+ 0x60000000, /* FEATURE_BMac_IO_enable */
+ 0x02000000, /* FEATURE_Modem_PowerOn -> guess...*/
+ 0x07000000 /* FEATURE_Modem_Reset -> guess...*/
+};
+
+/* definition of a feature controller object */
+struct feature_controller
+{
+ u32* bits;
+ volatile u32* reg;
+ struct device_node* device;
+};
+
+/* static functions */
+static void
+feature_add_controller(struct device_node *controller_device, u32* bits);
+
+static int
+feature_lookup_controller(struct device_node *device);
+
+/* static varialbles */
+static struct feature_controller controllers[MAX_FEATURE_REGS];
+static int controller_count = 0;
+
+
+void
+feature_init(void)
+{
+ struct device_node *np;
+
+ np = find_devices("mac-io");
+ while (np != NULL)
+ {
+ feature_add_controller(np, feature_bits_heathrow);
+ np = np->next;
+ }
+ if (controller_count == 0)
+ {
+ np = find_devices("ohare");
+ if (np)
+ {
+ if (find_devices("via-pmu") != NULL)
+ feature_add_controller(np, feature_bits_pbook);
+ else
+ /* else not sure; maybe this is a Starmax? */
+ feature_add_controller(np, NULL);
+ }
+ }
+
+ if (controller_count)
+ printk(KERN_INFO "Registered %d feature controller(s)\n", controller_count);
+}
+
+static void
+feature_add_controller(struct device_node *controller_device, u32* bits)
+{
+ struct feature_controller* controller;
+
+ if (controller_count >= MAX_FEATURE_REGS)
+ {
+ printk(KERN_INFO "Feature controller %s skipped(MAX:%d)\n",
+ controller_device->full_name, MAX_FEATURE_REGS);
+ return;
+ }
+ controller = &controllers[controller_count];
+
+ controller->bits = bits;
+ controller->device = controller_device;
+ if (controller_device->n_addrs == 0) {
+ printk(KERN_ERR "No addresses for %s\n",
+ controller_device->full_name);
+ return;
+ }
+
+ controller->reg = (volatile u32 *)ioremap(
+ controller_device->addrs[0].address + OHARE_FEATURE_REG, 4);
+
+ if (bits == NULL) {
+ printk(KERN_INFO "Twiddling the magic ohare bits\n");
+ out_le32(controller->reg, STARMAX_FEATURES);
+ return;
+ }
+
+ controller_count++;
+}
+
+static int
+feature_lookup_controller(struct device_node *device)
+{
+ int i;
+
+ if (device == NULL)
+ return -EINVAL;
+
+ while(device)
+ {
+ for (i=0; i<controller_count; i++)
+ if (device == controllers[i].device)
+ return i;
+ device = device->parent;
+ }
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> not found on any controller\n",
+ device->name);
+#endif
+
+ return -ENODEV;
+}
+
+int
+feature_set(struct device_node* device, enum system_feature f)
+{
+ int controller;
+ unsigned long flags;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> setting feature %d in controller @0x%x\n",
+ device->name, (int)f, (unsigned int)controllers[controller].reg);
+#endif
+
+ save_flags(flags);
+ cli();
+ st_le32( controllers[controller].reg,
+ ld_le32(controllers[controller].reg) |
+ controllers[controller].bits[f]);
+ restore_flags(flags);
+ udelay(10);
+
+ return 0;
+}
+
+int
+feature_clear(struct device_node* device, enum system_feature f)
+{
+ int controller;
+ unsigned long flags;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+#ifdef DEBUG_FEATURE
+ printk("feature: <%s> clearing feature %d in controller @0x%x\n",
+ device->name, (int)f, (unsigned int)controllers[controller].reg);
+#endif
+
+ save_flags(flags);
+ cli();
+ st_le32( controllers[controller].reg,
+ ld_le32(controllers[controller].reg) &
+ ~(controllers[controller].bits[f]));
+ restore_flags(flags);
+ udelay(10);
+
+ return 0;
+}
+
+int
+feature_test(struct device_node* device, enum system_feature f)
+{
+ int controller;
+
+ if (f >= FEATURE_last)
+ return -EINVAL;
+
+ controller = feature_lookup_controller(device);
+ if (controller < 0)
+ return controller;
+
+ return (ld_le32(controllers[controller].reg) &
+ controllers[controller].bits[f]) != 0;
+}
+
diff --git a/arch/ppc/kernel/find_name.c b/arch/ppc/kernel/find_name.c
index d5d88bff7..3c0fa8e0c 100644
--- a/arch/ppc/kernel/find_name.c
+++ b/arch/ppc/kernel/find_name.c
@@ -16,7 +16,7 @@ int main(int argc, char **argv)
if ( argc < 2 )
{
fprintf(stderr, "Usage: %s <address>\n", argv[0]);
- exit(-1);
+ return -1;
}
for ( i = 1 ; argv[i] ; i++ )
@@ -41,7 +41,7 @@ int main(int argc, char **argv)
strcpy( last, s);
}
- printf( "%s", last);
+ printf( "%s%s", last, s );
}
fclose(f);
return 0;
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index a257e7762..4c528beb8 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1,7 +1,7 @@
/*
* arch/ppc/kernel/head.S
*
- * $Id: head.S,v 1.98 1998/07/26 21:28:48 geert Exp $
+ * $Id: head.S,v 1.111 1998/11/10 01:10:32 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -93,15 +93,18 @@ LG_CACHE_LINE_SIZE = 5
bdnz 0b
#endif
+/* 601 only have IBAT cr0.eq is set on 601 when using this macro */
#define LOAD_BAT(n, offset, reg, RA, RB) \
lwz RA,offset+0(reg); \
lwz RB,offset+4(reg); \
mtspr IBAT##n##U,RA; \
mtspr IBAT##n##L,RB; \
+ beq 1f; \
lwz RA,offset+8(reg); \
lwz RB,offset+12(reg); \
mtspr DBAT##n##U,RA; \
- mtspr DBAT##n##L,RB
+ mtspr DBAT##n##L,RB; \
+1:
#ifndef CONFIG_APUS
#define tophys(rd,rs,rt) addis rd,rs,-KERNELBASE@h
@@ -139,6 +142,12 @@ _start:
* pointer (r1) points to just below the end of the half-meg region
* from 0x380000 - 0x400000, which is mapped in already.
*
+ * If we are booted from MacOS via BootX, we enter with the kernel
+ * image loaded somewhere, and the following values in registers:
+ * r3: 'BooX' (0x426f6f58)
+ * r4: virtual address of boot_infos_t
+ * r5: 0
+ *
* PREP
* This is jumped to on prep systems right after the kernel is relocated
* to its proper place in memory by the boot loader. The expected layout
@@ -201,7 +210,8 @@ __start:
mr r27,r7
#ifndef CONFIG_8xx
bl prom_init
-
+ .globl __secondary_start
+__secondary_start:
/*
* Use the first pair of BAT registers to map the 1st 16MB
* of RAM to KERNELBASE. From this point on we can't safely
@@ -213,33 +223,45 @@ __start:
lis r11,KERNELBASE@h
bne 4f
ori r11,r11,4 /* set up BAT registers for 601 */
- li r8,0x7f
+ li r8,0x7f /* valid, block length = 8MB */
oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
+ mtspr IBAT0U,r11 /* N.B. 601 has valid bit in */
+ mtspr IBAT0L,r8 /* lower BAT register */
mtspr IBAT1U,r9
mtspr IBAT1L,r10
b 5f
4:
#ifndef CONFIG_APUS
- ori r11,r11,0x1ff /* set up BAT registers for 604 */
- li r8,2
+ ori r11,r11,0x1fe /* set up BAT registers for 604 */
+ li r8,2 /* R/W access */
#else
- ori r11,r11,0xff /* set up an 8MB mapping */
+ ori r11,r11,0xfe /* set up an 8MB mapping */
lis r8,CYBERBASEp@h
lwz r8,0(r8)
addis r8,r8,KERNELBASE@h
addi r8,r8,2
#endif
-5: mtspr DBAT0U,r11
- mtspr DBAT0L,r8
- mtspr IBAT0U,r11
+ mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
+ mtspr DBAT0U,r11 /* bit in upper BAT register */
mtspr IBAT0L,r8
- isync
+ mtspr IBAT0U,r11
+5: isync
#ifdef CONFIG_APUS
/* Unfortunately the APUS specific instructions bloat the
* code so it cannot fit in the 0x100 bytes available. We have
* to do it the crude way. */
+
+ /* Map 0xfff00000 so we can access VTOP/PTOV constant when
+ MMU is enabled. */
+ lis r8,0xfff0
+ ori r11,r8,0x2 /* r/w */
+ ori r8,r8,0x2 /* 128KB, supervisor */
+ mtspr DBAT3U,r8
+ mtspr DBAT3L,r11
+
+ /* Copy exception code to exception vector base. */
lis r3,KERNELBASE@h
tophys(r4,r3,r5)
lis r3,0xfff0 /* Copy to 0xfff00000 on APUS */
@@ -263,23 +285,10 @@ __start:
li r3,0
mfmsr r0
andi. r0,r0,MSR_DR /* MMU enabled? */
- beq 7f
+ beq relocate_kernel
lis r3,KERNELBASE@h /* if so, are we */
cmpw 0,r4,r3 /* already running at KERNELBASE? */
- beq 2f
- rlwinm r4,r4,0,8,31 /* translate source address */
- add r4,r4,r3 /* to region mapped with BATs */
-7: addis r9,r26,klimit@ha /* fetch klimit */
- lwz r25,klimit@l(r9)
- addis r25,r25,-KERNELBASE@h
- li r6,0 /* Destination */
- li r5,0x4000 /* # bytes of memory to copy */
- bl copy_and_flush /* copy the first 0x4000 bytes */
- addi r0,r3,4f@l /* jump to the address of 4f */
- mtctr r0 /* in copy and do the rest. */
- bctr /* jump to the copy */
-4: mr r5,r25
- bl copy_and_flush /* copy the rest */
+ bne relocate_kernel
2:
#endif /* CONFIG_APUS */
/*
@@ -356,6 +365,7 @@ __start:
*/
#endif /* CONFIG_8xx */
+turn_on_mmu:
mfmsr r0
ori r0,r0,MSR_DR|MSR_IR
mtspr SRR1,r0
@@ -364,7 +374,7 @@ __start:
mtspr SRR0,r0
SYNC
rfi /* enables MMU */
-
+
/*
* GCC sometimes accesses words at negative offsets from the stack
* pointer, although the SysV ABI says it shouldn't. To cope with
@@ -506,7 +516,7 @@ HardwareInterrupt:
li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
stb r20,APUS_IPL_EMU@l(r3)
- sync
+ eieio
lbz r3,APUS_IPL_EMU@l(r3)
@@ -1386,15 +1396,13 @@ hash_page_out:
next_slot:
.long 0
-/*
- * FPU stuff for the 6xx/7xx follows
- * -- Cort
- */
load_up_fpu:
/*
* Disable FP for the task which had the FPU previously,
* and save its floating-point registers in its thread_struct.
* Enables the FPU for use in the kernel on return.
+ * On SMP we know the fpu is free, since we give it up every
+ * switch. -- Cort
*/
#ifndef CONFIG_APUS
lis r6,-KERNELBASE@h
@@ -1402,28 +1410,23 @@ load_up_fpu:
lis r6,CYBERBASEp@h
lwz r6,0(r6)
#endif
+
addis r3,r6,last_task_used_math@ha
lwz r4,last_task_used_math@l(r3)
mfmsr r5
ori r5,r5,MSR_FP
SYNC
mtmsr r5 /* enable use of fpu now */
-#ifndef __SMP__
- SYNC
- cmpi 0,r4,0
- beq 1f
-#else
/*
* All the saving of last_task_used_math is handled
* by a switch_to() call to smp_giveup_fpu() in SMP so
* last_task_used_math is not used.
- *
- * We should never be herre on SMP anyway, sinc ethe fpu should
- * always be on.
* -- Cort
*/
- b 1f
-#endif
+#ifndef __SMP__
+ SYNC
+ cmpi 0,r4,0
+ beq 1f
add r4,r4,r6
addi r4,r4,TSS /* want TSS of last_task_used_math */
SAVE_32FPRS(0, r4)
@@ -1432,22 +1435,20 @@ load_up_fpu:
lwz r5,PT_REGS(r4)
add r5,r5,r6
lwz r4,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r20,MSR_FP
+ li r20,MSR_FP|MSR_FE0|MSR_FE1
andc r4,r4,r20 /* disable FP for previous task */
stw r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-
-1: ori r23,r23,MSR_FP /* enable use of FP after return */
+#endif /* __SMP__ */
+1: ori r23,r23,MSR_FP|MSR_FE0|MSR_FE1 /* enable use of FP after return */
mfspr r5,SPRG3 /* current task's TSS (phys) */
lfd fr0,TSS_FPSCR-4(r5)
mtfsf 0xff,fr0
REST_32FPRS(0, r5)
-/*
- * on SMP we don't really use last_task_used_math but set it
- * here anyway to avoid the ifdef's -- Cort
- */
subi r4,r5,TSS
sub r4,r4,r6
+#ifndef __SMP__
stw r4,last_task_used_math@l(r3)
+#endif /* __SMP__ */
/* restore registers and return */
lwz r3,_CCR(r21)
lwz r4,_LINK(r21)
@@ -1507,14 +1508,16 @@ giveup_fpu:
cmpi 0,r4,0
beqlr- /* if no previous owner, done */
addi r4,r4,TSS /* want TSS of last_task_used_math */
+#ifndef __SMP__
li r5,0
stw r5,last_task_used_math@l(r3)
+#endif /* __SMP__ */
SAVE_32FPRS(0, r4)
mffs fr0
stfd fr0,TSS_FPSCR-4(r4)
lwz r5,PT_REGS(r4)
lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5)
- li r4,MSR_FP
+ li r4,MSR_FP|MSR_FE0|MSR_FE1
andc r3,r3,r4 /* disable FP for previous task */
stw r3,_MSR-STACK_FRAME_OVERHEAD(r5)
#else /* CONFIG_8xx */
@@ -1522,7 +1525,31 @@ giveup_fpu:
giveup_fpu:
#endif /* CONFIG_8xx */
blr
-
+
+/*
+ * This code is jumped to from the startup code to copy
+ * the kernel image to physical address 0.
+ */
+relocate_kernel:
+ lis r9,0x426f /* if booted from BootX, don't */
+ addi r9,r9,0x6f58 /* translate source addr */
+ cmpw r31,r9 /* (we have to on chrp) */
+ beq 7f
+ rlwinm r4,r4,0,8,31 /* translate source address */
+ add r4,r4,r3 /* to region mapped with BATs */
+7: addis r9,r26,klimit@ha /* fetch klimit */
+ lwz r25,klimit@l(r9)
+ addis r25,r25,-KERNELBASE@h
+ li r6,0 /* Destination offset */
+ li r5,0x4000 /* # bytes of memory to copy */
+ bl copy_and_flush /* copy the first 0x4000 bytes */
+ addi r0,r3,4f@l /* jump to the address of 4f */
+ mtctr r0 /* in copy and do the rest. */
+ bctr /* jump to the copy */
+4: mr r5,r25
+ bl copy_and_flush /* copy the rest */
+ b turn_on_mmu
+
/*
* Copy routine used to copy the kernel to start at physical address 0
* and flush and invalidate the caches as needed.
@@ -1577,11 +1604,6 @@ start_here:
bne 3f /* don't invalidate the D-cache */
ori r8,r8,HID0_DCI /* unless it wasn't enabled */
3:
- /* turn on dpm for 603 */
- cmpi 0,r9,3
- bne 10f
- oris r11,r11,HID0_DPM@h
-10:
sync
mtspr HID0,r8 /* enable and invalidate caches */
sync
@@ -1600,14 +1622,27 @@ start_here:
5: mtspr HID0,r11 /* superscalar exec & br history tbl */
4:
#endif /* CONFIG_8xx */
+#ifdef __SMP__
+ /* if we're the second cpu stack and r2 are different
+ * and we want to not clear the bss -- Cort */
+ lis r5,first_cpu_booted@h
+ ori r5,r5,first_cpu_booted@l
+ lwz r5,0(r5)
+ cmpi 0,r5,0
+ beq 99f
+
+ /* get current */
+ lis r2,current_set@h
+ ori r2,r2,current_set@l
+ addi r2,r2,4
+ lwz r2,0(r2)
+
+ b 10f
+99:
+#endif /* __SMP__ */
/* ptr to current */
lis r2,init_task_union@h
ori r2,r2,init_task_union@l
- /* stack */
- addi r1,r2,TASK_UNION_SIZE
- li r0,0
- stwu r0,-STACK_FRAME_OVERHEAD(r1)
-
/* Clear out the BSS */
lis r11,_end@ha
addi r11,r11,_end@l
@@ -1623,6 +1658,15 @@ start_here:
3: stwu r0,4(r8)
bdnz 3b
2:
+#ifdef __SMP__
+10:
+#endif /* __SMP__ */
+
+ /* stack */
+ addi r1,r2,TASK_UNION_SIZE
+ li r0,0
+ stwu r0,-STACK_FRAME_OVERHEAD(r1)
+
/*
* Decide what sort of machine this is and initialize the MMU.
*/
@@ -1633,6 +1677,7 @@ start_here:
mr r7,r27
bl identify_machine
bl MMU_init
+
/*
* Go back to running unmapped so we can load up new values
* for SDR1 (hash table pointer) and the segment registers
@@ -1674,9 +1719,11 @@ start_here:
addi r3,r3,1 /* increment VSID */
addis r4,r4,0x1000 /* address of next segment */
bdnz 3b
-
/* Load the BAT registers with the values set up by MMU_init.
MMU_init takes care of whether we're on a 601 or not. */
+ mfpvr r3
+ srwi r3,r3,16
+ cmpwi r3,1
lis r3,BATS@ha
addi r3,r3,BATS@l
tophys(r3,r3,r4)
@@ -1696,6 +1743,20 @@ start_here:
li r4,MSR_KERNEL
lis r3,start_kernel@h
ori r3,r3,start_kernel@l
+#ifdef __SMP__
+ /* the second time through here we go to
+ * start_secondary(). -- Cort
+ */
+ lis r5,first_cpu_booted@h
+ ori r5,r5,first_cpu_booted@l
+ tophys(r5,r5,r3)
+ lwz r5,0(r5)
+ cmpi 0,r5,0
+ beq 10f
+ lis r3,start_secondary@h
+ ori r3,r3,start_secondary@l
+10:
+#endif /* __SMP__ */
mtspr SRR0,r3
mtspr SRR1,r4
rfi /* enable MMU and jump to start_kernel */
@@ -1954,6 +2015,8 @@ int_return:
beq+ 1f
addi r3,r1,STACK_FRAME_OVERHEAD
bl do_IRQ
+ .globl lost_irq_ret
+lost_irq_ret:
b 3b
1: lis r4,bh_mask@ha
lwz r4,bh_mask@l(r4)
@@ -1962,6 +2025,8 @@ int_return:
and. r4,r4,r5
beq+ 2f
bl do_bottom_half
+ .globl do_bottom_half_ret
+do_bottom_half_ret:
SYNC
mtmsr r30 /* disable interrupts again */
SYNC
@@ -1979,6 +2044,8 @@ int_return:
li r3,0
addi r4,r1,STACK_FRAME_OVERHEAD
bl do_signal
+ .globl do_signal_ret
+do_signal_ret:
b 0b
8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
stw r4,TSS+KSP(r2) /* save kernel stack pointer */
@@ -2221,173 +2288,6 @@ _GLOBAL(flush_hash_page)
_GLOBAL(__main)
blr
-#ifdef __SMP__
-/*
- * Secondary processor begins executing here.
- */
- .globl secondary_entry
-secondary_entry:
- /* just like __start() with a few changes -- Cort */
- mfspr r9,PVR
- rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
- cmpi 0,r9,1
- lis r11,KERNELBASE@h
- bne 4f
- ori r11,r11,4 /* set up BAT registers for 601 */
- li r8,0x7f
- oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */
- oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */
- mtspr IBAT1U,r9
- mtspr IBAT1L,r10
- b 5f
-4: ori r11,r11,0x1ff /* set up BAT registers for 604 */
- li r8,2
- mtspr DBAT0U,r11
- mtspr DBAT0L,r8
-5: mtspr IBAT0U,r11
- mtspr IBAT0L,r8
- isync
-/*
- * we now have the 1st 16M of ram mapped with the bats.
- * prep needs the mmu to be turned on here, but pmac already has it on.
- * this shouldn't bother the pmac since it just gets turned on again
- * as we jump to our code at KERNELBASE. -- Cort
- */
- mfmsr r0
- ori r0,r0,MSR_DR|MSR_IR
- mtspr SRR1,r0
- lis r0,100f@h
- ori r0,r0,100f@l
- mtspr SRR0,r0
- SYNC
- rfi /* enables MMU */
-100:
- /*
- * Enable caches and 604-specific features if necessary.
- */
- mfspr r9,PVR
- rlwinm r9,r9,16,16,31
- cmpi 0,r9,1
- beq 4f /* not needed for 601 */
- mfspr r11,HID0
- andi. r0,r11,HID0_DCE
- ori r11,r11,HID0_ICE|HID0_DCE
- ori r8,r11,HID0_ICFI
- bne 3f /* don't invalidate the D-cache */
- ori r8,r8,HID0_DCI /* unless it wasn't enabled */
-3:
- /* turn on dpm for 603 */
- cmpi 0,r9,3
- bne 10f
- oris r11,r11,HID0_DPM@h
-10:
- sync
- mtspr HID0,r8 /* enable and invalidate caches */
- sync
- mtspr HID0,r11 /* enable caches */
- sync
- isync
- cmpi 0,r9,4 /* check for 604 */
- cmpi 1,r9,9 /* or 604e */
- cmpi 2,r9,10 /* or mach5 */
- cror 2,2,6
- cror 2,2,10
- bne 4f
- ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
- bne 2,5f
- ori r11,r11,HID0_BTCD
-5: mtspr HID0,r11 /* superscalar exec & br history tbl */
-4:
-/*
- * init_MMU on the first processor has setup the variables
- * for us - all we need to do is load them -- Cort
- */
-
-/*
- * Go back to running unmapped so we can load up new values
- * for SDR1 (hash table pointer) and the segment registers
- * and change to using our exception vectors.
- */
- lis r6,_SDR1@ha
- lwz r6,_SDR1@l(r6)
- lis r4,2f@h
- ori r4,r4,2f@l
- tophys(r4,r4,r3)
- li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
- mtspr SRR0,r4
- mtspr SRR1,r3
- rfi
-/* Load up the kernel context */
-2:
- /* get ptr to current */
- lis r2,current_set@h
- ori r2,r2,current_set@l
- /* assume we're second processor for now */
- tophys(r2,r2,r10)
- lwz r2,4(r2)
- /* stack */
- addi r1,r2,TASK_UNION_SIZE
- li r0,0
- tophys(r3,r1,r10)
- stwu r0,-STACK_FRAME_OVERHEAD(r3)
-
- SYNC /* Force all PTE updates to finish */
- tlbia /* Clear all TLB entries */
- mtspr SDR1,r6
- li r0,16 /* load up segment register values */
- mtctr r0 /* for context 0 */
- lis r3,0x2000 /* Ku = 1, VSID = 0 */
- li r4,0
-3: mtsrin r3,r4
- addi r3,r3,1 /* increment VSID */
- addis r4,r4,0x1000 /* address of next segment */
- bdnz 3b
-
-/* Load the BAT registers with the values set up by MMU_init.
- MMU_init takes care of whether we're on a 601 or not. */
- lis r3,BATS@ha
- addi r3,r3,BATS@l
- tophys(r3,r3,r4)
- LOAD_BAT(0,0,r3,r4,r5)
- LOAD_BAT(1,16,r3,r4,r5)
- LOAD_BAT(2,32,r3,r4,r5)
- LOAD_BAT(3,48,r3,r4,r5)
-
-/* Set up for using our exception vectors */
- /* ptr to phys current tss */
- tophys(r4,r2,r4)
- addi r4,r4,TSS /* init task's TSS */
- mtspr SPRG3,r4
- li r3,0
- mtspr SPRG2,r3 /* 0 => r1 has kernel sp */
-
- /* need to flush/invalidate caches too */
- li r3,0x4000/CACHE_LINE_SIZE
- li r4,0
- mtctr r3
-73: dcbst 0,r4
- addi r4,r4,CACHE_LINE_SIZE
- bdnz 73b
- sync
- li r4,0
- mtctr r3
-72: icbi 0,r4
- addi r4,r4,CACHE_LINE_SIZE
- bdnz 72b
- sync
- isync
-77:
-/* Now turn on the MMU for real! */
- li r4,MSR_KERNEL
- lis r3,start_secondary@h
- ori r3,r3,start_secondary@l
- mtspr SRR0,r3
- mtspr SRR1,r4
- rfi /* enable MMU and jump to start_kernel */
-/* should never return */
- .long 0
-#endif /* __SMP__ */
-
/*
* PROM code for specific machines follows. Put it
* here so it's easy to add arch-specific sections later.
diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c
index bd7980678..b6c338946 100644
--- a/arch/ppc/kernel/idle.c
+++ b/arch/ppc/kernel/idle.c
@@ -1,5 +1,5 @@
/*
- * $Id: idle.c,v 1.48 1998/07/30 11:29:22 davem Exp $
+ * $Id: idle.c,v 1.56 1998/10/13 19:14:36 paulus Exp $
*
* Idle daemon for PowerPC. Idle daemon will handle any action
* that needs to be taken when the system becomes idle.
@@ -11,8 +11,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
-#define __KERNEL_SYSCALLS__
-
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
@@ -32,9 +30,6 @@
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/cache.h>
-#ifdef CONFIG_PMAC
-#include <asm/mediabay.h>
-#endif
void zero_paged(void);
void power_save(void);
@@ -53,22 +48,15 @@ int idled(void *unused)
__sti();
/* endless loop with no priority at all */
- current->priority = -100;
- current->counter = -100;
+ current->priority = 0;
+ current->counter = 0;
check_pgt_cache();
if ( !current->need_resched && zero_paged_on ) zero_paged();
if ( !current->need_resched && htab_reclaim_on ) htab_reclaim();
-
- /*
- * Only processor 1 may sleep now since processor 2 would
- * never wake up. Need to add timer code for processor 2
- * then it can sleep. -- Cort
- */
-#ifndef __SMP__
if ( !current->need_resched ) power_save();
-#endif /* __SMP__ */
+ run_task_queue(&tq_scheduler);
schedule();
}
ret = 0;
@@ -92,15 +80,9 @@ int cpu_idle(void *unused)
*/
asmlinkage int sys_idle(void)
{
- extern int media_bay_task(void *);
if(current->pid != 0)
return -EPERM;
-#ifdef CONFIG_PMAC
- if (media_bay_present)
- kernel_thread(media_bay_task, NULL, 0);
-#endif
-
idled(NULL);
return 0; /* should never execute this but it makes gcc happy -- Cort */
}
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index cb4d0872e..a180e5f0a 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -9,7 +9,7 @@
* Adapted for Power Macintosh by Paul Mackerras
* Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
* Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
- *
+ *
* This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines
* instead of just grabbing them. Thus setups with different IRQ numbers
@@ -50,55 +50,29 @@
#include <asm/gg2.h>
#include <asm/cache.h>
#include <asm/prom.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigappc.h>
#ifdef CONFIG_8xx
#include <asm/8xx_immap.h>
#include <asm/mbx.h>
#endif
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigappc.h>
-#define VEC_SPUR (24)
extern void process_int(unsigned long vec, struct pt_regs *fp);
extern void apus_init_IRQ(void);
extern void amiga_disable_irq(unsigned int irq);
extern void amiga_enable_irq(unsigned int irq);
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+static volatile unsigned char *chrp_int_ack_special;
+extern volatile unsigned long ipi_count;
+static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base);
+
#ifdef CONFIG_APUS
/* Rename a few functions. Requires the CONFIG_APUS protection. */
#define request_irq nop_ppc_request_irq
#define free_irq nop_ppc_free_irq
#define get_irq_list nop_get_irq_list
#endif
-
-#undef SHOW_IRQ
-
-#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
-
-int max_irqs;
-unsigned int local_irq_count[NR_CPUS];
-static struct irqaction *irq_action[NR_IRQS];
-static int spurious_interrupts = 0;
-static unsigned int cached_irq_mask[NR_MASK_WORDS];
-unsigned int lost_interrupts[NR_MASK_WORDS];
-atomic_t n_lost_interrupts;
-
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;*/
-#ifdef __SMP__
-atomic_t __ppc_bh_counter = ATOMIC_INIT(0);
-#else
-int __ppc_bh_counter = 0;
-#endif
-static volatile unsigned char *gg2_int_ack_special;
-extern volatile unsigned long ipi_count;
-
-#define cached_21 (((char *)(cached_irq_mask))[3])
-#define cached_A1 (((char *)(cached_irq_mask))[2])
-
-/*
- * These are set to the appropriate functions by init_IRQ()
- */
#ifndef CONFIG_8xx
void (*mask_and_ack_irq)(int irq_nr);
void (*mask_irq)(unsigned int irq_nr);
@@ -113,10 +87,24 @@ void (*unmask_irq)(unsigned int irq_nr);
#define unmask_irq(irq) mbx_unmask_irq(irq)
#endif /* CONFIG_8xx */
-
-/* prep */
+#define VEC_SPUR (24)
+#undef SHOW_IRQ
+#undef SHOW_GATWICK_IRQS
+#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
+#define cached_21 (((char *)(cached_irq_mask))[3])
+#define cached_A1 (((char *)(cached_irq_mask))[2])
#define PREP_IRQ_MASK (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+int max_irqs;
+int max_real_irqs;
+static struct irqaction *irq_action[NR_IRQS];
+static int spurious_interrupts = 0;
+static unsigned int cached_irq_mask[NR_MASK_WORDS];
+unsigned int lost_interrupts[NR_MASK_WORDS];
+atomic_t n_lost_interrupts;
+
/* pmac */
struct pmac_irq_hw {
unsigned int flag;
@@ -126,13 +114,32 @@ struct pmac_irq_hw {
};
/* XXX these addresses should be obtained from the device tree */
-volatile struct pmac_irq_hw *pmac_irq_hw[2] = {
+volatile struct pmac_irq_hw *pmac_irq_hw[4] = {
(struct pmac_irq_hw *) 0xf3000020,
(struct pmac_irq_hw *) 0xf3000010,
+ (struct pmac_irq_hw *) 0xf4000020,
+ (struct pmac_irq_hw *) 0xf4000010,
};
-#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */
+/* This is the interrupt used on the main controller for the secondary
+ controller. Happens on PowerBooks G3 Series (a second mac-io)
+ -- BenH
+ */
+static int second_irq = -999;
+
+/* Returns the number of 0's to the left of the most significant 1 bit */
+static inline int cntlzw(int bits)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
+ return lz;
+}
+static inline void sync(void)
+{
+ asm volatile ("sync");
+}
/* nasty hack for shared irq's since we need to do kmalloc calls but
* can't very very early in the boot when we need to do a request irq.
@@ -190,12 +197,12 @@ void i8259_mask_and_ack_irq(int irq_nr)
/* spin_unlock(&irq_controller_lock);*/
}
-void pmac_mask_and_ack_irq(int irq_nr)
+void __pmac pmac_mask_and_ack_irq(int irq_nr)
{
unsigned long bit = 1UL << (irq_nr & 0x1f);
int i = irq_nr >> 5;
- if (irq_nr >= max_irqs)
+ if ((unsigned)irq_nr >= max_irqs)
return;
/*spin_lock(&irq_controller_lock);*/
@@ -205,13 +212,15 @@ void pmac_mask_and_ack_irq(int irq_nr)
out_le32(&pmac_irq_hw[i]->ack, bit);
out_le32(&pmac_irq_hw[i]->enable, cached_irq_mask[i]);
out_le32(&pmac_irq_hw[i]->ack, bit);
+ /* make sure ack gets to controller before we enable interrupts */
+ sync();
/*spin_unlock(&irq_controller_lock);*/
/*if ( irq_controller_lock.lock )
panic("irq controller lock still held in mask and ack\n");*/
}
-void chrp_mask_and_ack_irq(int irq_nr)
+void __openfirmware chrp_mask_and_ack_irq(int irq_nr)
{
/* spinlocks are done by i8259_mask_and_ack() - Cort */
if (is_8259_irq(irq_nr))
@@ -228,12 +237,12 @@ static void i8259_set_irq_mask(int irq_nr)
}
}
-static void pmac_set_irq_mask(int irq_nr)
+static void __pmac pmac_set_irq_mask(int irq_nr)
{
unsigned long bit = 1UL << (irq_nr & 0x1f);
int i = irq_nr >> 5;
- if (irq_nr >= max_irqs)
+ if ((unsigned)irq_nr >= max_irqs)
return;
/* enable unmasked interrupts */
@@ -268,19 +277,20 @@ static void i8259_unmask_irq(unsigned int irq_nr)
i8259_set_irq_mask(irq_nr);
}
-static void pmac_mask_irq(unsigned int irq_nr)
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
{
clear_bit(irq_nr, cached_irq_mask);
pmac_set_irq_mask(irq_nr);
+ sync();
}
-static void pmac_unmask_irq(unsigned int irq_nr)
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
{
set_bit(irq_nr, cached_irq_mask);
pmac_set_irq_mask(irq_nr);
}
-static void chrp_mask_irq(unsigned int irq_nr)
+static void __openfirmware chrp_mask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_mask_irq(irq_nr);
@@ -288,7 +298,7 @@ static void chrp_mask_irq(unsigned int irq_nr)
openpic_disable_irq(irq_to_openpic(irq_nr));
}
-static void chrp_unmask_irq(unsigned int irq_nr)
+static void __openfirmware chrp_unmask_irq(unsigned int irq_nr)
{
if (is_8259_irq(irq_nr))
i8259_unmask_irq(irq_nr);
@@ -342,7 +352,7 @@ int get_irq_list(char *buf)
for (i = 0 ; i < NR_IRQS ; i++) {
action = irq_action[i];
- if (!action || !action->handler)
+ if ((!action || !action->handler) && (i != second_irq))
continue;
len += sprintf(buf+len, "%3d: ", i);
#ifdef __SMP__
@@ -358,7 +368,10 @@ int get_irq_list(char *buf)
len += sprintf(buf+len, " 82c59 ");
break;
case _MACH_Pmac:
- len += sprintf(buf+len, " PMAC-PIC ");
+ if (i < 64)
+ len += sprintf(buf+len, " PMAC-PIC ");
+ else
+ len += sprintf(buf+len, " GATWICK ");
break;
case _MACH_chrp:
if ( is_8259_irq(i) )
@@ -371,83 +384,132 @@ int get_irq_list(char *buf)
break;
}
- len += sprintf(buf+len, " %s",action->name);
- for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ", %s", action->name);
- }
- len += sprintf(buf+len, "\n");
+ if (i != second_irq) {
+ len += sprintf(buf+len, " %s",action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s", action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ } else
+ len += sprintf(buf+len, " Gatwick secondary IRQ controller\n");
}
#ifdef __SMP__
/* should this be per processor send/receive? */
- len += sprintf(buf+len, "IPI: %10lu\n", ipi_count);
+ len += sprintf(buf+len, "IPI: %10lu", ipi_count);
for ( i = 0 ; i <= smp_num_cpus-1; i++ )
len += sprintf(buf+len," ");
- len += sprintf(buf+len, " interprocessor messages received\n");
+ len += sprintf(buf+len, " interprocessor messages received\n");
#endif
len += sprintf(buf+len, "BAD: %10u",spurious_interrupts);
for ( i = 0 ; i <= smp_num_cpus-1; i++ )
len += sprintf(buf+len," ");
- len += sprintf(buf+len, " spurious or short\n");
+ len += sprintf(buf+len, " spurious or short\n");
return len;
}
+/*
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ */
#ifdef __SMP__
-/* Who has global_irq_lock. */
unsigned char global_irq_holder = NO_PROC_ID;
+unsigned volatile int global_irq_lock;
+atomic_t global_irq_count;
-/* This protects IRQ's. */
-spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
-unsigned long previous_irqholder;
+atomic_t global_bh_count;
+atomic_t global_bh_lock;
-/* This protects BH software state (masks, things like that). */
-spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
+static void show(char * str)
+{
+ int i;
+ unsigned long *stack;
+ int cpu = smp_processor_id();
-/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT(0);
+ printk("\n%s, CPU %d:\n", str, cpu);
+ printk("irq: %d [%d %d]\n",
+ atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+ printk("bh: %d [%d %d]\n",
+ atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+ stack = (unsigned long *) &str;
+ for (i = 40; i ; i--) {
+ unsigned long x = *++stack;
+ if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+ printk("<[%08lx]> ", x);
+ }
+ }
+}
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
+#define MAXCOUNT 100000000
+static inline void wait_on_bh(void)
+{
+ int count = MAXCOUNT;
+ do {
+ if (!--count) {
+ show("wait_on_bh");
+ count = ~0;
+ }
+ /* nothing .. wait for the other bh's to go away */
+ } while (atomic_read(&global_bh_count) != 0);
+}
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; }
-void wait_on_irq(int cpu, unsigned long where)
+#define MAXCOUNT 100000000
+static inline void wait_on_irq(int cpu)
{
- int stuck = INIT_STUCK;
- int local_count = local_irq_count[cpu];
+ int count = MAXCOUNT;
- /* Are we the only one in an interrupt context? */
- while (local_count != atomic_read(&global_irq_count)) {
- /*
- * No such luck. Now we need to release the lock,
- * _and_ release our interrupt context, because
- * otherwise we'd have dead-locks and live-locks
- * and other fun things.
- */
- atomic_sub(local_count, &global_irq_count);
- spin_unlock(&global_irq_lock);
+ for (;;) {
/*
- * Wait for everybody else to go away and release
- * their things before trying to get the lock again.
+ * Wait until all interrupts are gone. Wait
+ * for bottom half handlers unless we're
+ * already executing in one..
*/
+ if (!atomic_read(&global_irq_count)) {
+ if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+ break;
+ }
+
+ /* Duh, we have to loop. Release the lock to avoid deadlocks */
+ clear_bit(0,&global_irq_lock);
+
for (;;) {
- STUCK;
+ if (!--count) {
+ show("wait_on_irq");
+ count = ~0;
+ }
+ __sti();
+ /* don't worry about the lock race Linus found
+ * on intel here. -- Cort
+ */
+ __cli();
if (atomic_read(&global_irq_count))
continue;
- if (*((unsigned char *)&global_irq_lock))
+ if (global_irq_lock)
continue;
- if (spin_trylock(&global_irq_lock))
+ if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+ continue;
+ if (!test_and_set_bit(0,&global_irq_lock))
break;
}
- atomic_add(local_count, &global_irq_count);
}
}
-#define irq_active(cpu) \
- (global_irq_count != local_irq_count[cpu])
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler.
+ */
+void synchronize_bh(void)
+{
+ if (atomic_read(&global_bh_count) && !in_interrupt())
+ wait_on_bh();
+}
+
/*
* This is called when we want to synchronize with
@@ -455,97 +517,125 @@ void wait_on_irq(int cpu, unsigned long where)
* stop sending interrupts: but to make sure there
* are no interrupts that are executing on another
* CPU we need to call this function.
- *
- * On UP this is a no-op.
*/
void synchronize_irq(void)
{
- int cpu = smp_processor_id();
- int local_count = local_irq_count[cpu];
-
- /* Do we need to wait? */
- if (local_count != atomic_read(&global_irq_count)) {
- /* The stupid way to do this */
+ if (atomic_read(&global_irq_count)) {
+ /* Stupid approach */
cli();
sti();
}
}
-#undef INIT_STUCK
-#define INIT_STUCK 10000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {\
-ll_printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
-
-void get_irqlock(int cpu, unsigned long where)
+static inline void get_irqlock(int cpu)
{
- int stuck = INIT_STUCK;
- if (!spin_trylock(&global_irq_lock)) {
+ if (test_and_set_bit(0,&global_irq_lock)) {
/* do we already hold the lock? */
if ((unsigned char) cpu == global_irq_holder)
return;
/* Uhhuh.. Somebody else got it. Wait.. */
do {
do {
- STUCK;
- barrier();
- } while (*((unsigned char *)&global_irq_lock));
- } while (!spin_trylock(&global_irq_lock));
+
+ } while (test_bit(0,&global_irq_lock));
+ } while (test_and_set_bit(0,&global_irq_lock));
}
-
- /*
- * Ok, we got the lock bit.
- * But that's actually just the easy part.. Now
- * we need to make sure that nobody else is running
+ /*
+ * We also to make sure that nobody else is running
* in an interrupt context.
*/
- wait_on_irq(cpu, where);
+ wait_on_irq(cpu);
+
/*
- * Finally.
+ * Ok, finally..
*/
global_irq_holder = cpu;
- previous_irqholder = where;
}
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
void __global_cli(void)
{
- int cpu = smp_processor_id();
- unsigned long where;
- __asm__("mr %0,31" : "=r" (where)); /* get lr */
- __cli();
- get_irqlock(cpu, where);
+ unsigned int flags;
+
+ __save_flags(flags);
+ if (flags & (1 << 15)) {
+ int cpu = smp_processor_id();
+ __cli();
+ if (!local_irq_count[cpu])
+ get_irqlock(cpu);
+ }
}
void __global_sti(void)
{
- release_irqlock(smp_processor_id());
+ int cpu = smp_processor_id();
+
+ if (!local_irq_count[cpu])
+ release_irqlock(cpu);
__sti();
}
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
unsigned long __global_save_flags(void)
{
- return global_irq_holder == (unsigned char) smp_processor_id();
+ int retval;
+ int local_enabled;
+ unsigned long flags;
+
+ __save_flags(flags);
+ local_enabled = (flags >> 15) & 1;
+ /* default to local */
+ retval = 2 + local_enabled;
+
+ /* check for global flags if we're not in an interrupt */
+ if (!local_irq_count[smp_processor_id()]) {
+ if (local_enabled)
+ retval = 1;
+ if (global_irq_holder == (unsigned char) smp_processor_id())
+ retval = 0;
+ }
+ return retval;
}
void __global_restore_flags(unsigned long flags)
{
switch (flags) {
case 0:
- release_irqlock(smp_processor_id());
- __sti();
+ __global_cli();
break;
case 1:
- __global_cli();
+ __global_sti();
+ break;
+ case 2:
+ __cli();
+ break;
+ case 3:
+ __sti();
break;
default:
printk("global_restore_flags: %08lx (%08lx)\n",
flags, (&flags)[-1]);
}
}
-#endif /* __SMP__ */
+#endif /* __SMP__ */
asmlinkage void do_IRQ(struct pt_regs *regs)
{
@@ -569,9 +659,6 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
if (!atomic_read(&n_lost_interrupts))
{
extern void smp_message_recv(void);
- goto out;
-
- ipi_count++;
smp_message_recv();
goto out;
}
@@ -584,20 +671,48 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
switch ( _machine )
{
case _MACH_Pmac:
- for (irq = max_irqs - 1; irq > 0; irq -= 32) {
- int i = irq >> 5, lz;
+ for (irq = max_real_irqs - 1; irq > 0; irq -= 32) {
+ int i = irq >> 5;
bits = ld_le32(&pmac_irq_hw[i]->flag)
| lost_interrupts[i];
if (bits == 0)
continue;
- /* lz = number of 0 bits to left of most sig. 1 */
- asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
- irq -= lz;
+ irq -= cntlzw(bits);
break;
}
+
+ /* Here, we handle interrupts coming from Gatwick,
+ * normal interrupt code will take care of acking and
+ * masking the irq on Gatwick itself but we ack&mask
+ * the Gatwick main interrupt on Heathrow now. It's
+ * unmasked later, after interrupt handling. -- BenH
+ */
+ if (irq == second_irq) {
+ mask_and_ack_irq(second_irq);
+ for (irq = max_irqs - 1; irq > max_real_irqs; irq -= 32) {
+ int i = irq >> 5;
+ bits = ld_le32(&pmac_irq_hw[i]->flag)
+ | lost_interrupts[i];
+ if (bits == 0)
+ continue;
+ irq -= cntlzw(bits);
+ break;
+ }
+ /* If not found, on exit, irq is 63 (128-1-32-32).
+ * We set it to -1 and revalidate second controller
+ */
+ if (irq < max_real_irqs) {
+ irq = -1;
+ unmask_irq(second_irq);
+ }
+#ifdef SHOW_GATWICK_IRQS
+ printk("Gatwick irq %d (i:%d, bits:0x%08lx\n", irq, i, bits);
+#endif
+ }
+
break;
case _MACH_chrp:
- irq = openpic_irq(0);
+ irq = openpic_irq(0);
if (irq == IRQ_8259_CASCADE)
{
/*
@@ -605,7 +720,7 @@ asmlinkage void do_IRQ(struct pt_regs *regs)
*
* This should go in the above mask/ack code soon. -- Cort
*/
- irq = *gg2_int_ack_special;
+ irq = *chrp_int_ack_special;
/*
* Acknowledge as soon as possible to allow i8259
* interrupt nesting
@@ -682,11 +797,13 @@ apus_out:
}
#endif
}
-
+
if (irq < 0) {
- printk(KERN_DEBUG "Bogus interrupt from PC = %lx\n", regs->nip);
+ printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+ irq, regs->nip);
+ spurious_interrupts++;
goto out;
- }
+ }
#else /* CONFIG_8xx */
/* For MPC8xx, read the SIVEC register and shift the bits down
@@ -695,9 +812,7 @@ apus_out:
bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec;
irq = bits >> 26;
#endif /* CONFIG_8xx */
-
mask_and_ack_irq(irq);
-
status = 0;
action = irq_action[irq];
kstat.irqs[cpu][irq]++;
@@ -707,14 +822,10 @@ apus_out:
do {
status |= action->flags;
action->handler(irq, action->dev_id, regs);
- /*if (status & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);*/
action = action->next;
} while ( action );
__cli();
- /* spin_lock(&irq_controller_lock);*/
unmask_irq(irq);
- /* spin_unlock(&irq_controller_lock);*/
} else {
#ifndef CONFIG_8xx
if ( irq == 7 ) /* i8259 gives us irq 7 on 'short' intrs */
@@ -723,8 +834,13 @@ apus_out:
disable_irq( irq );
}
+ /* This was a gatwick sub-interrupt, we re-enable them on Heathrow
+ now */
+ if (_machine == _MACH_Pmac && irq >= max_real_irqs)
+ unmask_irq(second_irq);
+
/* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */
-#ifndef CONFIG_8xx
+#ifndef CONFIG_8xx
if ( is_prep && (irq > 7) )
goto retry_cascade;
/* do_bottom_half is called if necessary from int_return in head.S */
@@ -750,12 +866,16 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
#ifdef SHOW_IRQ
printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n",
- irq,handler,devname,dev_id);
+ irq,(int)handler,devname,(int)dev_id);
#endif /* SHOW_IRQ */
if (irq >= NR_IRQS)
return -EINVAL;
+ /* Cannot allocate second controller IRQ */
+ if (irq == second_irq)
+ return -EBUSY;
+
if (!handler)
{
/* Free */
@@ -780,7 +900,7 @@ int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *)
cli();
action->handler = handler;
- action->flags = irqflags;
+ action->flags = irqflags;
action->mask = 0;
action->name = devname;
action->dev_id = dev_id;
@@ -851,6 +971,9 @@ __initfunc(void init_IRQ(void))
{
extern void xmon_irq(int, void *, struct pt_regs *);
int i;
+ struct device_node *irqctrler;
+ unsigned long addr;
+ struct device_node *np;
#ifndef CONFIG_8xx
switch (_machine)
@@ -860,23 +983,77 @@ __initfunc(void init_IRQ(void))
mask_irq = pmac_mask_irq;
unmask_irq = pmac_unmask_irq;
- /* G3 powermacs have 64 interrupts, others have 32 */
- max_irqs = (find_devices("mac-io") ? 64 : 32);
- printk("System has %d possible interrupts\n", max_irqs);
+ /* G3 powermacs have 64 interrupts, G3 Series PowerBook have 128,
+ others have 32 */
+ max_irqs = max_real_irqs = 32;
+ irqctrler = find_devices("mac-io");
+ if (irqctrler)
+ {
+ max_real_irqs = 64;
+ if (irqctrler->next)
+ max_irqs = 128;
+ else
+ max_irqs = 64;
+ }
+
+ /* get addresses of first controller */
+ if (irqctrler) {
+ if (irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 0; i < 2; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (2 - i) * 0x10);
+ }
+
+ /* get addresses of second controller */
+ irqctrler = (irqctrler->next) ? irqctrler->next : NULL;
+ if (irqctrler && irqctrler->n_addrs > 0) {
+ addr = (unsigned long)
+ ioremap(irqctrler->addrs[0].address, 0x40);
+ for (i = 2; i < 4; ++i)
+ pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+ (addr + (4 - i) * 0x10);
+ }
+ }
+ /* disable all interrupts in all controllers */
for (i = 0; i * 32 < max_irqs; ++i)
out_le32(&pmac_irq_hw[i]->enable, 0);
+
+
+ /* get interrupt line of secondary interrupt controller */
+ if (irqctrler) {
+ second_irq = irqctrler->intrs[0].line;
+ printk(KERN_INFO "irq: secondary controller on irq %d\n",
+ (int)second_irq);
+ if (device_is_compatible(irqctrler, "gatwick"))
+ pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+ enable_irq(second_irq);
+ }
+ printk("System has %d possible interrupts\n", max_irqs);
+ if (max_irqs != max_real_irqs)
+ printk(KERN_DEBUG "%d interrupts on main controller\n",
+ max_real_irqs);
+
#ifdef CONFIG_XMON
- request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0);
+ request_irq(20, xmon_irq, 0, "NMI", 0);
#endif /* CONFIG_XMON */
break;
case _MACH_chrp:
mask_and_ack_irq = chrp_mask_and_ack_irq;
mask_irq = chrp_mask_irq;
unmask_irq = chrp_unmask_irq;
- gg2_int_ack_special = (volatile unsigned char *)
- ioremap(GG2_INT_ACK_SPECIAL, 1);
- openpic_init();
+
+ if ( !(np = find_devices("pci") ) )
+ printk("Cannot find pci to get ack address\n");
+ else
+ {
+ chrp_int_ack_special = (volatile unsigned char *)
+ (*(unsigned long *)get_property(np,
+ "8259-interrupt-acknowledge", NULL));
+ }
+ openpic_init(1);
i8259_init();
cached_irq_mask[0] = cached_irq_mask[1] = ~0UL;
#ifdef CONFIG_XMON
@@ -935,3 +1112,61 @@ __initfunc(void init_IRQ(void))
}
#endif /* CONFIG_8xx */
}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+__pmac
+static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+ struct device_node *node;
+ static struct interrupt_info int_pool[4];
+
+ memset(int_pool, 0, sizeof(int_pool));
+ node = gw->child;
+ while(node)
+ {
+ /* Fix SCC */
+ if (strcasecmp(node->name, "escc") == 0)
+ if (node->child && node->child->n_intrs == 0)
+ {
+ node->child->n_intrs = 1;
+ node->child->intrs = &int_pool[0];
+ int_pool[0].line = 15+irq_base;
+ printk(KERN_INFO "irq: fixed SCC on second controller (%d)\n",
+ int_pool[0].line);
+ }
+ /* Fix media-bay & left SWIM */
+ if (strcasecmp(node->name, "media-bay") == 0)
+ {
+ struct device_node* ya_node;
+
+ if (node->n_intrs == 0)
+ {
+ node->n_intrs = 1;
+ node->intrs = &int_pool[1];
+ int_pool[1].line = 29+irq_base;
+ printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+ int_pool[1].line);
+ }
+ ya_node = node->child;
+ while(ya_node)
+ {
+ if ((strcasecmp(ya_node->name, "floppy") == 0) &&
+ ya_node->n_intrs == 0)
+ {
+ ya_node->n_intrs = 2;
+ ya_node->intrs = &int_pool[2];
+ int_pool[2].line = 19+irq_base;
+ int_pool[3].line = 1+irq_base;
+ printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+ int_pool[2].line, int_pool[3].line);
+ }
+ ya_node = ya_node->sibling;
+ }
+ }
+ node = node->sibling;
+ }
+
+}
+
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index de55ceaa3..f13508d96 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -363,22 +363,62 @@ _GLOBAL(_get_THRM1)
mfspr r3,THRM1
blr
+_GLOBAL(_get_THRM2)
+ mfspr r3,THRM2
+ blr
+
+_GLOBAL(_get_THRM3)
+ mfspr r3,THRM3
+ blr
+
_GLOBAL(_set_THRM1)
mtspr THRM1,r3
blr
+
+_GLOBAL(_set_THRM2)
+ mtspr THRM2,r3
+ blr
+
+_GLOBAL(_set_THRM3)
+ mtspr THRM3,r3
+ blr
_GLOBAL(_get_L2CR)
mfspr r3,L2CR
blr
-
+
+_GLOBAL(_set_L2CR)
+ mtspr L2CR,r3
+ blr
+
_GLOBAL(_get_PVR)
mfspr r3,PVR
blr
+/*
+ * These are used in the alignment trap handler when emulating
+ * single-precision loads and stores.
+ * We restore and save the fpscr so the task gets the same result
+ * and exceptions as if the cpu had performed the load or store.
+ */
_GLOBAL(cvt_fd)
cvt_fd:
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
lfs 0,0(r3)
stfd 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
+ blr
+
+_GLOBAL(cvt_df)
+cvt_df:
+ lfd 0,-4(r5) /* load up fpscr value */
+ mtfsf 0xff,0
+ lfd 0,0(r3)
+ stfs 0,0(r4)
+ mffs 0 /* save new fpscr value */
+ stfd 0,-4(r5)
blr
/*
@@ -390,12 +430,6 @@ _GLOBAL(get_SR)
mr r3,r4
blr
-_GLOBAL(cvt_df)
-cvt_df:
- lfd 0,0(r3)
- stfs 0,0(r4)
- blr
-
/*
* Create a kernel thread
* __kernel_thread(flags, fn, arg)
@@ -435,7 +469,6 @@ _GLOBAL(name) \
#define __NR__exit __NR_exit
SYSCALL(idle)
-SYSCALL(setup)
SYSCALL(sync)
SYSCALL(setsid)
SYSCALL(write)
@@ -455,7 +488,7 @@ SYSCALL(read)
.align 4
.globl sys_call_table
sys_call_table:
- .long sys_setup /* 0 */
+ .long sys_ni_syscall /* 0 - old "setup()" system call */
.long sys_exit
.long sys_fork
.long sys_read
@@ -472,12 +505,12 @@ sys_call_table:
.long sys_mknod
.long sys_chmod /* 15 */
.long sys_lchown
- .long sys_ni_syscall
+ .long sys_ni_syscall /* old break syscall holder */
.long sys_stat
.long sys_lseek
.long sys_getpid /* 20 */
.long sys_mount
- .long sys_umount
+ .long sys_oldumount
.long sys_setuid
.long sys_getuid
.long sys_stime /* 25 */
@@ -486,11 +519,11 @@ sys_call_table:
.long sys_fstat
.long sys_pause
.long sys_utime /* 30 */
- .long /*sys_stty*/ sys_ni_syscall
- .long /*sys_gtty*/ sys_ni_syscall
+ .long sys_ni_syscall /* old stty syscall holder */
+ .long sys_ni_syscall /* old gtty syscall holder */
.long sys_access
.long sys_nice
- .long /*sys_ftime*/ sys_ni_syscall /* 35 */
+ .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */
.long sys_sync
.long sys_kill
.long sys_rename
@@ -499,7 +532,7 @@ sys_call_table:
.long sys_dup
.long sys_pipe
.long sys_times
- .long /*sys_prof*/ sys_ni_syscall
+ .long sys_ni_syscall /* old prof syscall holder */
.long sys_brk /* 45 */
.long sys_setgid
.long sys_getgid
@@ -507,13 +540,13 @@ sys_call_table:
.long sys_geteuid
.long sys_getegid /* 50 */
.long sys_acct
- .long /*sys_phys*/ sys_ni_syscall
- .long /*sys_lock*/ sys_ni_syscall
+ .long sys_umount /* recycled never used phys() */
+ .long sys_ni_syscall /* old lock syscall holder */
.long sys_ioctl
.long sys_fcntl /* 55 */
- .long /*sys_mpx*/ sys_ni_syscall
+ .long sys_ni_syscall /* old mpx syscall holder */
.long sys_setpgid
- .long /*sys_ulimit*/ sys_ni_syscall
+ .long sys_ni_syscall /* old ulimit syscall holder */
.long sys_olduname
.long sys_umask /* 60 */
.long sys_chroot
@@ -544,7 +577,7 @@ sys_call_table:
.long sys_uselib
.long sys_swapon
.long sys_reboot
- .long old_readdir /* was sys_readdir */
+ .long old_readdir
.long sys_mmap /* 90 */
.long sys_munmap
.long sys_truncate
@@ -553,7 +586,7 @@ sys_call_table:
.long sys_fchown /* 95 */
.long sys_getpriority
.long sys_setpriority
- .long /*sys_profil*/ sys_ni_syscall
+ .long sys_ni_syscall /* old profil syscall holder */
.long sys_statfs
.long sys_fstatfs /* 100 */
.long sys_ioperm
@@ -592,7 +625,7 @@ sys_call_table:
.long sys_bdflush
.long sys_sysfs /* 135 */
.long sys_personality
- .long 0 /* for afs_syscall */
+ .long sys_ni_syscall /* for afs_syscall */
.long sys_setfsuid
.long sys_setfsgid
.long sys_llseek /* 140 */
@@ -620,22 +653,28 @@ sys_call_table:
.long sys_nanosleep
.long sys_mremap
.long sys_setresuid
- .long sys_getresuid /* 165 */
+ .long sys_getresuid /* 165 */
.long sys_query_module
.long sys_poll
.long sys_nfsservctl
- .long sys_setresgid
- .long sys_getresgid /* 170 */
+ .long sys_setresgid
+ .long sys_getresgid /* 170 */
.long sys_prctl
.long sys_rt_sigreturn
.long sys_rt_sigaction
.long sys_rt_sigprocmask
- .long sys_rt_sigpending /* 175 */
+ .long sys_rt_sigpending /* 175 */
.long sys_rt_sigtimedwait
.long sys_rt_sigqueueinfo
.long sys_rt_sigsuspend
.long sys_pread
- .long sys_pwrite /* 180 */
+ .long sys_pwrite /* 180 */
.long sys_chown
.long sys_getcwd
+ .long sys_capget
+ .long sys_capset
+ .long sys_sigaltstack /* 185 */
+ .long sys_sendfile
+ .long sys_ni_syscall /* streams1 */
+ .long sys_ni_syscall /* streams2 */
.space (NR_syscalls-183)*4
diff --git a/arch/ppc/kernel/openpic.c b/arch/ppc/kernel/openpic.c
index fd104ae9f..ec60ca5a6 100644
--- a/arch/ppc/kernel/openpic.c
+++ b/arch/ppc/kernel/openpic.c
@@ -133,7 +133,7 @@ static inline u_int openpic_readfield(volatile u_int *addr, u_int mask)
return val & mask;
}
-static inline void openpic_writefield(volatile u_int *addr, u_int mask,
+inline void openpic_writefield(volatile u_int *addr, u_int mask,
u_int field)
{
u_int val = openpic_read(addr);
@@ -173,7 +173,7 @@ static void openpic_safe_writefield(volatile u_int *addr, u_int mask,
* Initialize the OpenPIC
*/
-__initfunc(void openpic_init(void))
+__initfunc(void openpic_init(int main_pic))
{
u_int t, i;
u_int vendorid, devid, stepping, timerfreq;
@@ -233,41 +233,44 @@ __initfunc(void openpic_init(void))
else
printk("not set\n");
- /* Initialize timer interrupts */
- for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
- /* Disabled, Priority 0 */
- openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
- /* No processor */
- openpic_maptimer(i, 0);
+ if ( main_pic )
+ {
+ /* Initialize timer interrupts */
+ for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+ /* Disabled, Priority 0 */
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+ /* No processor */
+ openpic_maptimer(i, 0);
+ }
+
+ /* Initialize IPI interrupts */
+ for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+ /* Disabled, Priority 0 */
+ openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+ }
+
+ /* Initialize external interrupts */
+ /* SIOint (8259 cascade) is special */
+ openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
+ /* Processor 0 */
+ openpic_mapirq(0, 1<<0);
+ for (i = 1; i < NumSources; i++) {
+ /* Enabled, Priority 8 */
+ openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
+ i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+ /* Processor 0 */
+ openpic_mapirq(i, 1<<0);
+ }
+
+ /* Initialize the spurious interrupt */
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+
+ if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+ "82c59 cascade", NULL))
+ printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+ openpic_set_priority(0, 0);
+ openpic_disable_8259_pass_through();
}
-
- /* Initialize IPI interrupts */
- for (i = 0; i < OPENPIC_NUM_IPI; i++) {
- /* Disabled, Priority 0 */
- openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
- }
-
- /* Initialize external interrupts */
- /* SIOint (8259 cascade) is special */
- openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
- /* Processor 0 */
- openpic_mapirq(0, 1<<0);
- for (i = 1; i < NumSources; i++) {
- /* Enabled, Priority 8 */
- openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
- i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
- /* Processor 0 */
- openpic_mapirq(i, 1<<0);
- }
-
- /* Initialize the spurious interrupt */
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-
- if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
- "82c59 cascade", NULL))
- printk("Unable to get OpenPIC IRQ 0 for cascade\n");
- openpic_set_priority(0, 0);
- openpic_disable_8259_pass_through();
}
@@ -529,5 +532,3 @@ void openpic_set_sense(u_int irq, int sense)
OPENPIC_SENSE_LEVEL,
(sense ? OPENPIC_SENSE_LEVEL : 0));
}
-
-
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 235365f5e..359446f4f 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: pci.c,v 1.36 1998/08/02 23:22:11 paulus Exp $
+ * $Id: pci.c,v 1.39 1998/10/13 20:59:04 cort Exp $
* Common pmac/prep/chrp pci routines. -- Cort
*/
@@ -164,7 +164,7 @@ __initfunc(void
get_property(find_path_device("/"), "model", NULL),3) )
{
isa_io_base = 0xfe000000;
- set_config_access_method(raven);
+ set_config_access_method(grackle);
}
else
{
@@ -201,8 +201,22 @@ __initfunc(void pcibios_fixup(void))
route_pci_interrupts();
for(dev=pci_devices; dev; dev=dev->next)
{
+ /*
+ * Use our old hard-coded kludge to figure out what
+ * irq this device uses. This is necessary on things
+ * without residual data. -- Cort
+ */
unsigned char d = PCI_SLOT(dev->devfn);
dev->irq = Motherboard_routes[Motherboard_map[d]];
+#if 0
+ /*
+ * If we have residual data and if it knows about this
+ * device ask it what the irq is.
+ * -- Cort
+ */
+ ppcd = residual_find_device_id( ~0L, dev->device,
+ -1,-1,-1, 0);
+#endif
}
break;
case _MACH_chrp:
diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c
index 481f69e2c..7763059f7 100644
--- a/arch/ppc/kernel/pmac_pci.c
+++ b/arch/ppc/kernel/pmac_pci.c
@@ -40,7 +40,6 @@ static void add_bridges(struct device_node *dev, unsigned long *mem_ptr);
#define BANDIT_COHERENT 0x40
__pmac
-
void *pci_io_base(unsigned int bus)
{
struct bridge_data *bp;
@@ -50,6 +49,7 @@ void *pci_io_base(unsigned int bus)
return bp->io_base;
}
+__pmac
int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
unsigned char *devfn_ptr)
{
@@ -68,6 +68,7 @@ int pci_device_loc(struct device_node *dev, unsigned char *bus_ptr,
return 0;
}
+__pmac
int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char *val)
{
@@ -90,6 +91,7 @@ int pmac_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short *val)
{
@@ -114,6 +116,7 @@ int pmac_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int *val)
{
@@ -138,6 +141,7 @@ int pmac_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned char val)
{
@@ -159,6 +163,7 @@ int pmac_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned short val)
{
@@ -182,6 +187,7 @@ int pmac_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
return PCIBIOS_SUCCESSFUL;
}
+__pmac
int pmac_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
unsigned char offset, unsigned int val)
{
@@ -406,7 +412,7 @@ __initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_p
ioremap(0xfec00000, 0x1000);
bp->cfg_data = (volatile unsigned char *)
ioremap(0xfee00000, 0x1000);
- bp->io_base = (void *) ioremap(0xfe000000, 0x10000);
+ bp->io_base = (void *) ioremap(0xfe000000, 0x20000);
}
if (isa_io_base == 0)
isa_io_base = (unsigned long) bp->io_base;
diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c
index 7e44b404c..499e8b6a5 100644
--- a/arch/ppc/kernel/pmac_setup.c
+++ b/arch/ppc/kernel/pmac_setup.c
@@ -38,6 +38,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/major.h>
+#include <linux/blk.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/prom.h>
@@ -48,28 +49,89 @@
#include <asm/adb.h>
#include <asm/cuda.h>
#include <asm/pmu.h>
-#include <asm/mediabay.h>
#include <asm/ohare.h>
#include <asm/mediabay.h>
+#include <asm/feature.h>
#include "time.h"
-extern int root_mountflags;
-
unsigned char drive_info;
+extern char saved_command_line[];
+
#define DEFAULT_ROOT_DEVICE 0x0801 /* sda1 - slightly silly choice */
extern void zs_kgdb_hook(int tty_num);
static void ohare_init(void);
__pmac
-
int
pmac_get_cpuinfo(char *buffer)
{
int len;
- /* should find motherboard type here as well */
- len = sprintf(buffer,"machine\t\t: PowerMac\n");
+ struct device_node *np;
+ char *pp;
+ int plen;
+
+ /* find motherboard type */
+ len = sprintf(buffer, "machine\t\t: ");
+ np = find_devices("device-tree");
+ if (np != NULL) {
+ pp = (char *) get_property(np, "model", NULL);
+ if (pp != NULL)
+ len += sprintf(buffer+len, "%s\n", pp);
+ else
+ len += sprintf(buffer+len, "PowerMac\n");
+ pp = (char *) get_property(np, "compatible", &plen);
+ if (pp != NULL) {
+ len += sprintf(buffer+len, "motherboard\t:");
+ while (plen > 0) {
+ int l = strlen(pp) + 1;
+ len += sprintf(buffer+len, " %s", pp);
+ plen -= l;
+ pp += l;
+ }
+ buffer[len++] = '\n';
+ }
+ } else
+ len += sprintf(buffer+len, "PowerMac\n");
+
+ /* find l2 cache info */
+ np = find_devices("l2-cache");
+ if (np == 0)
+ np = find_type_devices("cache");
+ if (np != 0) {
+ unsigned int *ic = (unsigned int *)
+ get_property(np, "i-cache-size", NULL);
+ unsigned int *dc = (unsigned int *)
+ get_property(np, "d-cache-size", NULL);
+ len += sprintf(buffer+len, "L2 cache\t:");
+ if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+ len += sprintf(buffer+len, " %dK unified", *dc / 1024);
+ } else {
+ if (ic)
+ len += sprintf(buffer+len, " %dK instruction",
+ *ic / 1024);
+ if (dc)
+ len += sprintf(buffer+len, "%s %dK data",
+ (ic? " +": ""), *dc / 1024);
+ }
+ pp = get_property(np, "ram-type", NULL);
+ if (pp)
+ len += sprintf(buffer+len, " %s", pp);
+ buffer[len++] = '\n';
+ }
+
+ /* find ram info */
+ np = find_devices("memory");
+ if (np != 0) {
+ struct reg_property *reg = (struct reg_property *)
+ get_property(np, "reg", NULL);
+ if (reg != 0) {
+ len += sprintf(buffer+len, "memory\t\t: %dMB\n",
+ reg->size >> 20);
+ }
+ }
+
return len;
}
@@ -82,6 +144,13 @@ pmac_get_cpuinfo(char *buffer)
#include "../../../drivers/scsi/sd.h"
#include "../../../drivers/scsi/hosts.h"
+#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
+#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8)
+#define SD_MINOR_NUMBER(i) ((i) & 255)
+#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), SD_MINOR_NUMBER(i))
+#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4)
+
+__init
kdev_t sd_find_target(void *host, int tgt)
{
Scsi_Disk *dp;
@@ -90,7 +159,7 @@ kdev_t sd_find_target(void *host, int tgt)
for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp)
if (dp->device != NULL && dp->device->host == host
&& dp->device->id == tgt)
- return MKDEV(SCSI_DISK_MAJOR, i << 4);
+ return MKDEV_SD(i);
return 0;
}
#endif
@@ -99,13 +168,13 @@ kdev_t sd_find_target(void *host, int tgt)
* Dummy mksound function that does nothing.
* The real one is in the dmasound driver.
*/
+__pmac
static void
pmac_mksound(unsigned int hz, unsigned int ticks)
{
}
static volatile u32 *sysctrl_regs;
-static volatile u32 *feature_addr;
__initfunc(void
pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
@@ -137,10 +206,11 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
and some registers used by smp boards */
sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
__ioremap(0xffc00000, 0x400000, pgprot_val(PAGE_READONLY));
+ ohare_init();
*memory_start_p = pmac_find_bridges(*memory_start_p, *memory_end_p);
- ohare_init();
+ feature_init();
#ifdef CONFIG_KGDB
zs_kgdb_hook(0);
@@ -154,43 +224,30 @@ pmac_setup_arch(unsigned long *memory_start_p, unsigned long *memory_end_p))
#endif
kd_mksound = pmac_mksound;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+ else
+#endif
+ ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
}
__initfunc(static void ohare_init(void))
{
- struct device_node *np;
-
- np = find_devices("ohare");
- if (np == 0)
- return;
- if (np->next != 0)
- printk(KERN_WARNING "only using the first ohare\n");
- if (np->n_addrs == 0) {
- printk(KERN_ERR "No addresses for %s\n", np->full_name);
- return;
- }
- feature_addr = (volatile u32 *)
- ioremap(np->addrs[0].address + OHARE_FEATURE_REG, 4);
-
- if (find_devices("via-pmu") == 0) {
- printk(KERN_INFO "Twiddling the magic ohare bits\n");
- out_le32(feature_addr, STARMAX_FEATURES);
- } else {
- out_le32(feature_addr, in_le32(feature_addr) | PBOOK_FEATURES);
- printk(KERN_DEBUG "feature reg = %x\n", in_le32(feature_addr));
- }
-
/*
* Turn on the L2 cache.
* We assume that we have a PSX memory controller iff
* we have an ohare I/O controller.
*/
- if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
- if (sysctrl_regs[4] & 0x10)
- sysctrl_regs[4] |= 0x04000020;
- else
- sysctrl_regs[4] |= 0x04000000;
- printk(KERN_INFO "Level 2 cache enabled\n");
+ if (find_devices("ohare") != NULL) {
+ if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+ if (sysctrl_regs[4] & 0x10)
+ sysctrl_regs[4] |= 0x04000020;
+ else
+ sysctrl_regs[4] |= 0x04000000;
+ printk(KERN_INFO "Level 2 cache enabled\n");
+ }
}
}
@@ -201,8 +258,10 @@ int boot_target;
int boot_part;
kdev_t boot_dev;
-__initfunc(void powermac_init(void))
+void __init powermac_init(void)
{
+ if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) )
+ return;
adb_init();
pmac_nvram_init();
if (_machine == _MACH_Pmac) {
@@ -210,6 +269,7 @@ __initfunc(void powermac_init(void))
}
}
+#ifdef CONFIG_SCSI
__initfunc(void
note_scsi_host(struct device_node *node, void *host))
{
@@ -238,28 +298,67 @@ note_scsi_host(struct device_node *node, void *host))
}
}
}
+#endif
-__initfunc(void find_boot_device(void))
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+extern int pmac_ide_count;
+extern struct device_node *pmac_ide_node[];
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+__initfunc(kdev_t find_ide_boot(void))
{
- kdev_t dev;
+ char *p;
+ int i, n;
- if (kdev_t_to_nr(ROOT_DEV) != 0)
- return;
- ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
- if (boot_host == NULL)
- return;
+ if (bootdevice == NULL)
+ return 0;
+ p = strrchr(bootdevice, '/');
+ if (p == NULL)
+ return 0;
+ n = p - bootdevice;
+
+ /*
+ * Look through the list of IDE interfaces for this one.
+ */
+ for (i = 0; i < pmac_ide_count; ++i) {
+ char *name = pmac_ide_node[i]->full_name;
+ if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+ /* XXX should cope with the 2nd drive as well... */
+ return MKDEV(ide_majors[i], 0);
+ }
+ }
+
+ return 0;
+}
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+
+__initfunc(void find_boot_device(void))
+{
#ifdef CONFIG_SCSI
- dev = sd_find_target(boot_host, boot_target);
- if (dev == 0)
- return;
- boot_dev = MKDEV(MAJOR(dev), MINOR(dev) + boot_part);
+ if (boot_host != NULL) {
+ boot_dev = sd_find_target(boot_host, boot_target);
+ if (boot_dev != 0)
+ return;
+ }
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ boot_dev = find_ide_boot();
#endif
- /* XXX should cope with booting from IDE also */
}
-__initfunc(void note_bootable_part(kdev_t dev, int part))
+/* can't be initfunc - can be called whenever a disk is first accessed */
+__pmac
+void note_bootable_part(kdev_t dev, int part)
{
static int found_boot = 0;
+ char *p;
+
+ /* Do nothing if the root has been set already. */
+ if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
+ return;
+ p = strstr(saved_command_line, "root=");
+ if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+ return;
if (!found_boot) {
find_boot_device();
diff --git a/arch/ppc/kernel/pmac_support.c b/arch/ppc/kernel/pmac_support.c
index c88c8bae9..0196c5eb6 100644
--- a/arch/ppc/kernel/pmac_support.c
+++ b/arch/ppc/kernel/pmac_support.c
@@ -25,8 +25,7 @@ static int nvram_mult;
#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */
-__pmac
-
+__init
void pmac_nvram_init(void)
{
struct device_node *dp;
diff --git a/arch/ppc/kernel/ppc_defs.h b/arch/ppc/kernel/ppc_defs.h
new file mode 100644
index 000000000..83315a2ae
--- /dev/null
+++ b/arch/ppc/kernel/ppc_defs.h
@@ -0,0 +1,69 @@
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+#define KERNELBASE -1073741824
+#define STATE 0
+#define NEXT_TASK 48
+#define COUNTER 24
+#define PROCESSOR 36
+#define SIGPENDING 8
+#define TSS 568
+#define MM 872
+#define TASK_STRUCT_SIZE 912
+#define KSP 0
+#define PG_TABLES 4
+#define PGD 8
+#define LAST_SYSCALL 20
+#define PT_REGS 12
+#define PF_TRACESYS 32
+#define TASK_FLAGS 4
+#define NEED_RESCHED 20
+#define TSS_FPR0 24
+#define TSS_FPSCR 284
+#define TSS_SMP_FORK_RET 288
+#define TASK_UNION_SIZE 8192
+#define STACK_FRAME_OVERHEAD 16
+#define INT_FRAME_SIZE 192
+#define GPR0 16
+#define GPR1 20
+#define GPR2 24
+#define GPR3 28
+#define GPR4 32
+#define GPR5 36
+#define GPR6 40
+#define GPR7 44
+#define GPR8 48
+#define GPR9 52
+#define GPR10 56
+#define GPR11 60
+#define GPR12 64
+#define GPR13 68
+#define GPR14 72
+#define GPR15 76
+#define GPR16 80
+#define GPR17 84
+#define GPR18 88
+#define GPR19 92
+#define GPR20 96
+#define GPR21 100
+#define GPR22 104
+#define GPR23 108
+#define GPR24 112
+#define GPR25 116
+#define GPR26 120
+#define GPR27 124
+#define GPR28 128
+#define GPR29 132
+#define GPR30 136
+#define GPR31 140
+#define _NIP 144
+#define _MSR 148
+#define _CTR 156
+#define _LINK 160
+#define _CCR 168
+#define _XER 164
+#define _DAR 180
+#define _DSISR 184
+#define ORIG_GPR3 152
+#define RESULT 188
+#define TRAP 176
diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
index c1445d393..3aa0534ea 100644
--- a/arch/ppc/kernel/ppc_htab.c
+++ b/arch/ppc/kernel/ppc_htab.c
@@ -1,5 +1,5 @@
/*
- * $Id: ppc_htab.c,v 1.21 1998/05/13 22:34:55 cort Exp $
+ * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $
*
* PowerPC hash table management proc entry. Will show information
* about the current hash table and will allow changes to it.
@@ -17,6 +17,8 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -31,6 +33,8 @@ static ssize_t ppc_htab_read(struct file * file, char * buf,
static ssize_t ppc_htab_write(struct file * file, const char * buffer,
size_t count, loff_t *ppos);
static long long ppc_htab_lseek(struct file * file, loff_t offset, int orig);
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp);
extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
@@ -519,3 +523,147 @@ ppc_htab_lseek(struct file * file, loff_t offset, int orig)
return(-EINVAL);
}
}
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+ void *buffer, size_t *lenp)
+{
+ int vleft, first=1, len, left, val;
+ #define TMPBUFLEN 256
+ char buf[TMPBUFLEN], *p;
+
+ if ( (_get_PVR() >> 16) != 8) return -EFAULT;
+
+ if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ vleft = table->maxlen / sizeof(int);
+ left = *lenp;
+
+ for (; left /*&& vleft--*/; first=0) {
+ if (write) {
+ while (left) {
+ char c;
+ if(get_user(c,(char *) buffer))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ ((char *) buffer)++;
+ }
+ if (!left)
+ break;
+ len = left;
+ if (len > TMPBUFLEN-1)
+ len = TMPBUFLEN-1;
+ if(copy_from_user(buf, buffer, len))
+ return -EFAULT;
+ buf[len] = 0;
+ p = buf;
+ if (*p < '0' || *p > '9')
+ break;
+ val = simple_strtoul(p, &p, 0);
+ len = p-buf;
+ if ((len < left) && *p && !isspace(*p))
+ break;
+ buffer += len;
+ left -= len;
+ _set_L2CR(val);
+ while ( _get_L2CR() & 0x1 )
+ /* wait for invalidate to finish */;
+
+ } else {
+ p = buf;
+ if (!first)
+ *p++ = '\t';
+ val = _get_L2CR();
+ p += sprintf(p, "%08x: ", val);
+ p += sprintf(p, " %s",
+ (val&0x80000000)?"enabled":"disabled");
+ p += sprintf(p,",%sparity",(val&0x40000000)?"":"no ");
+
+ switch( (val >> 28) & 0x3 )
+ {
+ case 1: p += sprintf(p,",256Kb");
+ break;
+ case 2: p += sprintf(p,",512Kb");
+ break;
+ case 3: p += sprintf(p,",1M");
+ break;
+ default: p += sprintf(p,",unknown size");
+ break;
+ }
+
+
+ switch( (val >> 25) & 0x7 )
+ {
+ case 0: p += sprintf(p,",clock disabled");
+ break;
+ case 1: p += sprintf(p,",+1 clock");
+ break;
+ case 2: p += sprintf(p,",+1.5 clock");
+ break;
+ case 7:
+ case 3: p += sprintf(p,",reserved clock");
+ break;
+ case 4: p += sprintf(p,",+2 clock");
+ break;
+ case 5: p += sprintf(p,",+2.5 clock");
+ break;
+ case 6: p += sprintf(p,",+3 clock");
+ break;
+ }
+
+ switch( (val >> 23) & 0x2 )
+ {
+ case 0: p += sprintf(p,",flow-through burst SRAM");
+ break;
+ case 1: p += sprintf(p,",reserved SRAM");
+ break;
+ case 2: p += sprintf(p,",pipelined burst SRAM");
+ break;
+ case 3: p += sprintf(p,",pipelined late-write SRAM");
+ break;
+ }
+
+ p += sprintf(p,"%s",(val>>22)?"":",data only");
+ p += sprintf(p,"%s",(val>>20)?",ZZ enabled":"");
+ p += sprintf(p,",%s",(val>>19)?"write-through":"copy-back");
+ p += sprintf(p,",%sns hold",(val>>16)?"1.0":"0.5");
+
+ p += sprintf(p,"\n");
+
+ len = strlen(buf);
+ if (len > left)
+ len = left;
+ if(copy_to_user(buffer, buf, len))
+ return -EFAULT;
+ left -= len;
+ buffer += len;
+ break;
+ }
+ }
+
+ if (!write && !first && left) {
+ if(put_user('\n', (char *) buffer))
+ return -EFAULT;
+ left--, buffer++;
+ }
+ if (write) {
+ p = (char *) buffer;
+ while (left) {
+ char c;
+ if(get_user(c, p++))
+ return -EFAULT;
+ if (!isspace(c))
+ break;
+ left--;
+ }
+ }
+ if (write && first)
+ return -EINVAL;
+ *lenp -= left;
+ filp->f_pos += *lenp;
+ return 0;
+}
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index e869a31dd..ea5f6db0d 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -11,6 +11,7 @@
#include <asm/semaphore.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/ide.h>
#include <asm/io.h>
#include <asm/atomic.h>
#include <asm/bitops.h>
@@ -23,6 +24,7 @@
#include <asm/system.h>
#include <asm/pci-bridge.h>
#include <asm/irq.h>
+#include <asm/feature.h>
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
@@ -56,10 +58,10 @@ EXPORT_SYMBOL(SingleStepException);
EXPORT_SYMBOL(sys_sigreturn);
EXPORT_SYMBOL(n_lost_interrupts);
EXPORT_SYMBOL(do_lost_interrupts);
-EXPORT_SYMBOL(__ppc_bh_counter);
EXPORT_SYMBOL(enable_irq);
EXPORT_SYMBOL(disable_irq);
EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(isa_mem_base);
@@ -138,11 +140,12 @@ EXPORT_SYMBOL(ioremap);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(ide_insw);
+EXPORT_SYMBOL(ide_outsw);
+
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(__kernel_thread);
-EXPORT_SYMBOL(__down_interruptible);
-
EXPORT_SYMBOL(__cli);
EXPORT_SYMBOL(__sti);
/*EXPORT_SYMBOL(__restore_flags);*/
@@ -154,6 +157,10 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(xchg_u32);
+#ifndef CONFIG_MACH_SPECIFIC
+EXPORT_SYMBOL(_machine);
+#endif
+
EXPORT_SYMBOL(adb_request);
EXPORT_SYMBOL(adb_autopoll);
EXPORT_SYMBOL(adb_register);
@@ -169,10 +176,15 @@ EXPORT_SYMBOL(sleep_notifier_list);
EXPORT_SYMBOL(abort);
EXPORT_SYMBOL(find_devices);
EXPORT_SYMBOL(find_type_devices);
+EXPORT_SYMBOL(find_compatible_devices);
EXPORT_SYMBOL(find_path_device);
+EXPORT_SYMBOL(find_phandle);
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_device_loc);
+EXPORT_SYMBOL(feature_set);
+EXPORT_SYMBOL(feature_clear);
+EXPORT_SYMBOL(feature_test);
EXPORT_SYMBOL(note_scsi_host);
EXPORT_SYMBOL(kd_mksound);
#ifdef CONFIG_PMAC
diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c
index 7f45756cb..b7d94d208 100644
--- a/arch/ppc/kernel/prep_pci.c
+++ b/arch/ppc/kernel/prep_pci.c
@@ -1,5 +1,5 @@
/*
- * $Id: prep_pci.c,v 1.20 1998/06/19 16:48:45 cort Exp $
+ * $Id: prep_pci.c,v 1.23 1998/10/21 10:52:24 cort Exp $
* PReP pci functions.
* Originally by Gary Thomas
* rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -234,6 +234,44 @@ static char ibm8xx_pci_IRQ_routes[] __prepdata = {
15, /* Line 4 */
};
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+ 0, /* Slot 0 - unused */
+ 0, /* Slot 1 - unused */
+ 0, /* Slot 2 - unused */
+ 0, /* Slot 3 - unused */
+ 0, /* Slot 4 - unused */
+ 0, /* Slot 5 - unused */
+ 0, /* Slot 6 - unused */
+ 0, /* Slot 7 - unused */
+ 0, /* Slot 8 - unused */
+ 0, /* Slot 9 - unused */
+ 0, /* Slot 10 - unused */
+ 0, /* Slot 11 - */
+ 1, /* Slot 12 - SCSI */
+ 2, /* Slot 13 - */
+ 2, /* Slot 14 - */
+ 1, /* Slot 15 - */
+ 1, /* Slot 16 - */
+ 0, /* Slot 17 - */
+ 2, /* Slot 18 - */
+ 0, /* Slot 19 - */
+ 0, /* Slot 20 - */
+ 0, /* Slot 21 - */
+ 2, /* Slot 22 - */
+};
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+ 0, /* Line 0 - unused */
+ 13, /* Line 1 */
+ 10, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+
+
/* IBM Nobis and 850 */
static char Nobis_pci_IRQ_map[23] __prepdata ={
0, /* Slot 0 - unused */
@@ -424,6 +462,11 @@ __initfunc(unsigned long route_pci_interrupts(void))
Motherboard_map = Utah_pci_IRQ_map;
Motherboard_routes = Utah_pci_IRQ_routes;
break;
+ case 0xE0: /* MTX -- close enough?? to Genesis, so reuse it */
+ Motherboard_map_name = "Motorola MTX";
+ Motherboard_map = Genesis_pci_IRQ_map;
+ Motherboard_routes = Genesis_pci_IRQ_routes;
+ break;
case 0x40: /* PowerStack */
default: /* Can't hurt, can it? */
Motherboard_map_name = "Blackhawk (Powerstack)";
@@ -434,16 +477,31 @@ __initfunc(unsigned long route_pci_interrupts(void))
} else if ( _prep_type == _PREP_IBM )
{
unsigned char pl_id;
-
- if (inb(0x0852) == 0xFF) {
+ /*
+ * my carolina is 0xf0
+ * 6015 has 0xfc
+ * -- Cort
+ */
+ printk("IBM ID: %08x\n", inb(0x0852));
+ switch(inb(0x0852))
+ {
+ case 0xff:
Motherboard_map_name = "IBM 850/860 Portable\n";
Motherboard_map = Nobis_pci_IRQ_map;
Motherboard_routes = Nobis_pci_IRQ_routes;
- } else {
+ break;
+ case 0xfc:
+ Motherboard_map_name = "IBM 6015";
+ Motherboard_map = ibm6015_pci_IRQ_map;
+ Motherboard_routes = ibm6015_pci_IRQ_routes;
+ break;
+ default:
Motherboard_map_name = "IBM 8xx (Carolina)";
Motherboard_map = ibm8xx_pci_IRQ_map;
Motherboard_routes = ibm8xx_pci_IRQ_routes;
+ break;
}
+
/*printk("Changing IRQ mode\n");*/
pl_id=inb(0x04d0);
/*printk("Low mask is %#0x\n", pl_id);*/
diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c
index 406c18281..e596f9ea5 100644
--- a/arch/ppc/kernel/prep_setup.c
+++ b/arch/ppc/kernel/prep_setup.c
@@ -76,26 +76,70 @@ prep_get_cpuinfo(char *buffer)
#endif
len = sprintf(buffer,"machine\t\t: PReP %s\n",Motherboard_map_name);
+
- len += sprintf(buffer+len,"L2\t\t: ");
- switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+ switch ( _prep_type )
{
- case L2CACHE_512KB:
- len += sprintf(buffer+len,"512Kb\n");
- break;
- case L2CACHE_256KB:
- len += sprintf(buffer+len,"256Kb\n");
- break;
- case L2CACHE_1MB:
- len += sprintf(buffer+len,"1MB\n");
+ case _PREP_IBM:
+ if ((*(unsigned char *)0x8000080c) & (1<<6))
+ len += sprintf(buffer+len,"Upgrade CPU\n");
+ len += sprintf(buffer+len,"L2\t\t: ");
+ if ((*(unsigned char *)0x8000080c) & (1<<7))
+ {
+ len += sprintf(buffer+len,"not present\n");
+ goto no_l2;
+ }
+ len += sprintf(buffer+len,"%sKb,",
+ (((*(unsigned char *)0x8000080d)>>2)&1)?"512":"256");
+ len += sprintf(buffer+len,"%sync\n",
+ ((*(unsigned char *)0x8000080d)>>7) ? "":"a");
break;
- case L2CACHE_NONE:
- len += sprintf(buffer+len,"none\n");
+ case _PREP_Motorola:
+ len += sprintf(buffer+len,"L2\t\t: ");
+ switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+ {
+ case L2CACHE_512KB:
+ len += sprintf(buffer+len,"512Kb");
+ break;
+ case L2CACHE_256KB:
+ len += sprintf(buffer+len,"256Kb");
+ break;
+ case L2CACHE_1MB:
+ len += sprintf(buffer+len,"1MB");
+ break;
+ case L2CACHE_NONE:
+ len += sprintf(buffer+len,"none\n");
+ goto no_l2;
+ break;
+ default:
+ len += sprintf(buffer+len, "%x\n",
+ *((unsigned char *)CACHECRBA));
+ }
+
+ len += sprintf(buffer+len,",parity %s",
+ (*((unsigned char *)CACHECRBA) & L2CACHE_PARITY) ?
+ "enabled" : "disabled");
+
+ len += sprintf(buffer+len, " SRAM:");
+
+ switch ( ((*((unsigned char *)CACHECRBA) & 0xf0) >> 4) & ~(0x3) )
+ {
+ case 1: len += sprintf(buffer+len,
+ "synchronous,parity,flow-through\n");
+ break;
+ case 2: len += sprintf(buffer+len,"asynchronous,no parity\n");
+ break;
+ case 3: len += sprintf(buffer+len,"asynchronous,parity\n");
+ break;
+ default:len += sprintf(buffer+len,
+ "synchronous,pipelined,no parity\n");
+ break;
+ }
break;
- default:
- len += sprintf(buffer+len,"%x\n", *((unsigned char *)CACHECRBA));
}
-
+
+
+no_l2:
if ( res->ResidualLength == 0 )
return len;
@@ -111,20 +155,6 @@ prep_get_cpuinfo(char *buffer)
}
len += sprintf(buffer+len,"\n");
-#if 0
- /* L2 */
- if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */
- {
- len += sprintf(buffer+len,"l2\t\t: %dkB %s\n",
- ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256,
- (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled");
- }
- else
- {
- len += sprintf(buffer+len,"l2\t\t: not present\n");
- }
-#endif
-
return len;
}
@@ -155,6 +185,9 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
break;
}
+
+ /* Enable L2. Assume we don't need to flush -- Cort*/
+ *(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3;
/* make the serial port the console */
/* strcat(cmd_line,"console=ttyS0,9600n8"); */
@@ -163,7 +196,7 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
sprintf(cmd_line,"%s console=tty0 console=ttyS0,9600n8", cmd_line);
printk("Boot arguments: %s\n", cmd_line);
-#ifdef CONFIG_CS4232
+#ifdef CONFIG_SOUND_CS4232
/*
* setup proper values for the cs4232 driver so we don't have
* to recompile for the motorola or ibm workstations sound systems.
@@ -200,8 +233,7 @@ prep_setup_arch(unsigned long * memory_start_p, unsigned long * memory_end_p))
}
}
}
-#endif /* CONFIG_CS4232 */
-
+#endif /* CONFIG_SOUND_CS4232 */
/*print_residual_device_info();*/
request_region(0x20,0x20,"pic1");
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index 9cf88c8a4..5ea55cee9 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -163,14 +163,19 @@ switch_to(struct task_struct *prev, struct task_struct *new)
#endif
#ifdef SHOW_TASK_SWITCHES
- printk("%s/%d -> %s/%d NIP %08lx cpu %d sfr %d lock %x\n",
+ printk("%s/%d -> %s/%d NIP %08lx cpu %d lock %x root %x/%x\n",
prev->comm,prev->pid,
new->comm,new->pid,new->tss.regs->nip,new->processor,
- new->tss.smp_fork_ret,scheduler_lock.lock);
+ scheduler_lock.lock,new->fs->root,prev->fs->root);
#endif
#ifdef __SMP__
/* avoid complexity of lazy save/restore of fpu
- * by just saving it every time we switch out -- Cort
+ * by just saving it every time we switch out if
+ * this task used the fpu during the last quantum.
+ *
+ * If it tries to use the fpu again, it'll trap and
+ * reload its fp regs.
+ * -- Cort
*/
if ( prev->tss.regs->msr & MSR_FP )
smp_giveup_fpu(prev);
@@ -349,6 +354,9 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
regs->gpr[1] = sp;
regs->msr = MSR_USER;
shove_aux_table(sp);
+ if (last_task_used_math == current)
+ last_task_used_math = 0;
+ current->tss.fpscr = 0;
}
asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -380,6 +388,7 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
{
int res;
+
lock_kernel();
res = do_fork(SIGCHLD, regs->gpr[1], regs);
/* only parent returns here */
@@ -401,18 +410,23 @@ asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
{
int error;
char * filename;
-
lock_kernel();
filename = getname((char *) a0);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
+#ifdef __SMP__
+ if ( regs->msr & MSR_FP )
+ smp_giveup_fpu(current);
+#else
if ( last_task_used_math == current )
- last_task_used_math = NULL;
+ giveup_fpu();
+#endif
error = do_execve(filename, (char **) a1, (char **) a2, regs);
putname(filename);
out:
unlock_kernel();
+
return error;
}
@@ -446,7 +460,7 @@ __initfunc(int ll_printk(const char *fmt, ...))
int i;
va_start(args, fmt);
- i=sprintf(buf,fmt,args);
+ i=vsprintf(buf,fmt,args);
ll_puts(buf);
va_end(args);
return i;
@@ -455,6 +469,19 @@ __initfunc(int ll_printk(const char *fmt, ...))
int lines = 24, cols = 80;
int orig_x = 0, orig_y = 0;
+void puthex(unsigned long val)
+{
+ unsigned char buf[10];
+ int i;
+ for (i = 7; i >= 0; i--)
+ {
+ buf[i] = "0123456789ABCDEF"[val & 0x0F];
+ val >>= 4;
+ }
+ buf[8] = '\0';
+ prom_print(buf);
+}
+
__initfunc(void ll_puts(const char *s))
{
int x,y;
diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c
index 047d590ed..da9d7a04c 100644
--- a/arch/ppc/kernel/prom.c
+++ b/arch/ppc/kernel/prom.c
@@ -1,5 +1,5 @@
/*
- * $Id: prom.c,v 1.32 1998/07/28 20:28:46 geert Exp $
+ * $Id: prom.c,v 1.46 1998/11/11 03:55:09 paulus Exp $
*
* Procedures for interfacing to the Open Firmware PROM on
* Power Macintosh computers.
@@ -15,11 +15,14 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/version.h>
#include <asm/prom.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/irq.h>
#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
/*
* Properties whose value is longer than this get excluded from our
@@ -60,6 +63,13 @@ struct isa_reg_property {
unsigned size;
};
+struct pci_intr_map {
+ struct pci_address addr;
+ unsigned dunno;
+ phandle int_ctrler;
+ unsigned intr;
+};
+
typedef unsigned long interpret_func(struct device_node *, unsigned long);
static interpret_func interpret_pci_props;
static interpret_func interpret_dbdma_props;
@@ -67,8 +77,12 @@ static interpret_func interpret_isa_props;
static interpret_func interpret_macio_props;
static interpret_func interpret_root_props;
+#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
+#define FB_MAX 8
+#endif
char *prom_display_paths[FB_MAX] __initdata = { 0, };
unsigned int prom_num_displays = 0;
+char *of_stdout_device = 0;
prom_entry prom = 0;
ihandle prom_chosen = 0, prom_stdout = 0;
@@ -84,20 +98,49 @@ unsigned int old_rtas = 0;
static struct device_node *allnodes = 0;
+static void clearscreen(void);
+
+#ifdef CONFIG_BOOTX_TEXT
+
+static void drawchar(char c);
+static void drawstring(const char *c);
+static void scrollscreen(void);
+
+static void draw_byte(unsigned char c, long locX, long locY);
+static void draw_byte_32(unsigned char *bits, unsigned long *base);
+static void draw_byte_16(unsigned char *bits, unsigned long *base);
+static void draw_byte_8(unsigned char *bits, unsigned long *base);
+
+static long g_loc_X;
+static long g_loc_Y;
+static long g_max_loc_X;
+static long g_max_loc_Y;
+
+#define cmapsz (16*256)
+
+static unsigned char vga_font[cmapsz];
+
+#endif
+
+
static void *call_prom(const char *service, int nargs, int nret, ...);
- void prom_print(const char *msg);
static void prom_exit(void);
static unsigned long copy_device_tree(unsigned long, unsigned long);
static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
unsigned long, struct device_node ***);
static unsigned long finish_node(struct device_node *, unsigned long,
interpret_func *);
+static void relocate_nodes(void);
static unsigned long check_display(unsigned long);
static int prom_next_node(phandle *);
+static void *early_get_property(unsigned long, unsigned long, char *);
extern void enter_rtas(void *);
extern unsigned long reloc_offset(void);
+extern char cmd_line[512]; /* XXX */
+boot_infos_t *boot_infos = 0; /* init it so it's in data segment not bss */
+
/*
* prom_init() is called very early on, before the kernel text
* and data have been mapped to KERNELBASE. At this point the code
@@ -124,7 +167,7 @@ extern unsigned long reloc_offset(void);
#define ALIGN(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
-__openfirmware
+__init
static void
prom_exit()
{
@@ -139,7 +182,7 @@ prom_exit()
;
}
-__openfirmware
+__init
void
prom_enter(void)
{
@@ -152,7 +195,7 @@ prom_enter(void)
RELOC(prom)(&args);
}
-__openfirmware
+__init
static void *
call_prom(const char *service, int nargs, int nret, ...)
{
@@ -174,13 +217,23 @@ call_prom(const char *service, int nargs, int nret, ...)
return prom_args.args[nargs];
}
-__openfirmware
+__init
void
prom_print(const char *msg)
{
const char *p, *q;
unsigned long offset = reloc_offset();
+ if (RELOC(prom_stdout) == 0)
+ {
+#ifdef CONFIG_BOOTX_TEXT
+ if (RELOC(boot_infos) != 0)
+ drawstring(msg);
+#endif
+ return;
+ }
+
+
for (p = msg; *p != 0; p = q) {
for (q = p; *q != 0 && *q != '\n'; ++q)
;
@@ -199,7 +252,7 @@ prom_print(const char *msg)
* We enter here early on, when the Open Firmware prom is still
* handling exceptions and the MMU hash table for us.
*/
-__openfirmware
+__init
void
prom_init(int r3, int r4, prom_entry pp)
{
@@ -208,13 +261,59 @@ prom_init(int r3, int r4, prom_entry pp)
unsigned long offset = reloc_offset();
int l;
char *p, *d;
+
+ /* check if we're apus, return if we are */
+ if ( r3 == 0x61707573 )
+ return;
+
+ /* If we came here from BootX, clear the screen,
+ * set up some pointers and return. */
+ if (r3 == 0x426f6f58 && pp == NULL) {
+ boot_infos_t *bi = (boot_infos_t *) r4;
+ unsigned long space;
+ unsigned long ptr, x;
+ char *model;
+
+ RELOC(boot_infos) = PTRUNRELOC(bi);
+
+ clearscreen();
+
+#ifdef CONFIG_BOOTX_TEXT
+ RELOC(g_loc_X) = 0;
+ RELOC(g_loc_Y) = 0;
+ RELOC(g_max_loc_X) = (bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) / 8;
+ RELOC(g_max_loc_Y) = (bi->dispDeviceRect[3] - bi->dispDeviceRect[1]) / 16;
+ prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE " booting...\n"));
+#endif
+
+ /*
+ * XXX If this is an iMac, turn off the USB controller.
+ */
+ model = (char *) early_get_property
+ (r4 + bi->deviceTreeOffset, 4, RELOC("model"));
+ if (model && strcmp(model, RELOC("iMac,1")) == 0) {
+ out_le32((unsigned *)0x80880008, 1); /* XXX */
+ }
+
+ space = bi->deviceTreeOffset + bi->deviceTreeSize;
+ if (bi->ramDisk)
+ space = bi->ramDisk + bi->ramDiskSize;
+ RELOC(klimit) = PTRUNRELOC((char *) bi + space);
+
+ /*
+ * Touch each page to make sure the PTEs for them
+ * are in the hash table - the aim is to try to avoid
+ * getting DSI exceptions while copying the kernel image.
+ */
+ for (ptr = (KERNELBASE + offset) & PAGE_MASK;
+ ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
+ x = *(volatile unsigned long *)ptr;
- /* check if we're prep, return if we are */
- if ( *(unsigned long *)(0) == 0xdeadc0de )
return;
+ }
- /* check if we're apus, return if we are */
- if ( r3 == 0x61707573 )
+ /* check if we're prep, return if we are */
+ if ( *(unsigned long *)(0) == 0xdeadc0de )
return;
/* First get a handle for the stdout device */
@@ -228,9 +327,16 @@ prom_init(int r3, int r4, prom_entry pp)
sizeof(prom_stdout)) <= 0)
prom_exit();
- /* Get the boot device and translate it to a full OF pathname. */
+ /* Get the full OF pathname of the stdout device */
mem = (unsigned long) RELOC(klimit) + offset;
p = (char *) mem;
+ memset(p, 0, 256);
+ call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);
+ RELOC(of_stdout_device) = PTRUNRELOC(p);
+ mem += strlen(p) + 1;
+
+ /* Get the boot device and translate it to a full OF pathname. */
+ p = (char *) mem;
l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
RELOC("bootpath"), p, 1<<20);
if (l > 0) {
@@ -297,14 +403,15 @@ prom_init(int r3, int r4, prom_entry pp)
* So we check whether we will need to open the display,
* and if so, open it now.
*/
-__openfirmware
+__init
static unsigned long
check_display(unsigned long mem)
{
phandle node;
ihandle ih;
+ int i;
unsigned long offset = reloc_offset();
- char type[16], name[16], *path;
+ char type[16], *path;
for (node = 0; prom_next_node(&node); ) {
type[0] = 0;
@@ -323,27 +430,30 @@ check_display(unsigned long mem)
ih = call_prom(RELOC("open"), 1, 1, path);
if (ih == 0 || ih == (ihandle) -1) {
prom_print(RELOC("... failed\n"));
- /* platinum kludge. platinum is a valid display,
- * but not handled by OF. Make sure prom_num_display
- * is incremented anyway
- */
- call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
- name, sizeof(name));
- if (strncmp(name, RELOC("platinum"), 8))
- continue;
- } else {
- prom_print(RELOC("... ok\n"));
+ continue;
}
+ prom_print(RELOC("... ok\n"));
+
+ /*
+ * If this display is the device that OF is using for stdout,
+ * move it to the front of the list.
+ */
mem += strlen(path) + 1;
- RELOC(prom_display_paths[RELOC(prom_num_displays)++])
- = PTRUNRELOC(path);
+ i = RELOC(prom_num_displays)++;
+ if (RELOC(of_stdout_device) != 0 && i > 0
+ && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
+ for (; i > 0; --i)
+ RELOC(prom_display_paths[i])
+ = RELOC(prom_display_paths[i-1]);
+ }
+ RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
if (RELOC(prom_num_displays) >= FB_MAX)
break;
}
return ALIGN(mem);
}
-__openfirmware
+__init
static int
prom_next_node(phandle *nodep)
{
@@ -366,7 +476,7 @@ prom_next_node(phandle *nodep)
/*
* Make a copy of the device tree from the PROM.
*/
-__openfirmware
+__init
static unsigned long
copy_device_tree(unsigned long mem_start, unsigned long mem_end)
{
@@ -387,7 +497,7 @@ copy_device_tree(unsigned long mem_start, unsigned long mem_end)
return new_start;
}
-__openfirmware
+__init
static unsigned long
inspect_node(phandle node, struct device_node *dad,
unsigned long mem_start, unsigned long mem_end,
@@ -472,19 +582,41 @@ inspect_node(phandle node, struct device_node *dad,
* It traverses the device tree and fills in the name, type,
* {n_}addrs and {n_}intrs fields of each node.
*/
-__openfirmware
+__init
void
finish_device_tree(void)
{
unsigned long mem = (unsigned long) klimit;
+ if (boot_infos)
+ relocate_nodes();
mem = finish_node(allnodes, mem, NULL);
printk(KERN_INFO "device tree used %lu bytes\n",
mem - (unsigned long) allnodes);
klimit = (char *) mem;
}
-__openfirmware
+/*
+ * early_get_property is used to access the device tree image prepared
+ * by BootX very early on, before the pointers in it have been relocated.
+ */
+__init void *
+early_get_property(unsigned long base, unsigned long node, char *prop)
+{
+ struct device_node *np = (struct device_node *)(base + node);
+ struct property *pp;
+
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ pp = (struct property *) (base + (unsigned long)pp);
+ if (strcmp((char *)((unsigned long)pp->name + base),
+ prop) == 0) {
+ return (void *)((unsigned long)pp->value + base);
+ }
+ }
+ return 0;
+}
+
+__init
static unsigned long
finish_node(struct device_node *np, unsigned long mem_start,
interpret_func *ifunc)
@@ -505,31 +637,79 @@ finish_node(struct device_node *np, unsigned long mem_start,
ifunc = NULL;
else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
ifunc = interpret_pci_props;
- else if (!strcmp(np->type, "dbdma")
- || (ifunc == interpret_dbdma_props
- && (!strcmp(np->type, "escc")
- || !strcmp(np->type, "media-bay"))))
+ else if (!strcmp(np->type, "dbdma"))
ifunc = interpret_dbdma_props;
- else if (!strcmp(np->type, "mac-io"))
+ else if (!strcmp(np->type, "mac-io")
+ || ifunc == interpret_macio_props)
ifunc = interpret_macio_props;
else if (!strcmp(np->type, "isa"))
ifunc = interpret_isa_props;
- else
+ else if (!((ifunc == interpret_dbdma_props
+ || ifunc == interpret_macio_props)
+ && (!strcmp(np->type, "escc")
+ || !strcmp(np->type, "media-bay"))))
ifunc = NULL;
+ /* if we were booted from BootX, convert the full name */
+ if (boot_infos
+ && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
+ if (np->full_name[19] == 0) {
+ strcpy(np->full_name, "/");
+ } else if (np->full_name[19] == ':') {
+ char *p = np->full_name + 19;
+ np->full_name = p;
+ for (; *p; ++p)
+ if (*p == ':')
+ *p = '/';
+ }
+ }
+
for (child = np->child; child != NULL; child = child->sibling)
mem_start = finish_node(child, mem_start, ifunc);
return mem_start;
}
-__openfirmware
+/*
+ * When BootX makes a copy of the device tree from the MacOS
+ * Name Registry, it is in the format we use but all of the pointers
+ * are offsets from the start of the tree.
+ * This procedure updates the pointers.
+ */
+__init
+static void relocate_nodes(void)
+{
+ unsigned long base;
+ struct device_node *np;
+ struct property *pp;
+
+#define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)
+
+ base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
+ allnodes = (struct device_node *)(base + 4);
+ for (np = allnodes; np != 0; np = np->allnext) {
+ ADDBASE(np->full_name);
+ ADDBASE(np->properties);
+ ADDBASE(np->parent);
+ ADDBASE(np->child);
+ ADDBASE(np->sibling);
+ ADDBASE(np->allnext);
+ for (pp = np->properties; pp != 0; pp = pp->next) {
+ ADDBASE(pp->name);
+ ADDBASE(pp->value);
+ ADDBASE(pp->next);
+ }
+ }
+}
+
+__init
static unsigned long
interpret_pci_props(struct device_node *np, unsigned long mem_start)
{
struct address_range *adr;
struct pci_reg_property *pci_addrs;
- int i, l, *ip;
+ int i, l, *ip, ml;
+ struct pci_intr_map *imp;
pci_addrs = (struct pci_reg_property *)
get_property(np, "assigned-addresses", &l);
@@ -548,6 +728,30 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start)
mem_start += i * sizeof(struct address_range);
}
+ /*
+ * If the pci host bridge has an interrupt-map property,
+ * look for our node in it.
+ */
+ if (np->parent != 0 && pci_addrs != 0
+ && (imp = (struct pci_intr_map *)
+ get_property(np->parent, "interrupt-map", &ml)) != 0
+ && (ip = (int *) get_property(np, "interrupts", &l)) != 0) {
+ unsigned int busdevfn = pci_addrs[0].addr.a_hi & 0xffff00;
+ np->n_intrs = 0;
+ np->intrs = (struct interrupt_info *) mem_start;
+ for (i = 0; (ml -= sizeof(struct pci_intr_map)) >= 0; ++i) {
+ if (imp[i].addr.a_hi == busdevfn) {
+ np->intrs[np->n_intrs].line = imp[i].intr;
+ np->intrs[np->n_intrs].sense = 0;
+ ++np->n_intrs;
+ }
+ }
+ if (np->n_intrs == 0)
+ np->intrs = 0;
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
+ return mem_start;
+ }
+
ip = (int *) get_property(np, "AAPL,interrupts", &l);
if (ip == 0)
ip = (int *) get_property(np, "interrupts", &l);
@@ -564,7 +768,7 @@ interpret_pci_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_dbdma_props(struct device_node *np, unsigned long mem_start)
{
@@ -613,7 +817,7 @@ interpret_dbdma_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_macio_props(struct device_node *np, unsigned long mem_start)
{
@@ -651,18 +855,28 @@ interpret_macio_props(struct device_node *np, unsigned long mem_start)
ip = (int *) get_property(np, "AAPL,interrupts", &l);
if (ip != 0) {
np->intrs = (struct interrupt_info *) mem_start;
- np->n_intrs = l / (2 * sizeof(int));
- mem_start += np->n_intrs * sizeof(struct interrupt_info);
- for (i = 0; i < np->n_intrs; ++i) {
- np->intrs[i].line = openpic_to_irq(*ip++);
- np->intrs[i].sense = *ip++;
+ if (_machine == _MACH_Pmac) {
+ /* for the iMac */
+ np->n_intrs = l / sizeof(int);
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = *ip++;
+ np->intrs[i].sense = 0;
+ }
+ } else {
+ /* CHRP machines */
+ np->n_intrs = l / (2 * sizeof(int));
+ for (i = 0; i < np->n_intrs; ++i) {
+ np->intrs[i].line = openpic_to_irq(*ip++);
+ np->intrs[i].sense = *ip++;
+ }
}
+ mem_start += np->n_intrs * sizeof(struct interrupt_info);
}
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_isa_props(struct device_node *np, unsigned long mem_start)
{
@@ -700,7 +914,7 @@ interpret_isa_props(struct device_node *np, unsigned long mem_start)
return mem_start;
}
-__openfirmware
+__init
static unsigned long
interpret_root_props(struct device_node *np, unsigned long mem_start)
{
@@ -779,6 +993,30 @@ find_type_devices(const char *type)
return head;
}
+/* Checks if the given "compat" string matches one of the strings in
+ * the device's "compatible" property
+ */
+__openfirmware
+int
+device_is_compatible(struct device_node *device, const char *compat)
+{
+ const char* cp;
+ int cplen, l;
+
+ cp = (char *) get_property(device, "compatible", &cplen);
+ if (cp == NULL)
+ return 0;
+ while (cplen > 0) {
+ if (strcasecmp(cp, compat) == 0)
+ return 1;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ }
+
+ return 0;
+}
+
/*
* Construct and return a list of the device_nodes with a given type
* and compatible property.
@@ -788,15 +1026,13 @@ struct device_node *
find_compatible_devices(const char *type, const char *compat)
{
struct device_node *head, **prevp, *np;
- const char *cp;
prevp = &head;
for (np = allnodes; np != 0; np = np->allnext) {
if (type != NULL
&& !(np->type != 0 && strcasecmp(np->type, type) == 0))
continue;
- cp = (char *) get_property(np, "compatible", NULL);
- if (cp != NULL && strcasecmp(cp, compat) == 0) {
+ if (device_is_compatible(np, compat)) {
*prevp = np;
prevp = &np->next;
}
@@ -854,6 +1090,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
return 0;
}
+#if 0
__openfirmware
void
print_properties(struct device_node *np)
@@ -904,7 +1141,9 @@ print_properties(struct device_node *np)
}
}
}
+#endif
+/* this can be called after setup -- Cort */
__openfirmware
int
call_rtas(const char *service, int nargs, int nret,
@@ -941,7 +1180,7 @@ call_rtas(const char *service, int nargs, int nret,
return u.words[nargs+3];
}
-__openfirmware
+__init
void
abort()
{
@@ -951,3 +1190,563 @@ abort()
#endif
prom_exit();
}
+
+#define CALC_BASE(y) (bi->dispDeviceBase + bi->dispDeviceRect[0] * \
+ (bi->dispDeviceDepth >> 3) + bi->dispDeviceRowBytes * (y))
+
+__init
+static void
+clearscreen(void)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned long *base = (unsigned long *)CALC_BASE(0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++)
+ {
+ unsigned long *ptr = base;
+ for(j=width; j; --j)
+ *(ptr++) = 0;
+ base += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+
+__init
+static void
+scrollscreen(void)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned long *src = (unsigned long *)CALC_BASE(16);
+ unsigned long *dst = (unsigned long *)CALC_BASE(0);
+ unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) *
+ (bi->dispDeviceDepth >> 3)) >> 2;
+ int i,j;
+
+ for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++)
+ {
+ unsigned long *src_ptr = src;
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = *(src_ptr++);
+ src += (bi->dispDeviceRowBytes >> 2);
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+ for (i=0; i<16; i++)
+ {
+ unsigned long *dst_ptr = dst;
+ for(j=width; j; --j)
+ *(dst_ptr++) = 0;
+ dst += (bi->dispDeviceRowBytes >> 2);
+ }
+}
+
+__init
+static void
+drawchar(char c)
+{
+ unsigned long offset = reloc_offset();
+
+ switch(c)
+ {
+ case '\r': RELOC(g_loc_X) = 0; break;
+ case '\n': RELOC(g_loc_X) = 0; RELOC(g_loc_Y)++; break;
+ default:
+ draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y));
+ if (RELOC(g_loc_X) >= RELOC(g_max_loc_X))
+ {
+ RELOC(g_loc_X) = 0;
+ RELOC(g_loc_Y)++;
+ }
+ }
+ while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y))
+ {
+ scrollscreen();
+ RELOC(g_loc_Y)--;
+ }
+}
+
+__init
+static void
+drawstring(const char *c)
+{
+ while(*c)
+ drawchar(*(c++));
+}
+
+__init
+static void
+draw_byte(unsigned char c, long locX, long locY)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ unsigned char *base = bi->dispDeviceBase
+ + (bi->dispDeviceRowBytes * ((locY * 16) + bi->dispDeviceRect[1]))
+ + (bi->dispDeviceDepth >> 3) * ((locX * 8) + bi->dispDeviceRect[0]);
+ unsigned char *font = &RELOC(vga_font)[((unsigned long)c) * 16];
+
+ switch(bi->dispDeviceDepth)
+ {
+ case 32:
+ draw_byte_32(font, (unsigned long *)base);
+ break;
+ case 16:
+ draw_byte_16(font, (unsigned long *)base);
+ break;
+ case 8:
+ draw_byte_8(font, (unsigned long *)base);
+ break;
+ default:
+ break;
+ }
+}
+
+__init
+static unsigned long expand_bits_8[16] = {
+ 0x00000000,
+ 0x000000ff,
+ 0x0000ff00,
+ 0x0000ffff,
+ 0x00ff0000,
+ 0x00ff00ff,
+ 0x00ffff00,
+ 0x00ffffff,
+ 0xff000000,
+ 0xff0000ff,
+ 0xff00ff00,
+ 0xff00ffff,
+ 0xffff0000,
+ 0xffff00ff,
+ 0xffffff00,
+ 0xffffffff
+};
+
+__init
+static unsigned long expand_bits_16[4] = {
+ 0x00000000,
+ 0x0000ffff,
+ 0xffff0000,
+ 0xffffffff
+};
+
+
+__init
+static void
+draw_byte_32(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (-(bits >> 7) & fg) ^ bg;
+ base[1] = (-((bits >> 6) & 1) & fg) ^ bg;
+ base[2] = (-((bits >> 5) & 1) & fg) ^ bg;
+ base[3] = (-((bits >> 4) & 1) & fg) ^ bg;
+ base[4] = (-((bits >> 3) & 1) & fg) ^ bg;
+ base[5] = (-((bits >> 2) & 1) & fg) ^ bg;
+ base[6] = (-((bits >> 1) & 1) & fg) ^ bg;
+ base[7] = (-(bits & 1) & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static void
+draw_byte_16(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0xFFFFFFFFUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = RELOC(expand_bits_16);
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 6] & fg) ^ bg;
+ base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg;
+ base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg;
+ base[3] = (eb[bits & 3] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static void
+draw_byte_8(unsigned char *font, unsigned long *base)
+{
+ unsigned long offset = reloc_offset();
+ boot_infos_t* bi = PTRRELOC(RELOC(boot_infos));
+ int l, bits;
+ int fg = 0x0F0F0F0FUL;
+ int bg = 0x00000000UL;
+ unsigned long *eb = RELOC(expand_bits_8);
+
+ for (l = 0; l < 16; ++l)
+ {
+ bits = *font++;
+ base[0] = (eb[bits >> 4] & fg) ^ bg;
+ base[1] = (eb[bits & 0xf] & fg) ^ bg;
+ base = (unsigned long *) ((char *)base + bi->dispDeviceRowBytes);
+ }
+}
+
+__init
+static unsigned char vga_font[cmapsz] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd,
+0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff,
+0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe,
+0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd,
+0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e,
+0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30,
+0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63,
+0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8,
+0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e,
+0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb,
+0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6,
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c,
+0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c,
+0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c,
+0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18,
+0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c,
+0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe,
+0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18,
+0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
+0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
+0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde,
+0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68,
+0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7,
+0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66,
+0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c,
+0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c,
+0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6,
+0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18,
+0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60,
+0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb,
+0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66,
+0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60,
+0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
+0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3,
+0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
+0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6,
+0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66,
+0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38,
+0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06,
+0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe,
+0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6,
+0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b,
+0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c,
+0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
+0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00,
+0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
+0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6,
+0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e,
+0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18,
+0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66,
+0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30,
+0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc,
+0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc,
+0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
+0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0,
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06,
+0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30,
+0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
+0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
+0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
+0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
+0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8,
+0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66,
+0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66,
+0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60,
+0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
+0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c,
+0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00,
+};
+
+#endif /* CONFIG_BOOTX_TEXT */
diff --git a/arch/ppc/kernel/residual.c b/arch/ppc/kernel/residual.c
index b2e198f68..83333f660 100644
--- a/arch/ppc/kernel/residual.c
+++ b/arch/ppc/kernel/residual.c
@@ -1,5 +1,5 @@
/*
- * $Id: residual.c,v 1.10 1998/07/09 22:23:18 cort Exp $
+ * $Id: residual.c,v 1.14 1998/10/11 17:38:10 cort Exp $
*
* Code to deal with the PReP residual data.
*
@@ -23,7 +23,6 @@
#include <asm/pnp.h>
#include <asm/byteorder.h>
-#if 0
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -50,7 +49,7 @@
#include <asm/ide.h>
-const char * PnP_BASE_TYPES[]= {
+const char * PnP_BASE_TYPES[] __initdata = {
"Reserved",
"MassStorageDevice",
"NetworkInterfaceController",
@@ -66,7 +65,7 @@ const char * PnP_BASE_TYPES[]= {
/* Device Sub Type Codes */
-const unsigned char * PnP_SUB_TYPES[] = {
+const unsigned char * PnP_SUB_TYPES[] __initdata = {
"\001\000SCSIController",
"\001\001IDEController",
"\001\002FloppyController",
@@ -123,7 +122,7 @@ const unsigned char * PnP_SUB_TYPES[] = {
/* Device Interface Type Codes */
-const unsigned char * PnP_INTERFACES[]= {
+const unsigned char * PnP_INTERFACES[] __initdata = {
"\000\000\000General",
"\001\000\000GeneralSCSI",
"\001\001\000GeneralIDE",
@@ -241,7 +240,7 @@ const unsigned char * PnP_INTERFACES[]= {
NULL
};
-static const unsigned char *PnP_SUB_TYPE_STR(unsigned char BaseType,
+static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType,
unsigned char SubType) {
const unsigned char ** s=PnP_SUB_TYPES;
while (*s && !((*s)[0]==BaseType
@@ -250,7 +249,7 @@ static const unsigned char *PnP_SUB_TYPE_STR(unsigned char BaseType,
else return("Unknown !");
};
-static const unsigned char *PnP_INTERFACE_STR(unsigned char BaseType,
+static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType,
unsigned char SubType,
unsigned char Interface) {
const unsigned char ** s=PnP_INTERFACES;
@@ -261,7 +260,7 @@ static const unsigned char *PnP_INTERFACE_STR(unsigned char BaseType,
else return NULL;
};
-static void printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
+static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
int i, c;
char decomp[4];
#define p pkt->S14_Pack.S14_Data.S14_PPCPack
@@ -286,7 +285,7 @@ static void printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
#undef p
}
-static void printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
+static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
static const unsigned char * intlevel[] = {"high", "low"};
static const unsigned char * intsense[] = {"edge", "level"};
@@ -353,7 +352,7 @@ static void printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
}
}
-static void printlargevendor(PnP_TAG_PACKET * pkt, int size) {
+static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
@@ -463,9 +462,7 @@ static void printlargevendor(PnP_TAG_PACKET * pkt, int size) {
}
}
-static void printlargepacket(PnP_TAG_PACKET * pkt, int size) {
- int i;
-
+static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
case LargeVendorItem:
printlargevendor(pkt, size);
@@ -476,8 +473,7 @@ static void printlargepacket(PnP_TAG_PACKET * pkt, int size) {
break;
}
}
-static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
- PnP_TAG_PACKET tmp;
+static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
if (pkt->S1_Pack.Tag== END_TAG) {
printk(" No packets describing %s resources.\n", cat);
return;
@@ -498,13 +494,11 @@ static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
} while (pkt->S1_Pack.Tag != END_TAG);
}
-void print_residual_device_info(void)
+void __init print_residual_device_info(void)
{
int i;
- union _PnP_TAG_PACKET *pkt;
PPC_DEVICE *dev;
#define did dev->DeviceId
-return;
/* make sure we have residual data first */
if ( res->ResidualLength == 0 )
@@ -552,18 +546,24 @@ return;
PnP_BASE_TYPES[did.BaseType],
PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
s);
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->AllocatedOffset], "allocated");
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->PossibleOffset], "possible");
- printpackets( (union _PnP_TAG_PACKET *)
- &res->DevicePnPHeap[dev->CompatibleOffset], "compatible");
+ if ( dev->AllocatedOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->AllocatedOffset],
+ "allocated");
+ if ( dev->PossibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->PossibleOffset],
+ "possible");
+ if ( dev->CompatibleOffset )
+ printpackets( (union _PnP_TAG_PACKET *)
+ &res->DevicePnPHeap[dev->CompatibleOffset],
+ "compatible");
}
}
-
-static void printVPD(void) {
+#if 0
+static void __init printVPD(void) {
#define vpd res->VitalProductData
int ps=vpd.PageSize, i, j;
static const char* Usage[]={
@@ -628,7 +628,6 @@ static void printVPD(void) {
/*
* Spit out some info about residual data
*/
-#if 0
void print_residual_device_info(void)
{
int i;
@@ -728,7 +727,6 @@ void print_residual_device_info(void)
}
#endif
-#endif /* 0 */
/* Returns the device index in the residual data,
any of the search items may be set as -1 for wildcard,
DevID number field (second halfword) is big endian !
@@ -765,7 +763,7 @@ in this rarely used area we unencode and compare */
little endian in the heap, so we use two parameters to avoid writing
two very similar functions */
-static int same_DevID(unsigned short vendor,
+static int __init same_DevID(unsigned short vendor,
unsigned short Number,
char * str)
{
@@ -781,7 +779,7 @@ static int same_DevID(unsigned short vendor,
return 0;
}
-PPC_DEVICE *residual_find_device(unsigned long BusMask,
+PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
unsigned char * DevID,
int BaseType,
int SubType,
@@ -804,6 +802,28 @@ PPC_DEVICE *residual_find_device(unsigned long BusMask,
return 0;
}
+PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
+ unsigned short DevID,
+ int BaseType,
+ int SubType,
+ int Interface,
+ int n)
+{
+ int i;
+ if ( !res->ResidualLength ) return NULL;
+ for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+ if ( (Dev.BusId&BusMask) &&
+ (BaseType==-1 || Dev.BaseType==BaseType) &&
+ (SubType==-1 || Dev.SubType==SubType) &&
+ (Interface==-1 || Dev.Interface==Interface) &&
+ (DevID==0xffff || (Dev.DevId&0xffff) == DevID) &&
+ !(n--) ) return res->Devices+i;
+#undef Dev
+ }
+ return 0;
+}
+
PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
unsigned packet_tag,
int n)
@@ -823,7 +843,7 @@ PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
return 0; /* not found */
}
-PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
+PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
unsigned packet_type,
int n)
{
@@ -837,7 +857,7 @@ PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p,
return 0; /* not found */
}
-PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
+PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
unsigned packet_type,
int n)
{
@@ -850,4 +870,3 @@ PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p,
};
return 0; /* not found */
}
-
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 7ea277866..706c1dde2 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,9 +1,10 @@
/*
- * $Id: setup.c,v 1.95 1998/07/20 19:03:47 geert Exp $
+ * $Id: setup.c,v 1.117 1998/11/09 19:55:53 geert Exp $
* Common prep/pmac/chrp boot and setup code.
*/
#include <linux/config.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/init.h>
@@ -23,15 +24,22 @@
#include <asm/bootinfo.h>
#include <asm/setup.h>
#include <asm/amigappc.h>
+#include <asm/smp.h>
#ifdef CONFIG_MBX
#include <asm/mbx.h>
#endif
+#include <asm/bootx.h>
/* APUS defs */
extern unsigned long m68k_machtype;
-extern struct mem_info ramdisk;
extern int parse_bootinfo(const struct bi_record *);
extern char _end[];
+#ifdef CONFIG_APUS
+struct mem_info ramdisk;
+unsigned long isa_io_base;
+unsigned long isa_mem_base;
+unsigned long pci_dram_offset;
+#endif
/* END APUS defs */
extern char cmd_line[512];
@@ -52,6 +60,8 @@ RESIDUAL *res = (RESIDUAL *)&__res;
int _prep_type;
+extern boot_infos_t *boot_infos;
+
/*
* Perhaps we can put the pmac screen_info[] here
* on pmac as well so we don't need the ifdef's.
@@ -122,9 +132,7 @@ void machine_restart(char *cmd)
cuda_poll();
break;
case ADB_VIAPMU:
- pmu_request(&req, NULL, 1, PMU_RESET);
- for (;;)
- pmu_poll();
+ pmu_restart();
break;
default:
}
@@ -197,10 +205,7 @@ void machine_power_off(void)
cuda_poll();
break;
case ADB_VIAPMU:
- pmu_request(&req, NULL, 5, PMU_SHUTDOWN,
- 'M', 'A', 'T', 'T');
- for (;;)
- pmu_poll();
+ pmu_shutdown();
break;
default:
}
@@ -217,10 +222,7 @@ void machine_power_off(void)
case _MACH_prep:
machine_restart(NULL);
case _MACH_apus:
-#if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
- apm_set_power_state(APM_STATE_OFF);
for (;;);
-#endif
}
for (;;);
#else /* CONFIG_MBX */
@@ -239,14 +241,16 @@ void machine_halt(void)
}
-#ifdef CONFIG_BLK_DEV_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
{
#if !defined(CONFIG_MBX) && !defined(CONFIG_APUS)
switch (_machine) {
+#if defined(CONFIG_BLK_DEV_IDE_PMAC)
case _MACH_Pmac:
- pmac_ide_init_hwif_ports(p,base,irq);
+ pmac_ide_init_hwif_ports(p,base,irq);
break;
+#endif
case _MACH_chrp:
chrp_ide_init_hwif_ports(p,base,irq);
break;
@@ -256,72 +260,36 @@ void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
}
#endif
}
+EXPORT_SYMBOL(ide_init_hwif_ports);
#endif
unsigned long cpu_temp(void)
{
-#if 0
- unsigned long i, temp, thrm1, dir;
- int sanity;
+ unsigned char thres = 0;
- /*
- * setup thrm3 - need to give TAU at least 20us
- * to do the compare so assume a 300MHz clock.
- * We need 300*20 ticks then.
- * -- Cort
- */
- asm("mtspr 1020, %1\n\t"
- "mtspr 1021, %1\n\t"
- "mtspr 1022, %0\n\t"::
- "r" ( ((300*20)<<18) | THRM3_E), "r" (0) );
-
#if 0
- for ( i = 127 ; i >= 0 ; i-- )
- {
- asm("mtspr 1020, %0\n\t"::
- "r" (THRM1_TID|THRM1_V|(i<<2)) );
- /* check value */
- while ( !( thrm1 & THRM1_TIV) )
- asm("mfspr %0, 1020 \n\t": "=r" (thrm1) );
- if ( thrm1 & THRM1_TIN )
- {
- printk("tin set: %x tiv %x\n", thrm1,thrm1&THRM1_TIV);
- goto out;
- }
-
- }
+ /* disable thrm2 */
+ _set_THRM2( 0 );
+ /* threshold 0 C, tid: exceeding threshold, tie: don't generate interrupt */
+ _set_THRM1( THRM1_V );
+
+ /* we need 20us to do the compare - assume 300MHz processor clock */
+ _set_THRM3(0);
+ _set_THRM3(THRM3_E | (300*30)<<18 );
+
+ udelay(100);
+ /* wait for the compare to complete */
+ /*while ( !(_get_THRM1() & THRM1_TIV) ) ;*/
+ if ( !(_get_THRM1() & THRM1_TIV) )
+ printk("no tiv\n");
+ if ( _get_THRM1() & THRM1_TIN )
+ printk("crossed\n");
+ /* turn everything off */
+ _set_THRM3(0);
+ _set_THRM1(0);
#endif
-#if 0
- i = 32; /* increment */
- dir = 1; /* direction we're checking 0=up 1=down */
- temp = 64; /* threshold checking against */
- while ( i )
- {
- _set_THRM1((1<<29) | THRM1_V | (temp<<2) );
- printk("checking %d in dir %d thrm set to %x/%x\n", temp,dir,
- ( (1<<29) | THRM1_V | (temp<<2)),_get_THRM1());
- /* check value */
- sanity = 0x0fffffff;
- while ( (!( thrm1 & THRM1_TIV)) && (sanity--) )
- thrm1 = _get_THRM1();
- /*asm("mfspr %0, 1020 \n\t": "=r" (thrm1) );*/
- if ( ! sanity || sanity==0xffffffff ) printk("no sanity\n");
- /* temp is not in that direction */
- if ( !(thrm1 & THRM1_TIN) )
- {
- printk("not in that dir thrm1 %x\n",thrm1);
- if ( dir == 0 ) dir = 1;
- else dir = 0;
- }
- if ( dir ) temp -= i;
- else temp += i;
- i /= 2;
- }
- asm("mtspr 1020, %0\n\t"
- "mtspr 1022, %0\n\t" ::"r" (0) );
-#endif
-#endif
- return 0;
+
+ return thres;
}
int get_cpuinfo(char *buffer)
@@ -333,14 +301,13 @@ int get_cpuinfo(char *buffer)
unsigned long len = 0;
unsigned long bogosum = 0;
unsigned long i;
- unsigned long cr;
+
#ifdef __SMP__
- extern unsigned long cpu_present_map;
- extern struct cpuinfo_PPC cpu_data[NR_CPUS];
+#define CPU_PRESENT(x) (cpu_callin_map[(x)])
#define GET_PVR ((long int)(cpu_data[i].pvr))
#define CD(x) (cpu_data[i].x)
#else
-#define cpu_present_map 1L
+#define CPU_PRESENT(x) ((x)==0)
#define smp_num_cpus 1
#define GET_PVR ((long int)_get_PVR())
#define CD(x) (x)
@@ -348,7 +315,7 @@ int get_cpuinfo(char *buffer)
for ( i = 0; i < smp_num_cpus ; i++ )
{
- if ( ! ( cpu_present_map & (1<<i) ) )
+ if ( !CPU_PRESENT(i) )
continue;
if ( i )
len += sprintf(len+buffer,"\n");
@@ -374,14 +341,6 @@ int get_cpuinfo(char *buffer)
break;
case 8:
len += sprintf(len+buffer, "750\n");
- cr = _get_L2CR();
- if ( cr & (0x1<<28)) cr = 256;
- else if ( cr & (0x2<<28)) cr = 512;
- else if ( cr & (0x3<<28)) cr = 1024;
- else cr = 0;
- len += sprintf(len+buffer, "on-chip l2\t: "
- "%ld KB (%s)\n",
- cr,(_get_L2CR()&0x80000000) ? "on" : "off");
len += sprintf(len+buffer, "temperature \t: %lu C\n",
cpu_temp());
break;
@@ -436,9 +395,9 @@ int get_cpuinfo(char *buffer)
#else /* CONFIG_MBX */
{
bd_t *bp;
- extern RESIDUAL res;
+ extern RESIDUAL *res;
- bp = (bd_t *)&res;
+ bp = (bd_t *)res;
len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
"bus clock\t: %dMHz\n",
@@ -510,30 +469,41 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7))
{
extern void setup_pci_ptrs(void);
+
+#ifdef __SMP__
+ if ( first_cpu_booted ) return 0;
+#endif /* __SMP__ */
+
#ifndef CONFIG_MBX
#ifndef CONFIG_MACH_SPECIFIC
- char *model;
- /* prep boot loader tells us if we're prep or not */
- if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
- {
- _machine = _MACH_prep;
- have_of = 0;
- }
/* boot loader will tell us if we're APUS */
- else if ( r3 == 0x61707573 )
+ if ( r3 == 0x61707573 )
{
_machine = _MACH_apus;
have_of = 0;
r3 = 0;
- } else
- {
+ }
+ /* prep boot loader tells us if we're prep or not */
+ else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
+ _machine = _MACH_prep;
+ have_of = 0;
+ } else {
+ char *model;
+
have_of = 1;
/* ask the OF info if we're a chrp or pmac */
- model = get_property(find_path_device("/"), "type", NULL);
- if ( !strncmp("chrp",model,4) )
+ model = get_property(find_path_device("/"), "device_type", NULL);
+ if ( model && !strncmp("chrp",model,4) )
_machine = _MACH_chrp;
- else
- _machine = _MACH_Pmac;
+ else
+ {
+ model = get_property(find_path_device("/"),
+ "model", NULL);
+ if ( model && !strncmp(model, "IBM", 3))
+ _machine = _MACH_chrp;
+ else
+ _machine = _MACH_Pmac;
+ }
}
#endif /* CONFIG_MACH_SPECIFIC */
@@ -556,6 +526,20 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
strncpy(cmd_line, (char *)r3 + KERNELBASE,
sizeof(cmd_line));
+ } else if (boot_infos != 0) {
+ /* booted by BootX - check for ramdisk */
+ if (boot_infos->kernelParamsOffset != 0)
+ strncpy(cmd_line, (char *) boot_infos
+ + boot_infos->kernelParamsOffset,
+ sizeof(cmd_line));
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (boot_infos->ramDisk) {
+ initrd_start = (unsigned long) boot_infos
+ + boot_infos->ramDisk;
+ initrd_end = initrd_start + boot_infos->ramDiskSize;
+ initrd_below_start_ok = 1;
+ }
+#endif
} else {
struct device_node *chosen;
char *p;
@@ -568,6 +552,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
}
#endif
+ cmd_line[0] = 0;
chosen = find_devices("chosen");
if (chosen != NULL) {
p = get_property(chosen, "bootargs", NULL);
@@ -652,7 +637,6 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
break;
#ifdef CONFIG_APUS
case _MACH_apus:
- setup_pci_ptrs();
/* Parse bootinfo. The bootinfo is located right after
the kernel bss */
parse_bootinfo((const struct bi_record *)&_end);
@@ -677,6 +661,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
default:
printk("Unknown machine type in identify_machine!\n");
}
+
#else /* CONFIG_MBX */
if ( r3 )
@@ -702,6 +687,12 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
strcpy(cmd_line, (char *)(r6+KERNELBASE));
}
#endif /* CONFIG_MBX */
+
+ /* Check for nobats option (used in mapin_ram). */
+ if (strstr(cmd_line, "nobats")) {
+ extern int __map_without_bats;
+ __map_without_bats = 1;
+ }
return 0;
}
@@ -722,6 +713,8 @@ __initfunc(void setup_arch(char **cmdline_p,
#ifdef CONFIG_XMON
extern void xmon_map_scc(void);
xmon_map_scc();
+ if (strstr(cmd_line, "xmon"))
+ xmon(0);
#endif /* CONFIG_XMON */
/* reboot on panic */
@@ -739,20 +732,6 @@ __initfunc(void setup_arch(char **cmdline_p,
*memory_start_p = find_available_memory();
*memory_end_p = (unsigned long) end_of_DRAM;
-#ifdef CONFIG_BLK_DEV_INITRD
- /* initrd_start and size are setup by boot/head.S and kernel/head.S */
- if ( initrd_start )
- {
- if (initrd_end > *memory_end_p)
- {
- printk("initrd extends beyond end of memory "
- "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
- initrd_end,*memory_end_p);
- initrd_start = 0;
- }
- }
-#endif
-
#ifdef CONFIG_MBX
mbx_setup_arch(memory_start_p,memory_end_p);
#else /* CONFIG_MBX */
@@ -771,7 +750,7 @@ __initfunc(void setup_arch(char **cmdline_p,
m68k_machtype = MACH_AMIGA;
apus_setup_arch(memory_start_p,memory_end_p);
break;
-#endif
+#endif
default:
printk("Unknown machine %d in setup_arch()\n", _machine);
}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 6d2d4279e..3ffb7981e 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -1,7 +1,7 @@
/*
* linux/arch/ppc/kernel/signal.c
*
- * $Id: signal.c,v 1.16 1998/06/16 23:34:10 cort Exp $
+ * $Id: signal.c,v 1.21 1998/10/22 19:37:49 paulus Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -128,6 +128,13 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
do_exit(SIGSEGV);
}
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ struct pt_regs *regs = (struct pt_regs *) &uss;
+ return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
+
int
sys_sigaction(int sig, const struct old_sigaction *act,
struct old_sigaction *oact)
@@ -238,7 +245,7 @@ int sys_sigreturn(struct pt_regs *regs)
goto badframe;
sr = (struct sigregs *) sigctx.regs;
regs->gpr[3] = ret = sigctx.signal;
- regs->gpr[4] = (unsigned long) sr;
+ regs->gpr[4] = (unsigned long) sc;
regs->link = (unsigned long) &sr->tramp;
regs->nip = sigctx.handler;
@@ -286,7 +293,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
|| get_user(regs->gpr[3], &sc->signal))
goto badframe;
regs->gpr[1] = newsp;
- regs->gpr[4] = (unsigned long) frame;
+ regs->gpr[4] = (unsigned long) sc;
regs->link = (unsigned long) frame->tramp;
return;
@@ -483,3 +490,4 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
+
diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c
index ca8d81de1..75445925f 100644
--- a/arch/ppc/kernel/smp.c
+++ b/arch/ppc/kernel/smp.c
@@ -1,5 +1,5 @@
/*
- * $Id: smp.c,v 1.28 1998/08/04 04:47:45 cort Exp $
+ * $Id: smp.c,v 1.36 1998/10/08 01:17:48 cort Exp $
*
* Smp support for ppc.
*
@@ -35,22 +35,20 @@
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_num_cpus = 1;
-unsigned long cpu_present_map = 0;
-volatile int cpu_number_map[NR_CPUS];
-volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
-volatile int __cpu_logical_map[NR_CPUS];
-static unsigned char boot_cpu_id = 0;
struct cpuinfo_PPC cpu_data[NR_CPUS];
struct klock_info_struct klock_info = { KLOCK_CLEAR, 0 };
volatile unsigned char active_kernel_processor = NO_PROC_ID; /* Processor holding kernel spinlock */
volatile unsigned long ipi_count;
spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
-
unsigned int prof_multiplier[NR_CPUS];
unsigned int prof_counter[NR_CPUS];
+int first_cpu_booted = 0;
-int start_secondary(void *);
+/* all cpu mappings are 1-1 -- Cort */
+int cpu_number_map[NR_CPUS] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,};
+volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
+int start_secondary(void *);
extern int cpu_idle(void *unused);
void smp_local_timer_interrupt(struct pt_regs * regs)
@@ -58,7 +56,6 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
int cpu = smp_processor_id();
extern void update_one_process(struct task_struct *,unsigned long,
unsigned long,unsigned long,int);
-
if (!--prof_counter[cpu]) {
int user=0,system=0;
struct task_struct * p = current;
@@ -104,7 +101,7 @@ void smp_local_timer_interrupt(struct pt_regs * regs)
* Right now it only works for stop cpu's but will be setup
* later for more general message passing.
*
- * As it is now, if we're sending two message as the same time
+ * As it is now, if we're sending two message at the same time
* we have race conditions. I avoided doing locks here since
* all that works right now is the stop cpu message.
*
@@ -115,17 +112,25 @@ void smp_message_recv(void)
{
int msg = smp_message[smp_processor_id()];
- printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);
+ /* clear interrupt */
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
/* make sure msg is for us */
if ( msg == -1 ) return;
-printk("recv after msg check\n");
+
+ ipi_count++;
+ /*printk("SMP %d: smp_message_recv() msg %x\n", smp_processor_id(),msg);*/
+
switch( msg )
{
case MSG_STOP_CPU:
__cli();
while (1) ;
break;
+ case MSG_RESCHEDULE:
+ current->need_resched = 1;
+ break;
case 0xf0f0: /* syncing time bases - just return */
break;
default:
@@ -139,19 +144,17 @@ printk("recv after msg check\n");
void smp_send_reschedule(int cpu)
{
- /* for now, nothing */
+ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0);
}
-
spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED;
void smp_message_pass(int target, int msg, unsigned long data, int wait)
{
- printk("SMP %d: sending smp message\n", current->processor);
-
- spin_lock(&mesg_pass_lock);
if ( _machine != _MACH_Pmac )
return;
-
+ /*printk("SMP %d: sending smp message\n", current->processor);*/
+if (smp_processor_id() ) printk("pass from cpu 1\n");
+ spin_lock(&mesg_pass_lock);
#define OTHER (~smp_processor_id() & 1)
switch( target )
@@ -167,9 +170,10 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
break;
}
/* interrupt secondary processor */
- /**(volatile unsigned long *)(0xf80000c0) = 0xffffffff;
- eieio();*/
- *(volatile unsigned long *)(0xf80000c0) = 0;
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
+ *(volatile unsigned long *)(0xf80000c0) = 0L;
+ eieio();
/* interrupt primary */
/**(volatile unsigned long *)(0xf3019000);*/
spin_unlock(&mesg_pass_lock);
@@ -177,29 +181,25 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
__initfunc(void smp_boot_cpus(void))
{
- extern unsigned long secondary_entry[];
extern struct task_struct *current_set[NR_CPUS];
- int i, timeout;
+ extern void __secondary_start(void);
+ int i;
struct task_struct *p;
printk("Entering SMP Mode...\n");
+
+ first_cpu_booted = 1;
+ dcbf(&first_cpu_booted);
for (i = 0; i < NR_CPUS; i++) {
- cpu_number_map[i] = -1;
prof_counter[i] = 1;
prof_multiplier[i] = 1;
}
-
- cpu_present_map = 0;
- for(i=0; i < NR_CPUS; i++)
- __cpu_logical_map[i] = -1;
- smp_store_cpu_info(boot_cpu_id);
- active_kernel_processor = boot_cpu_id;
- current->processor = boot_cpu_id;
- cpu_present_map |= 1;
- cpu_number_map[boot_cpu_id] = 0;
- __cpu_logical_map[0] = boot_cpu_id;
+ cpu_callin_map[0] = 1;
+ smp_store_cpu_info(0);
+ active_kernel_processor = 0;
+ current->processor = 0;
if ( _machine != _MACH_Pmac )
{
@@ -207,10 +207,6 @@ __initfunc(void smp_boot_cpus(void))
return;
}
- /* assume a 2nd processor for now */
- cpu_present_map |= (1 << 1);
- smp_num_cpus = 2;
-
/* create a process for second processor */
kernel_thread(start_secondary, NULL, CLONE_PID);
p = task[1];
@@ -218,14 +214,16 @@ __initfunc(void smp_boot_cpus(void))
panic("No idle task for secondary processor\n");
p->processor = 1;
current_set[1] = p;
+
/* need to flush here since secondary bat's aren't setup */
- dcbf((volatile unsigned long *)&current_set[1]);
-
+ dcbf((void *)&current_set[1]);
/* setup entry point of secondary processor */
- *(volatile unsigned long *)(0xf2800000)
- = (unsigned long)secondary_entry-KERNELBASE;
+ *(volatile unsigned long *)(0xf2800000) =
+ (unsigned long)__secondary_start-KERNELBASE;
eieio();
/* interrupt secondary to begin executing code */
+ *(volatile unsigned long *)(0xf80000c0) = ~0L;
+ eieio();
*(volatile unsigned long *)(0xf80000c0) = 0L;
eieio();
/*
@@ -234,24 +232,23 @@ __initfunc(void smp_boot_cpus(void))
* calibrate_delay() so use this value that I found through
* experimentation. -- Cort
*/
- udelay(1);
+ for ( i = 1000; i && !cpu_callin_map[1] ; i-- )
+ udelay(100);
+
if(cpu_callin_map[1]) {
- cpu_number_map[1] = 1;
- __cpu_logical_map[i] = 1;
- printk("Processor 1 found.\n");
-
+ printk("Processor %d found.\n", smp_num_cpus);
+ smp_num_cpus++;
#if 0 /* this sync's the decr's, but we don't want this now -- Cort */
set_dec(decrementer_count);
#endif
- /* interrupt secondary to start decr's again */
- smp_message_pass(1,0xf0f0, 0, 0);
- /* interrupt secondary to begin executing code */
- /**(volatile unsigned long *)(0xf80000c0) = 0L;
- eieio();*/
} else {
- smp_num_cpus--;
- printk("Processor %d is stuck.\n", 1);
+ printk("Processor %d is stuck. \n", smp_num_cpus);
}
+ /* reset the entry point so if we get another intr we won't
+ * try to startup again */
+ *(volatile unsigned long *)(0xf2800000) = 0x100;
+ /* send interrupt to other processors to start decr's on all cpus */
+ smp_message_pass(1,0xf0f0, 0, 0);
}
__initfunc(void smp_commence(void))
@@ -271,7 +268,7 @@ __initfunc(void initialize_secondary(void))
}
/* Activate a secondary processor. */
-__initfunc(int start_secondary(void *unused))
+asmlinkage int __init start_secondary(void *unused)
{
printk("SMP %d: start_secondary()\n",current->processor);
smp_callin();
@@ -281,16 +278,14 @@ __initfunc(int start_secondary(void *unused))
__initfunc(void smp_callin(void))
{
printk("SMP %d: smp_callin()\n",current->processor);
- smp_store_cpu_info(1);
+ smp_store_cpu_info(current->processor);
set_dec(decrementer_count);
current->mm->mmap->vm_page_prot = PAGE_SHARED;
current->mm->mmap->vm_start = PAGE_OFFSET;
current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
-
- /* assume we're just the secondary processor for now */
- cpu_callin_map[1] = 1;
+ cpu_callin_map[current->processor] = current->processor;
while(!smp_commenced)
barrier();
__sti();
@@ -310,6 +305,7 @@ __initfunc(void smp_store_cpu_info(int id))
{
struct cpuinfo_PPC *c = &cpu_data[id];
+ /* assume bogomips are same for everything */
c->loops_per_sec = loops_per_sec;
c->pvr = _get_PVR();
}
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 91a8d0ccf..b97456226 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -209,7 +209,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
goto out;
}
- /*flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);*/
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
ret = do_mmap(file, addr, len, prot, flags, offset);
out:
unlock_kernel();
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index 0857c2633..8bada0e69 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -1,5 +1,5 @@
/*
- * $Id: time.c,v 1.35 1998/07/24 11:05:47 geert Exp $
+ * $Id: time.c,v 1.36 1998/10/10 12:16:08 geert Exp $
* Common time routines among all ppc machines.
*
* Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -106,7 +106,12 @@ void timer_interrupt(struct pt_regs * regs)
#ifdef __SMP__
smp_local_timer_interrupt(regs);
#endif
-
+#ifdef CONFIG_APUS
+ {
+ extern void apus_heartbeat (void);
+ apus_heartbeat ();
+ }
+#endif
hardirq_exit(cpu);
/* restore the HID0 in case dcache was off - see idle.c
* this hack should leave for a better solution -- Cort */
diff --git a/arch/ppc/kernel/totalmp.c b/arch/ppc/kernel/totalmp.c
new file mode 100644
index 000000000..5f87755a7
--- /dev/null
+++ b/arch/ppc/kernel/totalmp.c
@@ -0,0 +1,109 @@
+/*
+ * $Id: totalmp.c,v 1.5 1998/08/26 13:58:50 cort Exp $
+ *
+ * Support for Total Impact's TotalMP PowerPC accelerator board.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * 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.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/openpic.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+
+extern void totalmp_init(void);
+
+extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
+ u_int field);
+__initfunc(void totalmp_init(void))
+{
+ struct pci_dev *dev;
+ u32 val;
+ unsigned long ctl_area, ctl_area_phys;
+
+ /* it's a pci card */
+ if ( !pci_present() ) return;
+
+ /* search for a MPIC. For now, we assume
+ * only one TotalMP card installed. -- Cort
+ */
+ for(dev=pci_devices; dev; dev=dev->next)
+ {
+ if ( (dev->vendor == PCI_VENDOR_ID_IBM)
+ && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
+ || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
+ {
+ break;
+ }
+ }
+
+ if ( !dev ) return;
+
+ OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
+#if 0
+ if ( (ulong)OpenPIC > 0x10000000 )
+ {
+ printk("TotalMP: relocating base %lx -> %lx\n",
+ (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+ OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
+ }*/
+#endif
+ OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
+
+ openpic_init(0);
+
+ /* put openpic in 8259-cascade mode */
+ openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
+ /* set ipi to highest priority */
+ openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
+
+ /* allocate and remap the control area to be no-cache */
+ ctl_area = __get_free_pages(GFP_ATOMIC, 3);
+ ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
+ ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
+
+ /* soft reset cpu 0 */
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
+ openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
+
+ /* wait for base address reg to change, signaling that cpu 0 is done */
+#define wait_for(where) { \
+ udelay(100); \
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); \
+ if ( val != 0x77700000 ) \
+ { \
+ printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
+ /*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
+ return; \
+ } }
+
+ /* tell cpu0 where the control area is */
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
+ wait_for(0);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0xff000000)>>20);
+ wait_for(1);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x00ff0000)>>12);
+ wait_for(2);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x0000ff00)>>4);
+ wait_for(3);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+ ((ulong)ctl_area & 0x000000ff)<<4);
+ wait_for(4);
+#undef wait_for
+ /* wait for cpu0 to "sign-on" */
+}
+