summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMiguel de Icaza <miguel@nuclecu.unam.mx>1997-08-06 19:14:48 +0000
committerMiguel de Icaza <miguel@nuclecu.unam.mx>1997-08-06 19:14:48 +0000
commite2819e52a162873ff5061de81bb749831bdb5de9 (patch)
tree6067ea700202750ba335a423696f2972700e5f76 /arch
parent17a005074429bbf143e40401f405ae4363e56828 (diff)
Merge to 2.1.38.
IMPORTANT NOTE: I could not figure out what information is the one that should be used for the following files (ie, those that were in our tree, or those that came from Linus' patch), please, check these: include/asm-mips/jazz.h include/asm-mips/jazzdma.h include/asm-mips/ioctls.h
Diffstat (limited to 'arch')
-rw-r--r--arch/alpha/kernel/ptrace.c2
-rw-r--r--arch/alpha/kernel/signal.c4
-rw-r--r--arch/i386/boot/setup.S2
-rw-r--r--arch/i386/defconfig3
-rw-r--r--arch/i386/kernel/ptrace.c2
-rw-r--r--arch/i386/kernel/signal.c4
-rw-r--r--arch/i386/kernel/smp.c3
-rw-r--r--arch/i386/mm/init.c10
-rw-r--r--arch/m68k/Makefile4
-rw-r--r--arch/m68k/amiga/amikeyb.c18
-rw-r--r--arch/m68k/amiga/zorro.c2
-rw-r--r--arch/m68k/boot/Makefile65
-rw-r--r--arch/m68k/boot/amiga/bootstrap.c335
-rw-r--r--arch/m68k/boot/amiga/bootstrap.h149
-rw-r--r--arch/m68k/boot/amiga/linuxboot.c1692
-rw-r--r--arch/m68k/boot/amiga/linuxboot.h455
-rw-r--r--arch/m68k/boot/atari/bootp.c814
-rw-r--r--arch/m68k/boot/atari/bootp.h44
-rw-r--r--arch/m68k/boot/atari/bootstrap.c1602
-rw-r--r--arch/m68k/boot/atari/bootstrap.h171
-rw-r--r--arch/m68k/boot/atari/ethlance.c435
-rw-r--r--arch/m68k/boot/atari/ethlance.h7
-rw-r--r--arch/m68k/boot/atari/sysvars.h22
-rw-r--r--arch/m68k/config.in5
-rw-r--r--arch/m68k/defconfig3
-rw-r--r--arch/m68k/ifpsp060/iskeleton.S1
-rw-r--r--arch/m68k/kernel/console.c10
-rw-r--r--arch/m68k/kernel/entry.S2
-rw-r--r--arch/m68k/kernel/head.S3
-rw-r--r--arch/m68k/kernel/process.c5
-rw-r--r--arch/m68k/kernel/sys_m68k.c178
-rw-r--r--arch/mips/boot/Makefile1
-rw-r--r--arch/mips/config.in2
-rw-r--r--arch/mips/kernel/irixsig.c8
-rw-r--r--arch/mips/kernel/ptrace.c2
-rw-r--r--arch/mips/kernel/signal.c6
-rw-r--r--arch/mips/kernel/syscalls.h4
-rw-r--r--arch/mips/kernel/sysirix.c8
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/lib/dump_tlb.c44
-rw-r--r--arch/mips/mm/r4xx0.c4
-rw-r--r--arch/ppc/Makefile63
-rw-r--r--arch/ppc/boot/Makefile57
-rw-r--r--arch/ppc/boot/cortstrip.c73
-rw-r--r--arch/ppc/boot/gzip.h2
-rw-r--r--arch/ppc/boot/head.S1
-rw-r--r--arch/ppc/boot/inflate.c2
-rw-r--r--arch/ppc/boot/misc.c90
-rw-r--r--arch/ppc/boot/mk_type41.c208
-rw-r--r--arch/ppc/boot/mkprep.c337
-rw-r--r--arch/ppc/boot/piggyback.c64
-rw-r--r--arch/ppc/boot/unzip.c2
-rw-r--r--arch/ppc/boot/vreset.c1093
-rw-r--r--arch/ppc/config.in75
-rw-r--r--arch/ppc/kernel/Makefile45
-rw-r--r--arch/ppc/kernel/head.S2866
-rw-r--r--arch/ppc/kernel/irq.c810
-rw-r--r--arch/ppc/kernel/ksyms.c36
-rw-r--r--arch/ppc/kernel/misc.S697
-rw-r--r--arch/ppc/kernel/mk_defs.c261
-rw-r--r--arch/ppc/kernel/pci.c326
-rw-r--r--arch/ppc/kernel/port_io.c181
-rw-r--r--arch/ppc/kernel/ppc_asm.tmpl47
-rw-r--r--arch/ppc/kernel/process.c716
-rw-r--r--arch/ppc/kernel/ptrace.c158
-rw-r--r--arch/ppc/kernel/setup.c409
-rw-r--r--arch/ppc/kernel/signal.c208
-rw-r--r--arch/ppc/kernel/stubs.c58
-rw-r--r--arch/ppc/kernel/support.c84
-rw-r--r--arch/ppc/kernel/syscalls.c201
-rw-r--r--arch/ppc/kernel/time.c465
-rw-r--r--arch/ppc/kernel/traps.c154
-rw-r--r--arch/ppc/kernel/usercpy.c116
-rw-r--r--arch/ppc/ld.script36
-rw-r--r--arch/ppc/lib/Makefile36
-rw-r--r--arch/ppc/mm/Makefile6
-rw-r--r--arch/ppc/mm/fault.c264
-rw-r--r--arch/ppc/mm/init.c1558
-rw-r--r--arch/sparc/defconfig7
-rw-r--r--arch/sparc/kernel/sys_sunos.c7
-rw-r--r--arch/sparc/mm/srmmu.c9
-rw-r--r--arch/sparc/mm/sun4c.c9
-rw-r--r--arch/sparc64/defconfig5
-rw-r--r--arch/sparc64/kernel/Makefile20
-rw-r--r--arch/sparc64/kernel/auxio.c3
-rw-r--r--arch/sparc64/kernel/cpu.c9
-rw-r--r--arch/sparc64/kernel/devices.c2
-rw-r--r--arch/sparc64/kernel/entry.S4
-rw-r--r--arch/sparc64/kernel/ioctl32.c19
-rw-r--r--arch/sparc64/kernel/ioport.c4
-rw-r--r--arch/sparc64/kernel/irq.c229
-rw-r--r--arch/sparc64/kernel/process.c66
-rw-r--r--arch/sparc64/kernel/setup.c8
-rw-r--r--arch/sparc64/kernel/smp.c136
-rw-r--r--arch/sparc64/kernel/time.c63
-rw-r--r--arch/sparc64/lib/locks.S118
-rw-r--r--arch/sparc64/mm/Makefile14
-rw-r--r--arch/sparc64/mm/init.c13
-rw-r--r--arch/sparc64/mm/ultra.S3
-rw-r--r--arch/sparc64/prom/console.c4
-rw-r--r--arch/sparc64/prom/misc.c4
-rw-r--r--arch/sparc64/prom/p1275.c4
102 files changed, 6680 insertions, 12018 deletions
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index c388f0b51..84cde1b4f 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -650,7 +650,7 @@ asmlinkage void syscall_trace(void)
goto out;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 5c3eb79ef..9f71e6146 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -315,7 +315,7 @@ asmlinkage int do_signal(unsigned long oldmask,
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
single_stepping |= ptrace_cancel_bpt(current);
if (!(signr = current->exit_code))
@@ -354,7 +354,7 @@ asmlinkage int do_signal(unsigned long oldmask,
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
single_stepping |= ptrace_cancel_bpt(current);
continue;
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 7553ce943..edc0fe0ff 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -272,8 +272,8 @@ loader_ok:
! and fall into the old memory detection code to populate the
! compatability slot.
- pop ebx
oldstylemem:
+ pop ebx
#endif
mov ah,#0x88
int 0x15
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 430d6b971..e3e50886c 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -139,6 +139,7 @@ CONFIG_SCSI_OMIT_FLASHPOINT=y
# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_NCR53C7xx is not set
# CONFIG_SCSI_NCR53C8XX is not set
+# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_PAS16 is not set
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
@@ -171,6 +172,7 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
# CONFIG_DLCI is not set
+# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_NET_RADIO is not set
# CONFIG_SLIP is not set
@@ -234,6 +236,7 @@ CONFIG_82C710_MOUSE=y
# CONFIG_APM is not set
# CONFIG_WATCHDOG is not set
# CONFIG_RTC is not set
+# CONFIG_NVRAM is not set
# CONFIG_JOYSTICK is not set
#
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index 0dfffd672..c8a7f986e 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -577,7 +577,7 @@ asmlinkage void syscall_trace(void)
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index 3141c5318..f5af47201 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -346,7 +346,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
if (!(signr = current->exit_code))
continue;
@@ -386,7 +386,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
continue;
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 5a020b723..d187128e1 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -156,6 +156,9 @@ volatile unsigned long smp_idle_map=0; /* Map for idle processors */
volatile unsigned long smp_proc_in_lock[NR_CPUS] = {0,};/* for computing process time */
volatile int smp_process_available=0;
+const char lk_lockmsg[] = "lock from interrupt context at %p\n";
+
+
/*#define SMP_DEBUG*/
#ifdef SMP_DEBUG
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index c8371aa81..8f2852a48 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -209,7 +209,7 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
pgd_val(pg_dir[0]) = 0;
/* Map whole memory from 0xC0000000 */
-
+ pg_dir += 768;
while (address < end_mem) {
/*
* If we're running on a Pentium CPU, we can use the 4MB
@@ -224,13 +224,13 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
set_in_cr4(X86_CR4_PSE);
wp_works_ok = 1;
- __pe = _PAGE_TABLE + _PAGE_4M + __pa(address);
+ __pe = _KERNPG_TABLE + _PAGE_4M + __pa(address);
/* Make it "global" too if supported */
if (x86_capability & X86_FEATURE_PGE) {
set_in_cr4(X86_CR4_PGE);
__pe += _PAGE_GLOBAL;
}
- pgd_val(pg_dir[768]) = _PAGE_TABLE + _PAGE_4M + __pa(address);
+ pgd_val(*pg_dir) = __pe;
pg_dir++;
address += 4*1024*1024;
continue;
@@ -239,13 +239,13 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
* We're on a [34]86, use normal page tables.
* pg_table is physical at this point
*/
- pg_table = (pte_t *) (PAGE_MASK & pgd_val(pg_dir[768]));
+ pg_table = (pte_t *) (PAGE_MASK & pgd_val(*pg_dir));
if (!pg_table) {
pg_table = (pte_t *) __pa(start_mem);
start_mem += PAGE_SIZE;
}
- pgd_val(pg_dir[768]) = _PAGE_TABLE | (unsigned long) pg_table;
+ pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pg_table;
pg_dir++;
/* now change pg_table to kernel virtual addresses */
pg_table = (pte_t *) __va(pg_table);
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 7548a8dc8..94257b578 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -79,8 +79,6 @@ CORE_FILES := $(CORE_FILES) arch/m68k/ifpsp060/ifpsp.o
SUBDIRS := $(SUBDIRS) arch/m68k/ifpsp060
endif
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-
lilo: vmlinux
if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
@@ -106,7 +104,5 @@ bootstrap: dummy
archclean:
rm -f vmlinux.gz
- @$(MAKEBOOT) clean
archdep:
- $(MAKEBOOT) dep
diff --git a/arch/m68k/amiga/amikeyb.c b/arch/m68k/amiga/amikeyb.c
index 06fe55d29..5a102a12c 100644
--- a/arch/m68k/amiga/amikeyb.c
+++ b/arch/m68k/amiga/amikeyb.c
@@ -195,7 +195,7 @@ static void amikeyb_rep(unsigned long ignore)
static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
- unsigned char scancode, break_flag;
+ unsigned char scancode, break_flag, keycode;
static int reset_warning = 0;
/* save frame for register dump */
@@ -207,6 +207,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
/* switch SP pin to output for handshake */
ciaa.cra |= 0x40;
+#if 0 // No longer used
/*
* On receipt of the second RESET_WARNING, we must not pull KDAT high
* again to delay the hard reset as long as possible.
@@ -222,6 +223,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
} else
/* Probably a mistake, cancel the alert */
reset_warning = 0;
+#endif
/* wait until 85 us have expired */
udelay(85);
@@ -237,27 +239,27 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
* Check make/break first
*/
break_flag = scancode & BREAK_MASK;
- scancode &= (unsigned char )~BREAK_MASK;
+ keycode = scancode & (unsigned char)~BREAK_MASK;
- if (scancode == AMIKEY_CAPS) {
+ if (keycode == AMIKEY_CAPS) {
/* if the key is CAPS, fake a press/release. */
handle_scancode(AMIKEY_CAPS);
handle_scancode(BREAK_MASK | AMIKEY_CAPS);
- } else if (scancode < 0x78) {
+ } else if (keycode < 0x78) {
/* handle repeat */
if (break_flag) {
del_timer(&amikeyb_rep_timer);
rep_scancode = 0;
} else {
del_timer(&amikeyb_rep_timer);
- rep_scancode = scancode;
+ rep_scancode = keycode;
amikeyb_rep_timer.expires = jiffies + key_repeat_delay;
amikeyb_rep_timer.prev = amikeyb_rep_timer.next = NULL;
add_timer(&amikeyb_rep_timer);
}
- handle_scancode(break_flag | scancode);
+ handle_scancode(scancode);
} else
- switch (scancode) {
+ switch (keycode) {
case 0x78:
reset_warning = 1;
break;
@@ -288,7 +290,7 @@ static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
#endif
default:
printk(KERN_WARNING "amikeyb: unknown keyboard communication code 0x%02x\n",
- break_flag | scancode);
+ scancode);
break;
}
}
diff --git a/arch/m68k/amiga/zorro.c b/arch/m68k/amiga/zorro.c
index d64ad8ce3..1da948134 100644
--- a/arch/m68k/amiga/zorro.c
+++ b/arch/m68k/amiga/zorro.c
@@ -730,7 +730,7 @@ int zorro_find(int manuf, int prod, int part, int index)
{
int key;
struct ConfigDev *cd;
-
+
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
return(0);
diff --git a/arch/m68k/boot/Makefile b/arch/m68k/boot/Makefile
index 822030ebb..e69de29bb 100644
--- a/arch/m68k/boot/Makefile
+++ b/arch/m68k/boot/Makefile
@@ -1,65 +0,0 @@
-#
-# linux/arch/m68k/boot/Makefile
-#
-# This file is subject to the terms and conditions of the GNU General Public
-# License. See the file "COPYING" in the main directory of this archive
-# for more details.
-
-ifdef CONFIG_AMIGA
-AMIGA_BOOTSTRAP = amiga_bootstrap
-AMIGA_BOOTOBJS := amiga/bootstrap.o amiga/linuxboot.o
-AMIGA_HOSTCC = m68k-cbm-amigados-gcc
-AMIGA_HOSTINC = -I$(TOPDIR)/include
-AMIGA_HOSTFLAGS=-m68030 -O2 -Wall -Dlinux
-endif
-
-ifdef CONFIG_ATARI
-ATARI_BOOTSTRAP = atari_bootstrap
-ATARI_BOOTOBJS := atari/bootstrap.o
-ATARI_HOSTCC = m68k-mint-gcc
-ATARI_HOSTINC = -I$(TOPDIR)/include
-ATARI_HOSTFLAGS = -m68030 -m68881 -Dlinux -O2 -Wall
-
-# BOOTP/TFTP support in bootstrap?
-# USE_BOOTP = y
-
-ifdef USE_BOOTP
-ATARI_BOOTOBJS += atari/bootp.o
-ATARI_HOSTFLAGS += -DUSE_BOOTP
-
-# low-level Ethernet drivers:
-
-# Lance (RieblCard, PAM-VME)
-ATARI_BOOTOBJS += atari/ethlance.o
-ATARI_HOSTFLAGS += -DETHLL_LANCE
-
-endif
-endif
-
-ifdef CONFIG_ATARI
-atari_bootstrap: $(ATARI_BOOTOBJS)
- $(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -o $@ $(ATARI_BOOTOBJS)
- rm -f ../../../bootstrap
- ln $@ ../../../bootstrap
-endif
-
-ifdef CONFIG_AMIGA
-amiga_bootstrap: $(AMIGA_BOOTOBJS)
- $(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -o $@ -s -noixemul $(AMIGA_BOOTOBJS)
- rm -f ../../../bootstrap
- ln $@ ../../../bootstrap
-endif
-
-$(AMIGA_BOOTOBJS): %.o: %.c
- $(AMIGA_HOSTCC) $(AMIGA_HOSTINC) $(AMIGA_HOSTFLAGS) -c $< -o $@
-
-$(ATARI_BOOTOBJS): %.o: %.c
- $(ATARI_HOSTCC) $(ATARI_HOSTINC) $(ATARI_HOSTFLAGS) -c $< -o $@
-
-bootstrap: $(AMIGA_BOOTSTRAP) $(ATARI_BOOTSTRAP)
-
-clean:
- rm -f *.o amiga/*.o atari/*.o amiga_bootstrap atari_bootstrap \
- ../../../bootstrap
-
-dep:
diff --git a/arch/m68k/boot/amiga/bootstrap.c b/arch/m68k/boot/amiga/bootstrap.c
index 41ac75ada..e69de29bb 100644
--- a/arch/m68k/boot/amiga/bootstrap.c
+++ b/arch/m68k/boot/amiga/bootstrap.c
@@ -1,335 +0,0 @@
-/*
-** linux/arch/m68k/boot/amiga/bootstrap.c -- This program loads the Linux/m68k
-** kernel into an Amiga and launches
-** it.
-**
-** Copyright 1993,1994 by Hamish Macdonald, Greg Harp
-**
-** Modified 11-May-94 by Geert Uytterhoeven
-** (Geert.Uytterhoeven@cs.kuleuven.ac.be)
-** - A3640 MapROM check
-** Modified 31-May-94 by Geert Uytterhoeven
-** - Memory thrash problem solved
-** Modified 07-March-95 by Geert Uytterhoeven
-** - Memory block sizes are rounded to a multiple of 256K instead of 1M
-** This _requires_ >0.9pl5 to work!
-** (unless all block sizes are multiples of 1M :-)
-** Modified 11-July-95 by Andreas Schwab
-** - Support for ELF kernel (untested!)
-** Modified 10-Jan-96 by Geert Uytterhoeven
-** - The real Linux/m68k boot code moved to linuxboot.[ch]
-** Modified 9-Sep-96 by Geert Uytterhoeven
-** - Rewritten option parsing
-** - New parameter passing to linuxboot() (linuxboot_args)
-** Modified 6-Oct-96 by Geert Uytterhoeven
-** - Updated for the new boot information structure
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file COPYING in the main directory of this archive
-** for more details.
-**
-*/
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <sys/file.h>
-#include <unistd.h>
-
-/* required Linux/m68k include files */
-#define __KERNEL_STRICT_NAMES /* This is ugly, I know */
-#define _LINUX_POSIX_TYPES_H
-#include <asm/posix_types.h>
-#include <linux/a.out.h>
-#include <linux/elf.h>
-#include <asm/amigahw.h>
-#include <asm/page.h>
-
-/* Amiga bootstrap include files */
-#include "linuxboot.h"
-#include "bootstrap.h"
-
-
-/* Library Bases */
-long __oslibversion = 36;
-extern const struct ExecBase *SysBase;
-
-static const char *memfile_name = NULL;
-
-static int model = AMI_UNKNOWN;
-
-static const char *ProgramName;
-
-struct linuxboot_args args;
-
-
- /*
- * Function Prototypes
- */
-
-static void Usage(void) __attribute__ ((noreturn));
-int main(int argc, char *argv[]);
-static void Puts(const char *str);
-static long GetChar(void);
-static void PutChar(char c);
-static void Printf(const char *fmt, ...);
-static int Open(const char *path);
-static int Seek(int fd, int offset);
-static int Read(int fd, char *buf, int count);
-static void Close(int fd);
-static int FileSize(const char *path);
-static void Sleep(u_long micros);
-
-
-static void Usage(void)
-{
- fprintf(stderr,
- "Linux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n\n"
- "Usage: %s [options] [kernel command line]\n\n"
- "Basic options:\n"
- " -h, --help Display this usage information\n"
- " -k, --kernel file Use kernel image `file' (default is `vmlinux')\n"
- " -r, --ramdisk file Use ramdisk image `file'\n"
- "Advanced options:\n"
- " -d, --debug Enable debug mode\n"
- " -b, --baud speed Set the serial port speed (default is 9600)\n"
- " -m, --memfile file Use memory file `file'\n"
- " -v, --keep-video Don't reset the video mode\n"
- " -t, --model id Set the Amiga model to `id'\n"
- " -p, --processor cfm Set the processor type to `cfm\n\n",
- ProgramName);
- exit(EXIT_FAILURE);
-}
-
-
-int main(int argc, char *argv[])
-{
- int i;
- int processor = 0, debugflag = 0, keep_video = 0;
- u_int baud = 0;
- const char *kernel_name = NULL;
- const char *ramdisk_name = NULL;
- char commandline[CL_SIZE] = "";
-
- ProgramName = argv[0];
- while (--argc) {
- argv++;
- if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help"))
- Usage();
- else if (!strcmp(argv[0], "-k") || !strcmp(argv[0], "--kernel"))
- if (--argc && !kernel_name) {
- kernel_name = argv[1];
- argv++;
- } else
- Usage();
- else if (!strcmp(argv[0], "-r") || !strcmp(argv[0], "--ramdisk"))
- if (--argc && !ramdisk_name) {
- ramdisk_name = argv[1];
- argv++;
- } else
- Usage();
- else if (!strcmp(argv[0], "-d") || !strcmp(argv[0], "--debug"))
- debugflag = 1;
- else if (!strcmp(argv[0], "-b") || !strcmp(argv[0], "--baud"))
- if (--argc && !baud) {
- baud = atoi(argv[1]);
- argv++;
- } else
- Usage();
- else if (!strcmp(argv[0], "-m") || !strcmp(argv[0], "--memfile"))
- if (--argc && !memfile_name) {
- memfile_name = argv[1];
- argv++;
- } else
- Usage();
- else if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--keep-video"))
- keep_video = 1;
- else if (!strcmp(argv[0], "-t") || !strcmp(argv[0], "--model"))
- if (--argc && !model) {
- model = atoi(argv[1]);
- argv++;
- } else
- Usage();
- else if (!strcmp(argv[0], "-p") || !strcmp(argv[0], "--processor"))
- if (--argc && !processor) {
- processor = atoi(argv[1]);
- argv++;
- } else
- Usage();
- else
- break;
- }
- if (!kernel_name)
- kernel_name = "vmlinux";
-
- SysBase = *(struct ExecBase **)4;
-
- /*
- * Join command line options
- */
- i = 0;
- while (argc--) {
- if ((i+strlen(*argv)+1) < CL_SIZE) {
- i += strlen(*argv) + 1;
- if (commandline[0])
- strcat(commandline, " ");
- strcat(commandline, *argv++);
- }
- }
-
- memset(&args.bi, 0, sizeof(args.bi));
- if (processor) {
- int cpu = processor/100%10;
- int fpu = processor/10%10;
- int mmu = processor%10;
- if (cpu)
- args.bi.cputype = 1<<(cpu-1);
- if (fpu)
- args.bi.fputype = 1<<(fpu-1);
- if (mmu)
- args.bi.mmutype = 1<<(mmu-1);
- }
- /*
- * If we have a memory file, read the memory information from it
- */
- if (memfile_name) {
- FILE *fp;
- int i;
-
- if ((fp = fopen(memfile_name, "r")) == NULL) {
- perror("open memory file");
- fprintf(stderr, "Cannot open memory file %s\n", memfile_name);
- return(FALSE);
- }
-
- if (fscanf(fp, "%lu", &args.bi.chip_size) != 1) {
- fprintf(stderr, "memory file does not contain chip memory size\n");
- fclose(fp);
- return(FALSE);
- }
-
- for (i = 0; i < NUM_MEMINFO; i++)
- if (fscanf(fp, "%lx %lu", &args.bi.memory[i].addr,
- &args.bi.memory[i].size) != 2)
- break;
-
- fclose(fp);
- args.bi.num_memory = i;
- }
- strncpy(args.bi.command_line, commandline, CL_SIZE);
- args.bi.command_line[CL_SIZE-1] = '\0';
- if (model != AMI_UNKNOWN)
- args.bi.model = model;
-
- args.kernelname = kernel_name;
- args.ramdiskname = ramdisk_name;
- args.debugflag = debugflag;
- args.keep_video = keep_video;
- args.reset_boards = 1;
- args.baud = baud;
- args.puts = Puts;
- args.getchar = GetChar;
- args.putchar = PutChar;
- args.printf = Printf;
- args.open = Open;
- args.seek = Seek;
- args.read = Read;
- args.close = Close;
- args.filesize = FileSize;
- args.sleep = Sleep;
-
- /* Do The Right Stuff */
- linuxboot(&args);
-
- /* if we ever get here, something went wrong */
- exit(EXIT_FAILURE);
-}
-
-
- /*
- * Routines needed by linuxboot
- */
-
-static void Puts(const char *str)
-{
- fputs(str, stderr);
- fflush(stderr);
-}
-
-static long GetChar(void)
-{
- return(getchar());
-}
-
-static void PutChar(char c)
-{
- fputc(c, stderr);
- fflush(stderr);
-}
-
-static void Printf(const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fflush(stderr);
-}
-
-static int Open(const char *path)
-{
- return(open(path, O_RDONLY));
-}
-
-static int Seek(int fd, int offset)
-{
- return(lseek(fd, offset, SEEK_SET));
-}
-
-
-static int Read(int fd, char *buf, int count)
-{
- return(read(fd, buf, count));
-}
-
-static void Close(int fd)
-{
- close(fd);
-}
-
-static int FileSize(const char *path)
-{
- int fd, size = -1;
-
- if ((fd = open(path, O_RDONLY)) != -1) {
- size = lseek(fd, 0, SEEK_END);
- close(fd);
- }
- return(size);
-}
-
-static void Sleep(u_long micros)
-{
- struct MsgPort *TimerPort;
- struct timerequest *TimerRequest;
-
- if ((TimerPort = CreateMsgPort())) {
- if ((TimerRequest = CreateIORequest(TimerPort,
- sizeof(struct timerequest)))) {
- if (!OpenDevice("timer.device", UNIT_VBLANK,
- (struct IORequest *)TimerRequest, 0)) {
- TimerRequest->io_Command = TR_ADDREQUEST;
- TimerRequest->io_Flags = IOF_QUICK;
- TimerRequest->tv_secs = micros/1000000;
- TimerRequest->tv_micro = micros%1000000;
- DoIO((struct IORequest *)TimerRequest);
- CloseDevice((struct IORequest *)TimerRequest);
- }
- DeleteIORequest(TimerRequest);
- }
- DeleteMsgPort(TimerPort);
- }
-}
diff --git a/arch/m68k/boot/amiga/bootstrap.h b/arch/m68k/boot/amiga/bootstrap.h
index 4d072cc75..e69de29bb 100644
--- a/arch/m68k/boot/amiga/bootstrap.h
+++ b/arch/m68k/boot/amiga/bootstrap.h
@@ -1,149 +0,0 @@
-/*
-** linux/arch/m68k/boot/amiga/bootstrap.h -- This file is part of the Amiga
-** bootloader.
-**
-** Copyright 1993, 1994 by Hamish Macdonald
-**
-** Some minor additions by Michael Rausch 1-11-94
-** Modified 11-May-94 by Geert Uytterhoeven
-** (Geert.Uytterhoeven@cs.kuleuven.ac.be)
-** - inline Supervisor() call
-** Modified 10-Jan-96 by Geert Uytterhoeven
-** - The real Linux/m68k boot code moved to linuxboot.[ch]
-** Modified 9-Sep-96 by Geert Uytterhoeven
-** - const library bases
-** - fixed register naming for m68k-cbm-amigados-gcc
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file COPYING in the main directory of this archive
-** for more details.
-**
-*/
-
-
-struct MsgPort {
- u_char fill1[15];
- u_char mp_SigBit;
- u_char fill2[18];
-};
-
-struct IOStdReq {
- u_char fill1[20];
- struct Device *io_Device;
- u_char fill2[4];
- u_short io_Command;
- u_char io_Flags;
- char io_Error;
- u_long io_Actual;
- u_long io_Length;
- void *io_Data;
- u_char fill4[4];
-};
-
-#define IOF_QUICK (1<<0)
-
-struct timerequest {
- u_char fill1[28];
- u_short io_Command;
- u_char io_Flags;
- u_char fill2[1];
- u_long tv_secs;
- u_long tv_micro;
-};
-
-#define UNIT_VBLANK 1
-#define TR_ADDREQUEST 9
-
-
-struct Library;
-struct IORequest;
-
-
-static __inline char OpenDevice(u_char *devName, u_long unit,
- struct IORequest *ioRequest, u_long flags)
-{
- register char _res __asm("d0");
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register u_char *a0 __asm("a0") = devName;
- register u_long d0 __asm("d0") = unit;
- register struct IORequest *a1 __asm("a1") = ioRequest;
- register u_long d1 __asm("d1") = flags;
-
- __asm __volatile ("jsr a6@(-0x1bc)"
- : "=r" (_res)
- : "r" (a6), "r" (a0), "r" (a1), "r" (d0), "r" (d1)
- : "a0","a1","d0","d1", "memory");
- return(_res);
-}
-
-static __inline void CloseDevice(struct IORequest *ioRequest)
-{
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register struct IORequest *a1 __asm("a1") = ioRequest;
-
- __asm __volatile ("jsr a6@(-0x1c2)"
- : /* no output */
- : "r" (a6), "r" (a1)
- : "a0","a1","d0","d1", "memory");
-}
-
-static __inline char DoIO(struct IORequest *ioRequest)
-{
- register char _res __asm("d0");
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register struct IORequest *a1 __asm("a1") = ioRequest;
-
- __asm __volatile ("jsr a6@(-0x1c8)"
- : "=r" (_res)
- : "r" (a6), "r" (a1)
- : "a0","a1","d0","d1", "memory");
- return(_res);
-}
-
-static __inline void *CreateIORequest(struct MsgPort *port, u_long size)
-{
- register struct Library *_res __asm("d0");
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register struct MsgPort *a0 __asm("a0") = port;
- register u_long d0 __asm("d0") = size;
-
- __asm __volatile ("jsr a6@(-0x28e)"
- : "=r" (_res)
- : "r" (a6), "r" (a0), "r" (d0)
- : "a0","a1","d0","d1", "memory");
- return(_res);
-}
-
-static __inline void DeleteIORequest(void *ioRequest)
-{
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register void *a0 __asm("a0") = ioRequest;
-
- __asm __volatile ("jsr a6@(-0x294)"
- : /* no output */
- : "r" (a6), "r" (a0)
- : "a0","a1","d0","d1", "memory");
-}
-
-static __inline struct MsgPort *CreateMsgPort(void)
-{
- register struct MsgPort *_res __asm("d0");
- register const struct ExecBase *a6 __asm("a6") = SysBase;
-
- __asm __volatile ("jsr a6@(-0x29a)"
- : "=r" (_res)
- : "r" (a6)
- : "a0","a1","d0","d1", "memory");
- return(_res);
-}
-
-static __inline void DeleteMsgPort(struct MsgPort *port)
-{
- register const struct ExecBase *a6 __asm("a6") = SysBase;
- register struct MsgPort *a0 __asm("a0") = port;
-
- __asm __volatile ("jsr a6@(-0x2a0)"
- : /* no output */
- : "r" (a6), "r" (a0)
- : "a0","a1","d0","d1", "memory");
-}
diff --git a/arch/m68k/boot/amiga/linuxboot.c b/arch/m68k/boot/amiga/linuxboot.c
index 74b873bf2..e69de29bb 100644
--- a/arch/m68k/boot/amiga/linuxboot.c
+++ b/arch/m68k/boot/amiga/linuxboot.c
@@ -1,1692 +0,0 @@
-/*
- * linux/arch/m68k/boot/amiga/linuxboot.c -- Generic routine to boot Linux/m68k
- * on Amiga, used by both Amiboot and
- * Amiga-Lilo.
- *
- * Created 1996 by Geert Uytterhoeven
- *
- *
- * This file is based on the original bootstrap code (bootstrap.c):
- *
- * Copyright (C) 1993, 1994 Hamish Macdonald
- * Greg Harp
- *
- * with work by Michael Rausch
- * Geert Uytterhoeven
- * Frank Neumann
- * Andreas Schwab
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- *
- * History:
- * 11 Jun 1997 Fix for unpadded gzipped ramdisks with bootinfo interface
- * version 1.0
- * 27 Mar 1997 FPU-less machines couldn't boot kernels that use bootinfo
- * interface version 1.0 (Geert)
- * 3 Feb 1997 Implemented kernel decompression (Geert, based on Roman's
- * code for ataboot)
- * 30 Dec 1996 Reverted the CPU detection to the old scheme
- * New boot parameter override scheme (Geert)
- * 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
- * 9 Sep 1996 Rewritten option parsing
- * New parameter passing to linuxboot() (linuxboot_args)
- * (Geert)
- * 18 Aug 1996 Updated for the new boot information structure (Geert)
- * 10 Jan 1996 The real Linux/m68k boot code moved to linuxboot.[ch]
- * (Geert)
- * 11 Jul 1995 Support for ELF kernel (untested!) (Andreas)
- * 7 Mar 1995 Memory block sizes are rounded to a multiple of 256K
- * instead of 1M (Geert)
- * 31 May 1994 Memory thrash problem solved (Geert)
- * 11 May 1994 A3640 MapROM check (Geert)
- */
-
-
-#ifndef __GNUC__
-#error GNU CC is required to compile this program
-#endif /* __GNUC__ */
-
-
-#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
-/* support compressed kernels? */
-#define ZKERNEL
-
-#include <stddef.h>
-#include <string.h>
-#include <errno.h>
-
-#include <linux/a.out.h>
-#include <linux/elf.h>
-#include <linux/linkage.h>
-#include <asm/bootinfo.h>
-#include <asm/amigahw.h>
-#include <asm/page.h>
-
-#include "linuxboot.h"
-
-
-#undef custom
-#define custom ((*(volatile struct CUSTOM *)(CUSTOM_PHYSADDR)))
-
-/* a.out linkage conventions */
-#undef SYMBOL_NAME_STR
-#define SYMBOL_NAME_STR(X) "_"#X
-
-/* temporary stack size */
-#define TEMP_STACKSIZE (256)
-
-#define DEFAULT_BAUD (9600)
-
-extern char copyall, copyallend;
-
-static struct exec kexec;
-static Elf32_Ehdr kexec_elf;
-static const struct linuxboot_args *linuxboot_args;
-
-/* Bootinfo */
-struct amiga_bootinfo bi;
-
-#ifdef BOOTINFO_COMPAT_1_0
-static struct compat_bootinfo compat_bootinfo;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-#define MAX_BI_SIZE (4096)
-static u_long bi_size;
-static union {
- struct bi_record record;
- u_char fake[MAX_BI_SIZE];
-} bi_union;
-
-#define kernelname linuxboot_args->kernelname
-#define ramdiskname linuxboot_args->ramdiskname
-#define debugflag linuxboot_args->debugflag
-#define keep_video linuxboot_args->keep_video
-#define reset_boards linuxboot_args->reset_boards
-#define baud linuxboot_args->baud
-
-#define Puts linuxboot_args->puts
-#define GetChar linuxboot_args->getchar
-#define PutChar linuxboot_args->putchar
-#define Printf linuxboot_args->printf
-#define Open linuxboot_args->open
-#define Seek linuxboot_args->seek
-#define Read linuxboot_args->read
-#define Close linuxboot_args->close
-#define FileSize linuxboot_args->filesize
-#define Sleep linuxboot_args->sleep
-
- /*
- * Function Prototypes
- */
-
-static u_long get_chipset(void);
-static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu);
-static u_long get_model(u_long chipset);
-static int probe_resident(const char *name);
-static int probe_resource(const char *name);
-static int create_bootinfo(void);
-#ifdef BOOTINFO_COMPAT_1_0
-static int create_compat_bootinfo(void);
-#endif /* BOOTINFO_COMPAT_1_0 */
-static int add_bi_record(u_short tag, u_short size, const void *data);
-static int add_bi_string(u_short tag, const u_char *s);
-static int check_bootinfo_version(const char *memptr);
-static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
- u_long start_mem, u_long kernel_size, u_long rd_dest,
- u_long rd_size) __attribute__ ((noreturn));
-asmlinkage u_long maprommed(void);
-#ifdef ZKERNEL
-static int load_zkernel(int fd);
-static int KRead(int fd, void *buf, int cnt);
-static int KSeek(int fd, int offset);
-static int KClose(int fd);
-#else
-#define KRead Read
-#define KSeek Seek
-#define KClose Close
-#endif
-
-
- /*
- * Reset functions for nasty Zorro boards
- */
-
-static void reset_rb3(const struct ConfigDev *cd);
-static void reset_piccolo(const struct ConfigDev *cd);
-static void reset_sd64(const struct ConfigDev *cd);
-static void reset_ariadne(const struct ConfigDev *cd);
-static void reset_hydra(const struct ConfigDev *cd);
-#if 0
-static void reset_a2060(const struct ConfigDev *cd);
-#endif
-
-struct boardreset {
- u_short manuf;
- u_short prod;
- const char *name;
- void (*reset)(const struct ConfigDev *cd);
-};
-
-static struct boardreset boardresetdb[] = {
- { MANUF_HELFRICH1, PROD_RAINBOW3, "Rainbow 3", reset_rb3 },
- { MANUF_HELFRICH2, PROD_PICCOLO_REG, "Piccolo", reset_piccolo },
- { MANUF_HELFRICH2, PROD_SD64_REG, "SD64", reset_sd64 },
- { MANUF_VILLAGE_TRONIC, PROD_ARIADNE, "Ariadne", reset_ariadne },
- { MANUF_HYDRA_SYSTEMS, PROD_AMIGANET, "Hydra", reset_hydra },
-#if 0
- { MANUF_COMMODORE, PROD_A2060, "A2060", reset_a2060 },
-#endif
-};
-#define NUM_BOARDRESET sizeof(boardresetdb)/sizeof(*boardresetdb)
-
-static void (*boardresetfuncs[ZORRO_NUM_AUTO])(const struct ConfigDev *cd);
-
-
-const char *amiga_models[] = {
- "Amiga 500", "Amiga 500+", "Amiga 600", "Amiga 1000", "Amiga 1200",
- "Amiga 2000", "Amiga 2500", "Amiga 3000", "Amiga 3000T", "Amiga 3000+",
- "Amiga 4000", "Amiga 4000T", "CDTV", "CD32", "Draco"
-};
-const u_long first_amiga_model = AMI_500;
-const u_long last_amiga_model = AMI_DRACO;
-
-
-#define MASK(model) (1<<AMI_##model)
-
-#define CLASS_A3000 (MASK(3000) | MASK(3000T))
-#define CLASS_A4000 (MASK(4000) | MASK(4000T))
-#define CLASS_ZKICK (MASK(500) | MASK(1000) | MASK(2000) | MASK(2500))
-
-
- /*
- * Boot the Linux/m68k Operating System
- */
-
-u_long linuxboot(const struct linuxboot_args *args)
-{
- int kfd = -1, rfd = -1, elf_kernel = 0, do_fast, do_chip;
- int i, j;
- const struct MemHeader *mnp;
- struct ConfigDev *cdp = NULL;
- char *memptr = NULL;
- u_long *stack = NULL;
- u_long fast_total, model_mask, startcodesize, start_mem, mem_size, rd_size;
- u_long kernel_size;
- u_int realbaud;
- u_long memreq = 0, text_offset = 0;
- Elf32_Phdr *kernel_phdrs = NULL;
- void (*startfunc)(void);
- u_short manuf;
- u_char prod;
- void *bi_ptr;
-
- linuxboot_args = args;
-
- /* print the greet message */
- Puts("\nLinux/m68k Amiga Bootstrap version " AMIBOOT_VERSION "\n");
- Puts("Copyright 1993,1994 by Hamish Macdonald and Greg Harp\n\n");
-
- /* Note: Initial values in bi override detected values */
- bi = args->bi;
-
- /* machine is Amiga */
- bi.machtype = MACH_AMIGA;
-
- /* determine chipset */
- if (!bi.chipset)
- bi.chipset = get_chipset();
-
- /* determine CPU, FPU and MMU type */
- if (!bi.cputype)
- get_processor(&bi.cputype, &bi.fputype, &bi.mmutype);
-
- /* determine Amiga model */
- if (!bi.model)
- bi.model = get_model(bi.chipset);
- model_mask = (bi.model != AMI_UNKNOWN) ? 1<<bi.model : 0;
-
- /* Memory & AutoConfig based on 'unix_boot.c' by C= */
-
- /* find all of the autoconfig boards in the system */
- if (!bi.num_autocon)
- for (i = 0; (cdp = (struct ConfigDev *)FindConfigDev(cdp, -1, -1)); i++)
- if (bi.num_autocon < ZORRO_NUM_AUTO)
- /* copy the contents of each structure into our boot info and
- count this device */
- memcpy(&bi.autocon[bi.num_autocon++], cdp,
- sizeof(struct ConfigDev));
- else
- Printf("Warning: too many AutoConfig devices. Ignoring device at "
- "0x%08lx\n", cdp->cd_BoardAddr);
-
- do_fast = bi.num_memory ? 0 : 1;
- do_chip = bi.chip_size ? 0 : 1;
- /* find out the memory in the system */
- for (mnp = (struct MemHeader *)SysBase->MemList.lh_Head;
- mnp->mh_Node.ln_Succ;
- mnp = (struct MemHeader *)mnp->mh_Node.ln_Succ) {
- struct MemHeader mh;
-
- /* copy the information */
- mh = *mnp;
-
- /* skip virtual memory */
- if (!(mh.mh_Attributes & MEMF_PUBLIC))
- continue;
-
- /* if we suspect that Kickstart is shadowed in an A3000,
- modify the entry to show 512K more at the top of RAM
- Check first for a MapROMmed A3640 board: overwriting the
- Kickstart image causes an infinite lock-up on reboot! */
- if ((mh.mh_Upper == (void *)0x07f80000) &&
- (model_mask & (CLASS_A3000 | CLASS_A4000)))
- if ((bi.cputype & CPU_68040) && Supervisor(maprommed))
- Puts("A3640 MapROM detected.\n");
- else if (model_mask & CLASS_A3000) {
- mh.mh_Upper = (void *)0x08000000;
- Puts("A3000 shadowed Kickstart detected.\n");
- }
-
- /* if we suspect that Kickstart is zkicked,
- modify the entry to show 512K more at the botton of RAM */
- if ((mh.mh_Lower == (void *)0x00280020) &&
- (model_mask & CLASS_ZKICK)) {
- mh.mh_Lower = (void *)0x00200000;
- Puts("ZKick detected.\n");
- }
-
- /* mask the memory limit values */
- mh.mh_Upper = (void *)((u_long)mh.mh_Upper & 0xfffff000);
- mh.mh_Lower = (void *)((u_long)mh.mh_Lower & 0xfffff000);
-
- /* if fast memory */
- if (do_fast && mh.mh_Attributes & MEMF_FAST) {
- /* set the size value to the size of this block and mask off to a
- 256K increment */
- u_long size = ((u_long)mh.mh_Upper-(u_long)mh.mh_Lower)&0xfffc0000;
- if (size > 0)
- if (bi.num_memory < NUM_MEMINFO) {
- /* record the start and size */
- bi.memory[bi.num_memory].addr = (u_long)mh.mh_Lower;
- bi.memory[bi.num_memory].size = size;
- /* count this block */
- bi.num_memory++;
- } else
- Printf("Warning: too many memory blocks. Ignoring block "
- "of %ldK at 0x%08x\n", size>>10,
- (u_long)mh.mh_Lower);
- } else if (do_chip && mh.mh_Attributes & MEMF_CHIP)
- /* if CHIP memory, record the size */
- bi.chip_size = (u_long)mh.mh_Upper;
- }
-
- /* get info from ExecBase */
- if (!bi.vblank)
- bi.vblank = SysBase->VBlankFrequency;
- if (!bi.psfreq)
- bi.psfreq = SysBase->PowerSupplyFrequency;
- if (!bi.eclock)
- bi.eclock = SysBase->ex_EClockFrequency;
-
- /* serial port */
- if (!bi.serper) {
- realbaud = baud ? baud : DEFAULT_BAUD;
- bi.serper = (5*bi.eclock+realbaud/2)/realbaud-1;
- }
-
- /* display Amiga model */
- if (bi.model >= first_amiga_model && bi.model <= last_amiga_model)
- Printf("%s ", amiga_models[bi.model-first_amiga_model]);
- else
- Puts("Amiga ");
-
- /* display the CPU type */
- Puts("CPU: ");
- switch (bi.cputype) {
- case CPU_68020:
- Puts("68020 (Do you have an MMU?)");
- break;
- case CPU_68030:
- Puts("68030");
- break;
- case CPU_68040:
- Puts("68040");
- break;
- case CPU_68060:
- Puts("68060");
- break;
- default:
- Puts("Insufficient for Linux. Aborting...\n");
- Printf("SysBase->AttnFlags = 0x%08lx\n", SysBase->AttnFlags);
- goto Fail;
- }
- switch (bi.fputype) {
- case FPU_68881:
- Puts(" with 68881 FPU");
- break;
- case FPU_68882:
- Puts(" with 68882 FPU");
- break;
- case FPU_68040:
- case FPU_68060:
- Puts(" with internal FPU");
- break;
- default:
- Puts(" without FPU");
- break;
- }
-
- /* display the chipset */
- switch (bi.chipset) {
- case CS_STONEAGE:
- Puts(", old or unknown chipset");
- break;
- case CS_OCS:
- Puts(", OCS");
- break;
- case CS_ECS:
- Puts(", ECS");
- break;
- case CS_AGA:
- Puts(", AGA chipset");
- break;
- }
-
- Puts("\n\n");
-
- /* display the command line */
- Printf("Command line is '%s'\n", bi.command_line);
-
- /* display the clock statistics */
- Printf("Vertical Blank Frequency: %ldHz\n", bi.vblank);
- Printf("Power Supply Frequency: %ldHz\n", bi.psfreq);
- Printf("EClock Frequency: %ldHz\n\n", bi.eclock);
-
- /* display autoconfig devices */
- if (bi.num_autocon) {
- Printf("Found %ld AutoConfig Device%s\n", bi.num_autocon,
- bi.num_autocon > 1 ? "s" : "");
- for (i = 0; i < bi.num_autocon; i++) {
- Printf("Device %ld: addr = 0x%08lx", i,
- (u_long)bi.autocon[i].cd_BoardAddr);
- boardresetfuncs[i] = NULL;
- if (reset_boards) {
- manuf = bi.autocon[i].cd_Rom.er_Manufacturer;
- prod = bi.autocon[i].cd_Rom.er_Product;
- for (j = 0; j < NUM_BOARDRESET; j++)
- if ((manuf == boardresetdb[j].manuf) &&
- (prod == boardresetdb[j].prod)) {
- Printf(" [%s - will be reset at kernel boot time]",
- boardresetdb[j].name);
- boardresetfuncs[i] = boardresetdb[j].reset;
- break;
- }
- }
- PutChar('\n');
- }
- } else
- Puts("No AutoConfig Devices Found\n");
-
- /* display memory */
- if (bi.num_memory) {
- Printf("\nFound %ld Block%sof Memory\n", bi.num_memory,
- bi.num_memory > 1 ? "s " : " ");
- for (i = 0; i < bi.num_memory; i++)
- Printf("Block %ld: 0x%08lx to 0x%08lx (%ldK)\n", i,
- bi.memory[i].addr, bi.memory[i].addr+bi.memory[i].size,
- bi.memory[i].size>>10);
- } else {
- Puts("No memory found?! Aborting...\n");
- goto Fail;
- }
-
- /* display chip memory size */
- Printf("%ldK of CHIP memory\n", bi.chip_size>>10);
-
- start_mem = bi.memory[0].addr;
- mem_size = bi.memory[0].size;
-
- /* tell us where the kernel will go */
- Printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
-
- /* verify that there is enough Chip RAM */
- if (bi.chip_size < 512*1024) {
- Puts("Not enough Chip RAM in this system. Aborting...\n");
- goto Fail;
- }
-
- /* verify that there is enough Fast RAM */
- for (fast_total = 0, i = 0; i < bi.num_memory; i++)
- fast_total += bi.memory[i].size;
- if (fast_total < 2*1024*1024) {
- Puts("Not enough Fast RAM in this system. Aborting...\n");
- goto Fail;
- }
-
- /* support for ramdisk */
- if (ramdiskname) {
- int size;
-
- if ((size = FileSize(ramdiskname)) == -1) {
- Printf("Unable to find size of ramdisk file `%s'\n", ramdiskname);
- goto Fail;
- }
- /* record ramdisk size */
- bi.ramdisk.size = size;
- } else
- bi.ramdisk.size = 0;
- rd_size = bi.ramdisk.size;
- bi.ramdisk.addr = (u_long)start_mem+mem_size-rd_size;
-
- /* create the bootinfo structure */
- if (!create_bootinfo())
- goto Fail;
-
- /* open kernel executable and read exec header */
- if ((kfd = Open(kernelname)) == -1) {
- Printf("Unable to open kernel file `%s'\n", kernelname);
- goto Fail;
- }
- if (KRead(kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec)) {
- Puts("Unable to read exec header from kernel file\n");
- goto Fail;
- }
-
-#ifdef ZKERNEL
- if (((unsigned char *)&kexec)[0] == 037 &&
- (((unsigned char *)&kexec)[1] == 0213 ||
- ((unsigned char *)&kexec)[1] == 0236)) {
- /* That's a compressed kernel */
- Puts("Kernel is compressed\n");
- if (load_zkernel(kfd)) {
- Puts("Decompression error -- aborting\n");
- goto Fail;
- }
- }
-#endif
-
- switch (N_MAGIC(kexec)) {
- case ZMAGIC:
- if (debugflag)
- Puts("\nLoading a.out (ZMAGIC) Linux/m68k kernel...\n");
- text_offset = N_TXTOFF(kexec);
- break;
-
- case QMAGIC:
- if (debugflag)
- Puts("\nLoading a.out (QMAGIC) Linux/m68k kernel...\n");
- text_offset = sizeof(kexec);
- /* the text size includes the exec header; remove this */
- kexec.a_text -= sizeof(kexec);
- break;
-
- default:
- /* Try to parse it as an ELF header */
- KSeek(kfd, 0);
- if ((KRead(kfd, (void *)&kexec_elf, sizeof(kexec_elf)) ==
- sizeof(kexec_elf)) &&
- (memcmp(&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)) {
- elf_kernel = 1;
- if (debugflag)
- Puts("\nLoading ELF Linux/m68k kernel...\n");
- /* A few plausibility checks */
- if ((kexec_elf.e_type != ET_EXEC) ||
- (kexec_elf.e_machine != EM_68K) ||
- (kexec_elf.e_version != EV_CURRENT)) {
- Puts("Invalid ELF header contents in kernel\n");
- goto Fail;
- }
- /* Load the program headers */
- if (!(kernel_phdrs =
- (Elf32_Phdr *)AllocMem(kexec_elf.e_phnum*sizeof(Elf32_Phdr),
- MEMF_FAST | MEMF_PUBLIC |
- MEMF_CLEAR))) {
- Puts("Unable to allocate memory for program headers\n");
- goto Fail;
- }
- KSeek(kfd, kexec_elf.e_phoff);
- if (KRead(kfd, (void *)kernel_phdrs,
- kexec_elf.e_phnum*sizeof(*kernel_phdrs)) !=
- kexec_elf.e_phnum*sizeof(*kernel_phdrs)) {
- Puts("Unable to read program headers from kernel file\n");
- goto Fail;
- }
- break;
- }
- Printf("Wrong magic number 0x%08lx in kernel header\n",
- N_MAGIC(kexec));
- goto Fail;
- }
-
- /* Load the kernel at one page after start of mem */
- start_mem += PAGE_SIZE;
- mem_size -= PAGE_SIZE;
- /* Align bss size to multiple of four */
- if (!elf_kernel)
- kexec.a_bss = (kexec.a_bss+3) & ~3;
-
- /* calculate the total required amount of memory */
- if (elf_kernel) {
- u_long min_addr = 0xffffffff, max_addr = 0;
- for (i = 0; i < kexec_elf.e_phnum; i++) {
- if (min_addr > kernel_phdrs[i].p_vaddr)
- min_addr = kernel_phdrs[i].p_vaddr;
- if (max_addr < kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz)
- max_addr = kernel_phdrs[i].p_vaddr+kernel_phdrs[i].p_memsz;
- }
- /* This is needed for newer linkers that include the header in
- the first segment. */
- if (min_addr == 0) {
- min_addr = PAGE_SIZE;
- kernel_phdrs[0].p_vaddr += PAGE_SIZE;
- kernel_phdrs[0].p_offset += PAGE_SIZE;
- kernel_phdrs[0].p_filesz -= PAGE_SIZE;
- kernel_phdrs[0].p_memsz -= PAGE_SIZE;
- }
- kernel_size = max_addr-min_addr;
- } else
- kernel_size = kexec.a_text+kexec.a_data+kexec.a_bss;
- memreq = kernel_size+bi_size+rd_size;
-#ifdef BOOTINFO_COMPAT_1_0
- if (sizeof(compat_bootinfo) > bi_size)
- memreq = kernel_size+sizeof(compat_bootinfo)+rd_size;
-#endif /* BOOTINFO_COMPAT_1_0 */
- if (!(memptr = (char *)AllocMem(memreq, MEMF_FAST | MEMF_PUBLIC |
- MEMF_CLEAR))) {
- Puts("Unable to allocate memory\n");
- goto Fail;
- }
-
- /* read the text and data segments from the kernel image */
- if (elf_kernel)
- for (i = 0; i < kexec_elf.e_phnum; i++) {
- if (KSeek(kfd, kernel_phdrs[i].p_offset) == -1) {
- Printf("Failed to seek to segment %ld\n", i);
- goto Fail;
- }
- if (KRead(kfd, memptr+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
- kernel_phdrs[i].p_filesz) != kernel_phdrs[i].p_filesz) {
- Printf("Failed to read segment %ld\n", i);
- goto Fail;
- }
- }
- else {
- if (KSeek(kfd, text_offset) == -1) {
- Puts("Failed to seek to text\n");
- goto Fail;
- }
- if (KRead(kfd, memptr, kexec.a_text) != kexec.a_text) {
- Puts("Failed to read text\n");
- goto Fail;
- }
- /* data follows immediately after text */
- if (KRead(kfd, memptr+kexec.a_text, kexec.a_data) != kexec.a_data) {
- Puts("Failed to read data\n");
- goto Fail;
- }
- }
- KClose(kfd);
- kfd = -1;
-
- /* Check kernel's bootinfo version */
- switch (check_bootinfo_version(memptr)) {
- case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
- bi_ptr = &bi_union.record;
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
- if (!create_compat_bootinfo())
- goto Fail;
- bi_ptr = &compat_bootinfo;
- bi_size = sizeof(compat_bootinfo);
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- goto Fail;
- }
-
- /* copy the bootinfo to the end of the kernel image */
- memcpy((void *)(memptr+kernel_size), bi_ptr, bi_size);
-
- if (ramdiskname) {
- if ((rfd = Open(ramdiskname)) == -1) {
- Printf("Unable to open ramdisk file `%s'\n", ramdiskname);
- goto Fail;
- }
- if (Read(rfd, memptr+kernel_size+bi_size, rd_size) != rd_size) {
- Puts("Failed to read ramdisk file\n");
- goto Fail;
- }
- Close(rfd);
- rfd = -1;
- }
-
- /* allocate temporary chip ram stack */
- if (!(stack = (u_long *)AllocMem(TEMP_STACKSIZE, MEMF_CHIP | MEMF_CLEAR))) {
- Puts("Unable to allocate memory for stack\n");
- goto Fail;
- }
-
- /* allocate chip ram for copy of startup code */
- startcodesize = &copyallend-&copyall;
- if (!(startfunc = (void (*)(void))AllocMem(startcodesize,
- MEMF_CHIP | MEMF_CLEAR))) {
- Puts("Unable to allocate memory for startcode\n");
- goto Fail;
- }
-
- /* copy startup code to CHIP RAM */
- memcpy(startfunc, &copyall, startcodesize);
-
- if (debugflag) {
- if (bi.ramdisk.size)
- Printf("RAM disk at 0x%08lx, size is %ldK\n",
- (u_long)memptr+kernel_size+bi_size, bi.ramdisk.size>>10);
-
- if (elf_kernel) {
- PutChar('\n');
- for (i = 0; i < kexec_elf.e_phnum; i++)
- Printf("Kernel segment %ld at 0x%08lx, size %ld\n", i,
- start_mem+kernel_phdrs[i].p_vaddr-PAGE_SIZE,
- kernel_phdrs[i].p_memsz);
- Printf("Boot info at 0x%08lx\n", start_mem+kernel_size);
- } else {
- Printf("\nKernel text at 0x%08lx, code size 0x%08lx\n", start_mem,
- kexec.a_text);
- Printf("Kernel data at 0x%08lx, data size 0x%08lx\n",
- start_mem+kexec.a_text, kexec.a_data);
- Printf("Kernel bss at 0x%08lx, bss size 0x%08lx\n",
- start_mem+kexec.a_text+kexec.a_data, kexec.a_bss);
- Printf("Boot info at 0x%08lx\n", start_mem+kernel_size);
- }
- Printf("\nKernel entry is 0x%08lx\n", elf_kernel ? kexec_elf.e_entry :
- kexec.a_entry);
-
- Printf("ramdisk dest is 0x%08lx\n", bi.ramdisk.addr);
- Printf("ramdisk lower limit is 0x%08lx\n",
- (u_long)memptr+kernel_size+bi_size);
- Printf("ramdisk src top is 0x%08lx\n",
- (u_long)memptr+kernel_size+bi_size+rd_size);
-
- Puts("\nType a key to continue the Linux/m68k boot...");
- GetChar();
- PutChar('\n');
- }
-
- /* wait for things to settle down */
- Sleep(1000000);
-
- if (!keep_video)
- /* set graphics mode to a nice normal one */
- LoadView(NULL);
-
- Disable();
-
- /* reset nasty Zorro boards */
- if (reset_boards)
- for (i = 0; i < bi.num_autocon; i++)
- if (boardresetfuncs[i])
- boardresetfuncs[i](&bi.autocon[i]);
-
- /* Turn off all DMA */
- custom.dmacon = DMAF_ALL | DMAF_MASTER;
-
- /* turn off caches */
- CacheControl(0, ~0);
-
- /* Go into supervisor state */
- SuperState();
-
- /* turn off any mmu translation */
- disable_mmu();
-
- /* execute the copy-and-go code (from CHIP RAM) */
- start_kernel(startfunc, (char *)stack+TEMP_STACKSIZE, memptr, start_mem,
- kernel_size, bi.ramdisk.addr, rd_size);
-
- /* Clean up and exit in case of a failure */
-Fail:
- if (kfd != -1)
- KClose(kfd);
- if (rfd != -1)
- Close(rfd);
- if (memptr)
- FreeMem((void *)memptr, memreq);
- if (stack)
- FreeMem((void *)stack, TEMP_STACKSIZE);
- if (kernel_phdrs)
- FreeMem((void *)kernel_phdrs, kexec_elf.e_phnum*sizeof(Elf32_Phdr));
- return(FALSE);
-}
-
-
- /*
- * Determine the Chipset
- */
-
-static u_long get_chipset(void)
-{
- u_char cs;
- u_long chipset;
-
- if (GfxBase->Version >= 39)
- cs = SetChipRev(SETCHIPREV_BEST);
- else
- cs = GfxBase->ChipRevBits0;
- if ((cs & GFXG_AGA) == GFXG_AGA)
- chipset = CS_AGA;
- else if ((cs & GFXG_ECS) == GFXG_ECS)
- chipset = CS_ECS;
- else if ((cs & GFXG_OCS) == GFXG_OCS)
- chipset = CS_OCS;
- else
- chipset = CS_STONEAGE;
- return(chipset);
-}
-
-
- /*
- * Determine the CPU Type
- */
-
-static void get_processor(u_long *cpu, u_long *fpu, u_long *mmu)
-{
- *cpu = *fpu = 0;
-
- if (SysBase->AttnFlags & AFF_68060)
- *cpu = CPU_68060;
- else if (SysBase->AttnFlags & AFF_68040)
- *cpu = CPU_68040;
- else if (SysBase->AttnFlags & AFF_68030)
- *cpu = CPU_68030;
- else if (SysBase->AttnFlags & AFF_68020)
- *cpu = CPU_68020;
-
- if (*cpu == CPU_68040 || *cpu == CPU_68060) {
- if (SysBase->AttnFlags & AFF_FPU40)
- *fpu = *cpu;
- } else if (SysBase->AttnFlags & AFF_68882)
- *fpu = FPU_68882;
- else if (SysBase->AttnFlags & AFF_68881)
- *fpu = FPU_68881;
-
- *mmu = *cpu;
-}
-
- /*
- * Determine the Amiga Model
- */
-
-static u_long get_model(u_long chipset)
-{
- u_long model = AMI_UNKNOWN;
-
- if (debugflag)
- Puts("Amiga model identification:\n");
- if (probe_resource("draco.resource"))
- model = AMI_DRACO;
- else {
- if (debugflag)
- Puts(" Chipset: ");
- switch (chipset) {
- case CS_STONEAGE:
- if (debugflag)
- Puts("Old or unknown\n");
- goto OCS;
- break;
-
- case CS_OCS:
- if (debugflag)
- Puts("OCS\n");
-OCS: if (probe_resident("cd.device"))
- model = AMI_CDTV;
- else
- /* let's call it an A2000 (may be A500, A1000, A2500) */
- model = AMI_2000;
- break;
-
- case CS_ECS:
- if (debugflag)
- Puts("ECS\n");
- if (probe_resident("Magic 36.7") ||
- probe_resident("kickad 36.57") ||
- probe_resident("A3000 Bonus") ||
- probe_resident("A3000 bonus"))
- /* let's call it an A3000 (may be A3000T) */
- model = AMI_3000;
- else if (probe_resource("card.resource"))
- model = AMI_600;
- else
- /* let's call it an A2000 (may be A500[+], A1000, A2500) */
- model = AMI_2000;
- break;
-
- case CS_AGA:
- if (debugflag)
- Puts("AGA\n");
- if (probe_resident("A1000 Bonus") ||
- probe_resident("A4000 bonus"))
- model = probe_resident("NCR scsi.device") ? AMI_4000T :
- AMI_4000;
- else if (probe_resource("card.resource"))
- model = AMI_1200;
- else if (probe_resident("cd.device"))
- model = AMI_CD32;
- else
- model = AMI_3000PLUS;
- break;
- }
- }
- if (debugflag) {
- Puts("\nType a key to continue...");
- GetChar();
- Puts("\n\n");
- }
- return(model);
-}
-
-
- /*
- * Probe for a Resident Modules
- */
-
-static int probe_resident(const char *name)
-{
- const struct Resident *res;
-
- if (debugflag)
- Printf(" Module `%s': ", name);
- res = FindResident(name);
- if (debugflag)
- if (res)
- Printf("0x%08lx\n", res);
- else
- Puts("not present\n");
- return(res ? TRUE : FALSE);
-}
-
-
- /*
- * Probe for an available Resource
- */
-
-static int probe_resource(const char *name)
-{
- const void *res;
-
- if (debugflag)
- Printf(" Resource `%s': ", name);
- res = OpenResource(name);
- if (debugflag)
- if (res)
- Printf("0x%08lx\n", res);
- else
- Puts("not present\n");
- return(res ? TRUE : FALSE);
-}
-
-
- /*
- * Create the Bootinfo structure
- */
-
-static int create_bootinfo(void)
-{
- int i;
- struct bi_record *record;
-
- /* Initialization */
- bi_size = 0;
-
- /* Generic tags */
- if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
- return(0);
- if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
- return(0);
- if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
- return(0);
- if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
- return(0);
- for (i = 0; i < bi.num_memory; i++)
- if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
- return(0);
- if (bi.ramdisk.size)
- if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
- return(0);
- if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
- return(0);
-
- /* Amiga tags */
- if (!add_bi_record(BI_AMIGA_MODEL, sizeof(bi.model), &bi.model))
- return(0);
- for (i = 0; i < bi.num_autocon; i++)
- if (!add_bi_record(BI_AMIGA_AUTOCON, sizeof(bi.autocon[i]),
- &bi.autocon[i]))
- return(0);
- if (!add_bi_record(BI_AMIGA_CHIP_SIZE, sizeof(bi.chip_size), &bi.chip_size))
- return(0);
- if (!add_bi_record(BI_AMIGA_VBLANK, sizeof(bi.vblank), &bi.vblank))
- return(0);
- if (!add_bi_record(BI_AMIGA_PSFREQ, sizeof(bi.psfreq), &bi.psfreq))
- return(0);
- if (!add_bi_record(BI_AMIGA_ECLOCK, sizeof(bi.eclock), &bi.eclock))
- return(0);
- if (!add_bi_record(BI_AMIGA_CHIPSET, sizeof(bi.chipset), &bi.chipset))
- return(0);
- if (!add_bi_record(BI_AMIGA_SERPER, sizeof(bi.serper), &bi.serper))
- return(0);
-
- /* Trailer */
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = BI_LAST;
- bi_size += sizeof(bi_union.record.tag);
-
- return(1);
-}
-
-
- /*
- * Add a Record to the Bootinfo Structure
- */
-
-static int add_bi_record(u_short tag, u_short size, const void *data)
-{
- struct bi_record *record;
- u_int size2;
-
- size2 = (sizeof(struct bi_record)+size+3)&-4;
- if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
- Puts("Can't add bootinfo record. Ask a wizard to enlarge me.\n");
- return(0);
- }
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = tag;
- record->size = size2;
- memcpy(record->data, data, size);
- bi_size += size2;
- return(1);
-}
-
-
- /*
- * Add a String Record to the Bootinfo Structure
- */
-
-static int add_bi_string(u_short tag, const u_char *s)
-{
- return(add_bi_record(tag, strlen(s)+1, (void *)s));
-}
-
-
-#ifdef BOOTINFO_COMPAT_1_0
-
- /*
- * Create the Bootinfo structure for backwards compatibility mode
- */
-
-static int create_compat_bootinfo(void)
-{
- u_int i;
-
- compat_bootinfo.machtype = bi.machtype;
- if (bi.cputype & CPU_68020)
- compat_bootinfo.cputype = COMPAT_CPU_68020;
- else if (bi.cputype & CPU_68030)
- compat_bootinfo.cputype = COMPAT_CPU_68030;
- else if (bi.cputype & CPU_68040)
- compat_bootinfo.cputype = COMPAT_CPU_68040;
- else if (bi.cputype & CPU_68060)
- compat_bootinfo.cputype = COMPAT_CPU_68060;
- else {
- Printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
- return(0);
- }
- if (bi.fputype & FPU_68881)
- compat_bootinfo.cputype |= COMPAT_FPU_68881;
- else if (bi.fputype & FPU_68882)
- compat_bootinfo.cputype |= COMPAT_FPU_68882;
- else if (bi.fputype & FPU_68040)
- compat_bootinfo.cputype |= COMPAT_FPU_68040;
- else if (bi.fputype & FPU_68060)
- compat_bootinfo.cputype |= COMPAT_FPU_68060;
- else if (bi.fputype) {
- Printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
- return(0);
- }
- compat_bootinfo.num_memory = bi.num_memory;
- if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
- Printf("Warning: using only %ld blocks of memory\n",
- COMPAT_NUM_MEMINFO);
- compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
- }
- for (i = 0; i < compat_bootinfo.num_memory; i++) {
- compat_bootinfo.memory[i].addr = bi.memory[i].addr;
- compat_bootinfo.memory[i].size = bi.memory[i].size;
- }
- if (bi.ramdisk.size) {
- bi.ramdisk.addr &= 0xfffffc00;
- compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
- compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
- } else {
- compat_bootinfo.ramdisk_size = 0;
- compat_bootinfo.ramdisk_addr = 0;
- }
- strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
- compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
-
- compat_bootinfo.bi_amiga.model = bi.model;
- compat_bootinfo.bi_amiga.num_autocon = bi.num_autocon;
- if (compat_bootinfo.bi_amiga.num_autocon > COMPAT_NUM_AUTO) {
- Printf("Warning: using only %ld AutoConfig devices\n",
- COMPAT_NUM_AUTO);
- compat_bootinfo.bi_amiga.num_autocon = COMPAT_NUM_AUTO;
- }
- for (i = 0; i < compat_bootinfo.bi_amiga.num_autocon; i++)
- compat_bootinfo.bi_amiga.autocon[i] = bi.autocon[i];
- compat_bootinfo.bi_amiga.chip_size = bi.chip_size;
- compat_bootinfo.bi_amiga.vblank = bi.vblank;
- compat_bootinfo.bi_amiga.psfreq = bi.psfreq;
- compat_bootinfo.bi_amiga.eclock = bi.eclock;
- compat_bootinfo.bi_amiga.chipset = bi.chipset;
- compat_bootinfo.bi_amiga.hw_present = 0;
- return(1);
-}
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-
- /*
- * Compare the Bootstrap and Kernel Versions
- */
-
-static int check_bootinfo_version(const char *memptr)
-{
- const struct bootversion *bv = (struct bootversion *)memptr;
- unsigned long version = 0;
- int i, kernel_major, kernel_minor, boots_major, boots_minor;
-
- if (bv->magic == BOOTINFOV_MAGIC)
- for (i = 0; bv->machversions[i].machtype != 0; ++i)
- if (bv->machversions[i].machtype == MACH_AMIGA) {
- version = bv->machversions[i].version;
- break;
- }
- if (!version)
- Puts("Kernel has no bootinfo version info, assuming 0.0\n");
-
- kernel_major = BI_VERSION_MAJOR(version);
- kernel_minor = BI_VERSION_MINOR(version);
- boots_major = BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION);
- boots_minor = BI_VERSION_MINOR(AMIGA_BOOTI_VERSION);
- Printf("Bootstrap's bootinfo version: %ld.%ld\n", boots_major,
- boots_minor);
- Printf("Kernel's bootinfo version : %ld.%ld\n", kernel_major,
- kernel_minor);
-
- switch (kernel_major) {
- case BI_VERSION_MAJOR(AMIGA_BOOTI_VERSION):
- if (kernel_minor > boots_minor) {
- Puts("Warning: Bootinfo version of bootstrap and kernel "
- "differ!\n");
- Puts(" Certain features may not work.\n");
- }
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_AMIGA_BOOTI_VERSION):
- Puts("(using backwards compatibility mode)\n");
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- Printf("\nThis bootstrap is too %s for this kernel!\n",
- boots_major < kernel_major ? "old" : "new");
- return(0);
- }
- return(kernel_major);
-}
-
-
- /*
- * Call the copy-and-go-code
- */
-
-static void start_kernel(void (*startfunc)(), char *stackp, char *memptr,
- u_long start_mem, u_long kernel_size, u_long rd_dest,
- u_long rd_size)
-{
- register void (*a0)() __asm("a0") = startfunc;
- register char *a2 __asm("a2") = stackp;
- register char *a3 __asm("a3") = memptr;
- register u_long a4 __asm("a4") = start_mem;
- register u_long d0 __asm("d0") = rd_dest;
- register u_long d1 __asm("d1") = rd_size;
- register u_long d2 __asm("d2") = kernel_size;
- register u_long d3 __asm("d3") = bi_size;
-
- __asm __volatile ("movel a2,sp;"
- "jmp a0@"
- : /* no outputs */
- : "r" (a0), "r" (a2), "r" (a3), "r" (a4), "r" (d0),
- "r" (d1), "r" (d2), "r" (d3)
- /* no return */);
- /* fake a noreturn */
- for (;;);
-}
-
-
- /*
- * This assembler code is copied to chip ram, and then executed.
- * It copies the kernel to it's final resting place.
- *
- * It is called with:
- *
- * a3 = memptr
- * a4 = start_mem
- * d0 = rd_dest
- * d1 = rd_size
- * d2 = kernel_size
- * d3 = bi_size
- */
-
-asm(".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(copyall) ":
- | /* copy kernel text and data */
- movel a3,a0 | src = (u_long *)memptr;
- movel a0,a2 | limit = (u_long *)(memptr+kernel_size);
- addl d2,a2
- movel a4,a1 | dest = (u_long *)start_mem;
-1: cmpl a0,a2
- jeq 2f | while (src < limit)
- moveb a0@+,a1@+ | *dest++ = *src++;
- jra 1b
-2:
- | /* copy bootinfo to end of bss */
- movel a3,a0 | src = (u_long *)(memptr+kernel_size);
- addl d2,a0 | dest = end of bss (already in a1)
- movel d3,d7 | count = bi_size
- subql #1,d7
-1: moveb a0@+,a1@+ | while (--count > -1)
- dbra d7,1b | *dest++ = *src++
-
- | /* copy the ramdisk to the top of memory */
- movel a3,a0 | src = (u_long *)(memptr+kernel_size+bi_size);
- addl d2,a0
- addl d3,a0
- movel d0,a1 | dest = (u_long *)rd_dest;
- movel a0,a2 | limit = (u_long *)(memptr+kernel_size+
- addl d1,a2 | bi_size+rd_size);
-1: cmpl a0,a2
- jeq 2f | while (src > limit)
- moveb a0@+,a1@+ | *dest++ = *src++;
- jra 1b
-2:
- | /* jump to start of kernel */
- movel a4,a0 | jump_to (start_mem);
- jmp a0@
-"
-SYMBOL_NAME_STR(copyallend) ":
-");
-
-
- /*
- * Test for a MapROMmed A3640 Board
- */
-
-asm(".text\n"
-ALIGN_STR "\n"
-SYMBOL_NAME_STR(maprommed) ":
- oriw #0x0700,sr
- moveml #0x3f20,sp@-
- | /* Save cache settings */
- .long 0x4e7a1002 | movec cacr,d1 */
- | /* Save MMU settings */
- .long 0x4e7a2003 | movec tc,d2
- .long 0x4e7a3004 | movec itt0,d3
- .long 0x4e7a4005 | movec itt1,d4
- .long 0x4e7a5006 | movec dtt0,d5
- .long 0x4e7a6007 | movec dtt1,d6
- moveq #0,d0
- movel d0,a2
- | /* Disable caches */
- .long 0x4e7b0002 | movec d0,cacr
- | /* Disable MMU */
- .long 0x4e7b0003 | movec d0,tc
- .long 0x4e7b0004 | movec d0,itt0
- .long 0x4e7b0005 | movec d0,itt1
- .long 0x4e7b0006 | movec d0,dtt0
- .long 0x4e7b0007 | movec d0,dtt1
- lea 0x07f80000,a0
- lea 0x00f80000,a1
- movel a0@,d7
- cmpl a1@,d7
- jne 1f
- movel d7,d0
- notl d0
- movel d0,a0@
- nop | /* Thanks to Jörg Mayer! */
- cmpl a1@,d0
- jne 1f
- moveq #-1,d0 | /* MapROMmed A3640 present */
- movel d0,a2
-1: movel d7,a0@
- | /* Restore MMU settings */
- .long 0x4e7b2003 | movec d2,tc
- .long 0x4e7b3004 | movec d3,itt0
- .long 0x4e7b4005 | movec d4,itt1
- .long 0x4e7b5006 | movec d5,dtt0
- .long 0x4e7b6007 | movec d6,dtt1
- | /* Restore cache settings */
- .long 0x4e7b1002 | movec d1,cacr
- movel a2,d0
- moveml sp@+,#0x04fc
- rte
-");
-
-
- /*
- * Reset functions for nasty Zorro boards
- */
-
-static void reset_rb3(const struct ConfigDev *cd)
-{
- volatile u_char *rb3_reg = (u_char *)(cd->cd_BoardAddr+0x01002000);
-
- /* FN: If a Rainbow III board is present, reset it to disable */
- /* its (possibly activated) vertical blank interrupts as the */
- /* kernel is not yet prepared to handle them (level 6). */
-
- /* set RESET bit in special function register */
- *rb3_reg = 0x01;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit */
- *rb3_reg = 0x00;
-}
-
-static void reset_piccolo(const struct ConfigDev *cd)
-{
- volatile u_char *piccolo_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
-
- /* FN: the same stuff as above, for the Piccolo board. */
- /* this also has the side effect of resetting the board's */
- /* output selection logic to use the Amiga's display in single */
- /* monitor systems - which is currently what we want. */
-
- /* set RESET bit in special function register */
- *piccolo_reg = 0x01;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit */
- *piccolo_reg = 0x51;
-}
-
-static void reset_sd64(const struct ConfigDev *cd)
-{
- volatile u_char *sd64_reg = (u_char *)(cd->cd_BoardAddr+0x8000);
-
- /* FN: the same stuff as above, for the SD64 board. */
- /* just as on the Piccolo, this also resets the monitor switch */
-
- /* set RESET bit in special function register */
- *sd64_reg = 0x1f;
- /* actually, only a few cycles delay are required... */
- Sleep(1000000);
- /* clear reset bit AND switch monitor bit (0x20) */
- *sd64_reg = 0x4f;
-}
-
-static void reset_ariadne(const struct ConfigDev *cd)
-{
- volatile u_short *lance_rdp = (u_short *)(cd->cd_BoardAddr+0x0370);
- volatile u_short *lance_rap = (u_short *)(cd->cd_BoardAddr+0x0372);
- volatile u_short *lance_reset = (u_short *)(cd->cd_BoardAddr+0x0374);
-
- volatile u_char *pit_paddr = (u_char *)(cd->cd_BoardAddr+0x1004);
- volatile u_char *pit_pbddr = (u_char *)(cd->cd_BoardAddr+0x1006);
- volatile u_char *pit_pacr = (u_char *)(cd->cd_BoardAddr+0x100b);
- volatile u_char *pit_pbcr = (u_char *)(cd->cd_BoardAddr+0x100e);
- volatile u_char *pit_psr = (u_char *)(cd->cd_BoardAddr+0x101a);
-
- u_short in;
-
- Disable();
-
- /*
- * Reset the Ethernet part (Am79C960 PCnet-ISA)
- */
-
- in = *lance_reset; /* Reset Chip on Read Access */
- *lance_rap = 0x0000; /* PCnet-ISA Controller Status (CSR0) */
- *lance_rdp = 0x0400; /* STOP */
-
- /*
- * Reset the Parallel part (MC68230 PI/T)
- */
-
- *pit_pacr &= 0xfd; /* Port A Control Register */
- *pit_pbcr &= 0xfd; /* Port B Control Register */
- *pit_psr = 0x05; /* Port Status Register */
- *pit_paddr = 0x00; /* Port A Data Direction Register */
- *pit_pbddr = 0x00; /* Port B Data Direction Register */
-
- Enable();
-}
-
-static void reset_hydra(const struct ConfigDev *cd)
-{
- volatile u_char *nic_cr = (u_char *)(cd->cd_BoardAddr+0xffe1);
- volatile u_char *nic_isr = (u_char *)(cd->cd_BoardAddr+0xffe1 + 14);
- int n = 5000;
-
- Disable();
-
- *nic_cr = 0x21; /* nic command register: software reset etc. */
- while (((*nic_isr & 0x80) == 0) && --n) /* wait for reset to complete */
- ;
-
- Enable();
-}
-
-#if 0
-static void reset_a2060(const struct ConfigDev *cd)
-{
-#error reset_a2060: not yet implemented
-}
-#endif
-
-
-#ifdef ZKERNEL
-
-#define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
-#define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
-#define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
-#define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
-
-/* variables for storing the uncompressed data */
-static char *ZFile[ZFILE_N_CHUNKS];
-static int ZFileSize = 0;
-static int ZFpos = 0;
-static int Zwpos = 0;
-
-static int Zinfd = 0; /* fd of compressed file */
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define INBUFSIZ 4096
-#define WSIZE 0x8000 /* window size--must be a power of two, and */
- /* at least 32K for zip's deflate method */
-
-static uch *inbuf;
-static uch *window;
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-static int exit_code = 0;
-static long bytes_out = 0;
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions (stubbed out) */
-#define Assert(cond,msg)
-#define Trace(x)
-#define Tracev(x)
-#define Tracevv(x)
-#define Tracec(c,x)
-#define Tracecv(c,x)
-
-#define STATIC static
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
-#define malloc(x) AllocVec(x, MEMF_FAST | MEMF_PUBLIC)
-#define free(x) FreeVec(x)
-
-#ifdef LILO
-#include "inflate.c"
-#else
-#include "../../../../lib/inflate.c"
-#endif
-
-static void gzip_mark(void **ptr)
-{
-}
-
-static void gzip_release(void **ptr)
-{
-}
-
-
-/*
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf(void)
-{
- if (exit_code)
- return -1;
-
- insize = Read(Zinfd, inbuf, INBUFSIZ);
- if (insize <= 0)
- return -1;
-
- inptr = 1;
- return(inbuf[0]);
-}
-
-/*
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window(void)
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, ch;
- int chunk = Zwpos >> ZFILE_CHUNK_BITS;
-
- if (exit_code)
- return;
-
- if (chunk >= ZFILE_N_CHUNKS) {
- error("Compressed image too large! Aborting.\n");
- return;
- }
- if (!ZFile[chunk]) {
- if (!(ZFile[chunk] = (char *)AllocMem(ZFILE_CHUNK_SIZE,
- MEMF_FAST | MEMF_PUBLIC))) {
- error("Out of memory for decompresing kernel image\n");
- return;
- }
- }
- memcpy(ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt);
- Zwpos += outcnt;
-
-#define DISPLAY_BITS 10
- if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0)
- PutChar('.');
-
- in = window;
- for (n = 0; n < outcnt; n++) {
- ch = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error(char *x)
-{
- Printf("\n%s", x);
- exit_code = 1;
-}
-
-static inline int call_sub(int (*func)(void), void *stackp)
-{
- register int _res __asm("d0");
- register int (*a0)(void) __asm("a0") = func;
- register int (*a1)(void) __asm("a1") = stackp;
-
- __asm __volatile ("movel sp,a2;"
- "movel a1,sp;"
- "jsr a0@;"
- "movel a2,sp"
- : "=r" (_res)
- : "r" (a0), "r" (a1)
- : "a0", "a1", "a2", "d0", "d1", "memory");
- return(_res);
-}
-
-static int load_zkernel(int fd)
-{
- int i, err = -1;
-#define ZSTACKSIZE (16384)
- u_long *zstack;
-
- for (i = 0; i < ZFILE_N_CHUNKS; ++i)
- ZFile[i] = NULL;
- Zinfd = fd;
- Seek(fd, 0);
-
- if (!(inbuf = (uch *)AllocMem(INBUFSIZ, MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip buffer\n");
- else {
- if (!(window = (uch *)AllocMem(WSIZE, MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip window\n");
- else {
- if (!(zstack = (u_long *)AllocMem(ZSTACKSIZE,
- MEMF_FAST | MEMF_PUBLIC)))
- Puts("Couldn't allocate gunzip stack\n");
- else {
- Puts("Uncompressing kernel image ");
- makecrc();
- if (!(err = call_sub(gunzip, (char *)zstack+ZSTACKSIZE)))
- Puts("done\n");
- ZFileSize = Zwpos;
- FreeMem(zstack, ZSTACKSIZE);
- }
- FreeMem(window, WSIZE);
- window = NULL;
- }
- FreeMem(inbuf, INBUFSIZ);
- inbuf = NULL;
- }
- Close(Zinfd); /* input file not needed anymore */
- return(err);
-}
-
-
-/* Note about the read/lseek wrapper and its memory management: It assumes
- * that all seeks are only forward, and thus data already read or skipped can
- * be freed. This is true for current organization of bootstrap and kernels.
- * Little exception: The struct kexec at the start of the file. After reading
- * it, there may be a seek back to the end of the file. But this currently
- * doesn't hurt. (Roman)
- */
-
-static int KRead(int fd, void *buf, int cnt)
-{
- unsigned done = 0;
-
- if (!ZFileSize)
- return(Read(fd, buf, cnt));
-
- if (ZFpos + cnt > ZFileSize)
- cnt = ZFileSize - ZFpos;
-
- while (cnt > 0) {
- unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
- unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
- unsigned n = cnt;
-
- if (ZFpos + n > endchunk)
- n = endchunk - ZFpos;
- memcpy(buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n);
- cnt -= n;
- buf += n;
- done += n;
- ZFpos += n;
-
- if (ZFpos == endchunk) {
- FreeMem(ZFile[chunk], ZFILE_CHUNK_SIZE);
- ZFile[chunk] = NULL;
- }
- }
-
- return(done);
-}
-
-
-static int KSeek(int fd, int offset)
-{
- unsigned oldpos, oldchunk, newchunk;
-
- if (!ZFileSize)
- return(Seek(fd, offset));
-
- oldpos = ZFpos;
- ZFpos = offset;
- if (ZFpos < 0) {
- ZFpos = 0;
- return(-1);
- } else if (ZFpos > ZFileSize) {
- ZFpos = ZFileSize;
- return(-1);
- }
-
- /* free memory of skipped-over data */
- oldchunk = oldpos >> ZFILE_CHUNK_BITS;
- newchunk = ZFpos >> ZFILE_CHUNK_BITS;
- while(oldchunk < newchunk) {
- if (ZFile[oldchunk]) {
- FreeMem(ZFile[oldchunk], ZFILE_CHUNK_SIZE);
- ZFile[oldchunk] = NULL;
- }
- ++oldchunk;
- }
- return(ZFpos);
-}
-
-
-static void free_zfile(void)
-{
- int i;
-
- for (i = 0; i < ZFILE_N_CHUNKS; ++i)
- if (ZFile[i]) {
- FreeMem(ZFile[i], ZFILE_CHUNK_SIZE);
- ZFile[i] = NULL;
- }
-}
-
-static int KClose(int fd)
-{
- if (ZFileSize) {
- free_zfile();
- ZFileSize = 0;
- } else
- Close(fd);
- return(0);
-}
-#endif /* ZKERNEL */
diff --git a/arch/m68k/boot/amiga/linuxboot.h b/arch/m68k/boot/amiga/linuxboot.h
index e04425a3a..e69de29bb 100644
--- a/arch/m68k/boot/amiga/linuxboot.h
+++ b/arch/m68k/boot/amiga/linuxboot.h
@@ -1,455 +0,0 @@
-/*
- * linux/arch/m68k/boot/amiga/linuxboot.h -- Generic routine to boot Linux/m68k
- * on Amiga, used by both Amiboot and
- * Amiga-Lilo.
- *
- * Created 1996 by Geert Uytterhoeven
- *
- *
- * This file is based on the original bootstrap code (bootstrap.c):
- *
- * Copyright (C) 1993, 1994 Hamish Macdonald
- * Greg Harp
- *
- * with work by Michael Rausch
- * Geert Uytterhoeven
- * Frank Neumann
- * Andreas Schwab
- *
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-
-#include <asm/setup.h>
-#include <linux/zorro.h>
-
-
- /*
- * Amiboot Version
- */
-
-#define AMIBOOT_VERSION "5.5"
-
-
- /*
- * Amiga Bootinfo Definitions
- *
- * All limits herein are `soft' limits, i.e. they don't put constraints
- * on the actual parameters in the kernel.
- */
-
-struct amiga_bootinfo {
- u_long machtype; /* machine type = MACH_AMIGA */
- u_long cputype; /* system CPU */
- u_long fputype; /* system FPU */
- u_long mmutype; /* system MMU */
- int num_memory; /* # of memory blocks found */
- struct mem_info memory[NUM_MEMINFO];/* memory description */
- struct mem_info ramdisk; /* ramdisk description */
- char command_line[CL_SIZE]; /* kernel command line parameters */
- u_long model; /* Amiga Model */
- int num_autocon; /* # of autoconfig devices found */
- struct ConfigDev autocon[ZORRO_NUM_AUTO]; /* autoconfig devices */
- u_long chip_size; /* size of chip memory (bytes) */
- u_char vblank; /* VBLANK frequency */
- u_char psfreq; /* power supply frequency */
- u_long eclock; /* EClock frequency */
- u_long chipset; /* native chipset present */
- u_short serper; /* serial port period */
-};
-
-
- /*
- * Parameters passed to linuxboot()
- */
-
-struct linuxboot_args {
- struct amiga_bootinfo bi; /* Initial values override detected values */
- const char *kernelname;
- const char *ramdiskname;
- int debugflag;
- int keep_video;
- int reset_boards;
- u_int baud;
- void (*puts)(const char *str);
- long (*getchar)(void);
- void (*putchar)(char c);
- void (*printf)(const char *fmt, ...);
- int (*open)(const char *path);
- int (*seek)(int fd, int offset);
- int (*read)(int fd, char *buf, int count);
- void (*close)(int fd);
- int (*filesize)(const char *path);
- void (*sleep)(u_long micros);
-};
-
-
- /*
- * Boot the Linux/m68k Operating System
- */
-
-extern u_long linuxboot(const struct linuxboot_args *args);
-
-
- /*
- * Amiga Models
- */
-
-extern const char *amiga_models[];
-extern const u_long first_amiga_model;
-extern const u_long last_amiga_model;
-
-
- /*
- * Exec Library Definitions
- */
-
-#define TRUE (1)
-#define FALSE (0)
-
-
-struct List {
- struct Node *lh_Head;
- struct Node *lh_Tail;
- struct Node *lh_TailPred;
- u_char lh_Type;
- u_char l_pad;
-};
-
-struct MemChunk {
- struct MemChunk *mc_Next; /* pointer to next chunk */
- u_long mc_Bytes; /* chunk byte size */
-};
-
-#define MEMF_PUBLIC (1<<0)
-#define MEMF_CHIP (1<<1)
-#define MEMF_FAST (1<<2)
-#define MEMF_LOCAL (1<<8)
-#define MEMF_CLEAR (1<<16)
-
-struct MemHeader {
- struct Node mh_Node;
- u_short mh_Attributes; /* characteristics of this region */
- struct MemChunk *mh_First; /* first free region */
- void *mh_Lower; /* lower memory bound */
- void *mh_Upper; /* upper memory bound+1 */
- u_long mh_Free; /* total number of free bytes */
-};
-
-struct ExecBase {
- u_char fill1[20];
- u_short Version;
- u_char fill2[274];
- u_short AttnFlags;
- u_char fill3[24];
- struct List MemList;
- u_char fill4[194];
- u_char VBlankFrequency;
- u_char PowerSupplyFrequency;
- u_char fill5[36];
- u_long ex_EClockFrequency;
- u_char fill6[60];
-};
-
-#define AFB_68020 (1)
-#define AFF_68020 (1<<AFB_68020)
-#define AFB_68030 (2)
-#define AFF_68030 (1<<AFB_68030)
-#define AFB_68040 (3)
-#define AFF_68040 (1<<AFB_68040)
-#define AFB_68881 (4)
-#define AFF_68881 (1<<AFB_68881)
-#define AFB_68882 (5)
-#define AFF_68882 (1<<AFB_68882)
-#define AFB_FPU40 (6) /* ONLY valid if AFB_68040 or AFB_68060 */
-#define AFF_FPU40 (1<<AFB_FPU40) /* is set; also set for 68060 FPU */
-#define AFB_68060 (7)
-#define AFF_68060 (1<<AFB_68060)
-
-struct Resident;
-
-
- /*
- * Graphics Library Definitions
- */
-
-struct GfxBase {
- u_char fill1[20];
- u_short Version;
- u_char fill2[194];
- u_short NormalDisplayRows;
- u_short NormalDisplayColumns;
- u_char fill3[16];
- u_char ChipRevBits0;
- u_char fill4[307];
-};
-
-#define GFXB_HR_AGNUS (0)
-#define GFXF_HR_AGNUS (1<<GFXB_HR_AGNUS)
-#define GFXB_HR_DENISE (1)
-#define GFXF_HR_DENISE (1<<GFXB_HR_DENISE)
-#define GFXB_AA_ALICE (2)
-#define GFXF_AA_ALICE (1<<GFXB_AA_ALICE)
-#define GFXB_AA_LISA (3)
-#define GFXF_AA_LISA (1<<GFXB_AA_LISA)
-
- /*
- * HiRes(=Big) Agnus present; i.e.
- * 1MB chipmem, big blits (none of interest so far) and programmable sync
- */
-#define GFXG_OCS (GFXF_HR_AGNUS)
- /*
- * HiRes Agnus/Denise present; we are running on ECS
- */
-#define GFXG_ECS (GFXF_HR_AGNUS|GFXF_HR_DENISE)
- /*
- * Alice and Lisa present; we are running on AGA
- */
-#define GFXG_AGA (GFXF_AA_ALICE|GFXF_AA_LISA)
-
-#define SETCHIPREV_BEST (0xffffffff)
-#define HIRES (0x8000)
-
-struct View;
-
-
- /*
- * Amiga Shared Library/Device Functions
- */
-
-extern const struct ExecBase *SysBase;
-
-#define LVOAllocMem (-0xc6)
-#define LVOAllocVec (-0x2ac)
-#define LVOCacheControl (-0x288)
-#define LVODisable (-0x78)
-#define LVOEnable (-0x7e)
-#define LVOFindResident (-0x60)
-#define LVOFreeMem (-0xd2)
-#define LVOFreeVec (-0x2b2)
-#define LVOOpenresource (-0x1f2)
-#define LVOSuperState (-0x96)
-#define LVOSupervisor (-0x1e)
-
-static __inline void *AllocMem(u_long byteSize, u_long requirements)
-{
- register void *_res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register u_long d0 __asm("d0") = byteSize;
- register u_long d1 __asm("d1") = requirements;
-
- __asm __volatile ("jsr a6@(-0xc6)"
- : "=r" (_res)
- : "r" (_base), "r" (d0), "r" (d1)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-static __inline void *AllocVec(u_long byteSize, u_long requirements)
-{
- register void *_res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register u_long d0 __asm("d0") = byteSize;
- register u_long d1 __asm("d1") = requirements;
-
- __asm __volatile ("jsr a6@(-0x2ac)"
- : "=r" (_res)
- : "r" (_base), "r" (d0), "r" (d1)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-static __inline u_long CacheControl(u_long cacheBits, u_long cacheMask)
-{
- register u_long _res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register u_long d0 __asm("d0") = cacheBits;
- register u_long d1 __asm("d1") = cacheMask;
-
- __asm __volatile ("jsr a6@(-0x288)"
- : "=r" (_res)
- : "r" (_base), "r" (d0), "r" (d1)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-static __inline void Disable(void)
-{
- register const struct ExecBase *_base __asm("a6") = SysBase;
-
- __asm __volatile ("jsr a6@(-0x78)"
- : /* no output */
- : "r" (_base)
- : "a0", "a1", "d0", "d1", "memory");
-}
-
-static __inline void Enable(void)
-{
- register const struct ExecBase *_base __asm("a6") = SysBase;
-
- __asm __volatile ("jsr a6@(-0x7e)"
- : /* no output */
- : "r" (_base)
- : "a0", "a1", "d0", "d1", "memory");
-}
-
-static __inline struct Resident *FindResident(const u_char *name)
-{
- register struct Resident *_res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register const u_char *a1 __asm("a1") = name;
-
- __asm __volatile ("jsr a6@(-0x60)"
- : "=r" (_res)
- : "r" (_base), "r" (a1)
- : "a0", "a1", "d0", "d1", "memory");
- return _res;
-}
-
-static __inline void FreeMem(void *memoryBlock, u_long byteSize)
-{
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register void *a1 __asm("a1") = memoryBlock;
- register u_long d0 __asm("d0") = byteSize;
-
- __asm __volatile ("jsr a6@(-0xd2)"
- : /* no output */
- : "r" (_base), "r" (a1), "r" (d0)
- : "a0", "a1", "d0", "d1", "memory");
-}
-
-static __inline void FreeVec(void *memoryBlock)
-{
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register void *a1 __asm("a1") = memoryBlock;
-
- __asm __volatile ("jsr a6@(-0x2b2)"
- : /* no output */
- : "r" (_base), "r" (a1)
- : "a0", "a1", "d0", "d1", "memory");
-}
-
-static __inline void *OpenResource(const u_char *resName)
-{
- register void *_res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register const u_char *a1 __asm("a1") = resName;
-
- __asm __volatile ("jsr a6@(-0x1f2)"
- : "=r" (_res)
- : "r" (_base), "r" (a1)
- : "a0", "a1", "d0", "d1", "memory");
- return _res;
-}
-
-static __inline void *SuperState(void)
-{
- register void *_res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
-
- __asm __volatile ("jsr a6@(-0x96)"
- : "=r" (_res)
- : "r" (_base)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-static __inline u_long Supervisor(u_long (*userfunc)(void))
-{
- register u_long _res __asm("d0");
- register const struct ExecBase *_base __asm("a6") = SysBase;
- register u_long (*d7)() __asm("d7") = userfunc;
-
- __asm __volatile ("exg d7,a5;"
- "jsr a6@(-0x1e);"
- "exg d7,a5"
- : "=r" (_res)
- : "r" (_base), "r" (d7)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-
-extern const struct ExpansionBase *ExpansionBase;
-
-#define LVOFindConfigDev (-0x48)
-
-static __inline struct ConfigDev *FindConfigDev(struct ConfigDev *oldConfigDev,
- long manufacturer, long product)
-{
- register struct ConfigDev *_res __asm("d0");
- register const struct ExpansionBase *_base __asm("a6") = ExpansionBase;
- register struct ConfigDev *a0 __asm("a0") = oldConfigDev;
- register long d0 __asm("d0") = manufacturer;
- register long d1 __asm("d1") = product;
-
- __asm __volatile ("jsr a6@(-0x48)"
- : "=r" (_res)
- : "r" (_base), "r" (a0), "r" (d0), "r" (d1)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-
-extern const struct GfxBase *GfxBase;
-
-#define LVOLoadView (-0xde)
-#define LVOSetChipRev (-0x378)
-
-static __inline void LoadView(struct View *view)
-{
- register const struct GfxBase *_base __asm("a6") = GfxBase;
- register struct View *a1 __asm("a1") = view;
-
- __asm __volatile ("jsr a6@(-0xde)"
- : /* no output */
- : "r" (_base), "r" (a1)
- : "a0", "a1", "d0", "d1", "memory");
-}
-
-static __inline u_long SetChipRev(u_long want)
-{
- register u_long _res __asm("d0");
- register const struct GfxBase *_base __asm("a6") = GfxBase;
- register u_long d0 __asm("d0") = want;
-
- __asm __volatile ("jsr a6@(-0x378)"
- : "=r" (_res)
- : "r" (_base), "r" (d0)
- : "a0", "a1", "d0", "d1", "memory");
- return(_res);
-}
-
-
- /*
- * Bootstrap Support Functions
- */
-
-static __inline void disable_mmu(void)
-{
- if (SysBase->AttnFlags & AFF_68040)
- __asm __volatile ("moveq #0,d0;"
- ".long 0x4e7b0003;" /* movec d0,tc */
- ".long 0x4e7b0004;" /* movec d0,itt0 */
- ".long 0x4e7b0005;" /* movec d0,itt1 */
- ".long 0x4e7b0006;" /* movec d0,dtt0 */
- ".long 0x4e7b0007" /* movec d0,dtt1 */
- : /* no outputs */
- : /* no inputs */
- : "d0");
- else {
- __asm __volatile ("subl #4,sp;"
- "pmove tc,sp@;"
- "bclr #7,sp@;"
- "pmove sp@,tc;"
- "addl #4,sp");
- if (SysBase->AttnFlags & AFF_68030)
- __asm __volatile ("clrl sp@-;"
- ".long 0xf0170800;" /* pmove sp@,tt0 */
- ".long 0xf0170c00;" /* pmove sp@,tt1 */
- "addql #4,sp");
- }
-}
diff --git a/arch/m68k/boot/atari/bootp.c b/arch/m68k/boot/atari/bootp.c
index affe636b8..e69de29bb 100644
--- a/arch/m68k/boot/atari/bootp.c
+++ b/arch/m68k/boot/atari/bootp.c
@@ -1,814 +0,0 @@
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "bootp.h"
-
-
-/* --------------------------------------------------------------------- */
-/* Protocol Header Structures */
-
-struct etherhdr {
- HWADDR dst_addr;
- HWADDR src_addr;
- unsigned short type;
-};
-
-struct arphdr {
- unsigned short hrd; /* format of hardware address */
- unsigned short pro; /* format of protocol address */
- unsigned char hln; /* length of hardware address */
- unsigned char pln; /* length of protocol address */
- unsigned short op; /* ARP opcode (command) */
- unsigned char addr[0]; /* addresses (var len) */
-};
-
-struct iphdr {
- unsigned char version : 4;
- unsigned char ihl : 4;
- unsigned char tos;
- unsigned short tot_len;
- unsigned short id;
- unsigned short frag_off;
- unsigned char ttl;
- unsigned char protocol;
- unsigned short chksum;
- IPADDR src_addr;
- IPADDR dst_addr;
-};
-
-struct udphdr {
- unsigned short src_port;
- unsigned short dst_port;
- unsigned short len;
- unsigned short chksum;
-};
-
-struct bootp {
- unsigned char op; /* packet opcode type */
- unsigned char htype; /* hardware addr type */
- unsigned char hlen; /* hardware addr length */
- unsigned char hops; /* gateway hops */
- unsigned long xid; /* transaction ID */
- unsigned short secs; /* seconds since boot began */
- unsigned short unused;
- IPADDR ciaddr; /* client IP address */
- IPADDR yiaddr; /* 'your' IP address */
- IPADDR siaddr; /* server IP address */
- IPADDR giaddr; /* gateway IP address */
- unsigned char chaddr[16]; /* client hardware address */
- unsigned char sname[64]; /* server host name */
- unsigned char file[128]; /* boot file name */
- unsigned char vend[64]; /* vendor-specific area */
-};
-
-struct tftp_req {
- unsigned short opcode;
- char name[512];
-};
-
-struct tftp_data {
- unsigned short opcode;
- unsigned short nr;
- unsigned char data[512];
-};
-
-struct tftp_ack {
- unsigned short opcode;
- unsigned short nr;
-};
-
-struct tftp_error {
- unsigned short opcode;
- unsigned short errcode;
- char str[512];
-};
-
-
-typedef struct {
- struct etherhdr ether;
- struct arphdr arp;
-} ARP;
-
-typedef struct {
- struct etherhdr ether;
- struct iphdr ip;
- struct udphdr udp;
-} UDP;
-
-#define UDP_BOOTPS 67
-#define UDP_BOOTPC 68
-#define UDP_TFTP 69
-
-typedef struct {
- struct etherhdr ether;
- struct iphdr ip;
- struct udphdr udp;
- struct bootp bootp;
-} BOOTP;
-
-#define BOOTREQUEST 1
-#define BOOTREPLY 2
-#define BOOTP_RETRYS 5
-
-typedef struct {
- struct etherhdr ether;
- struct iphdr ip;
- struct udphdr udp;
- union tftp {
- unsigned short opcode;
- struct tftp_req req;
- struct tftp_data data;
- struct tftp_ack ack;
- struct tftp_error error;
- } tftp;
-} TFTP;
-
-#define TFTP_RRQ 1
-#define TFTP_WRQ 2
-#define TFTP_DATA 3
-#define TFTP_ACK 4
-#define TFTP_ERROR 5
-
-
-/* --------------------------------------------------------------------- */
-/* Addresses */
-
-static HWADDR MyHwaddr;
-static HWADDR ServerHwaddr;
-static IPADDR MyIPaddr;
-static IPADDR ServerIPaddr;
-
-static IPADDR IP_Unknown_Addr = 0x00000000;
-static IPADDR IP_Broadcast_Addr = 0xffffffff;
-static HWADDR Eth_Broadcast_Addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-
-#define HZ 200
-#define _hz_200 (*(volatile unsigned long *)0x4ba)
-
-
-/* --------------------------------------------------------------------- */
-/* Error Strings */
-
-static char *ErrStr[] = {
- "timeout",
- "general Ethernet transmit error",
- "general Ethernet receive error",
- "Ethernet framing error",
- "Ethernet overflow error",
- "Ethernet CRC error"
-};
-
-
-/* --------------------------------------------------------------------- */
-/* Kfile Emulation Definitions */
-
-#define KFILE_CHUNK_BITS 16 /* chunk is 64 KB */
-#define KFILE_CHUNK_SIZE (1 << KFILE_CHUNK_BITS)
-#define KFILE_CHUNK_MASK (KFILE_CHUNK_SIZE-1)
-#define KFILE_N_CHUNKS (2*1024*1024/KFILE_CHUNK_SIZE)
-
-char *KFile[KFILE_N_CHUNKS];
-int KFileSize = 0;
-int KFpos = 0;
-
-
-
-
-/***************************** Prototypes *****************************/
-
-static void free_kfile( void );
-static int bootp( char *image_name );
-static int tftp( char *image_name );
-static int udp_send( UDP *pkt, int len, int fromport, int toport );
-static unsigned short ip_checksum( struct iphdr *buf );
-static int udp_rcv( UDP *pkt, int *len, int fromport, int atport );
-static void print_ip( IPADDR addr );
-static void print_hw( HWADDR addr );
-static int check_ethif( void );
-static int eth_send( Packet *pkt, int len );
-static int eth_rcv( Packet *pkt, int *len );
-
-/************************* End of Prototypes **************************/
-
-
-
-
-/* --------------------------------------------------------------------- */
-/* Interface to bootstrap.c */
-
-/* get_remote_kernel():
- * Perform all necessary steps to get the kernel image
- * from the boot server. If successfull (retval == 0), subsequent calls to
- * kread() can access the data. Fatal errors (i.e., retrying is useless)
- * return -2, others -1.
- */
-
-int get_remote_kernel( const char *kname /* optional */ )
-
-{ char image_name[256];
- int rv;
-
- /* Check if a Ethernet interface is present and determine the Ethernet
- * address */
- if (check_ethif() < 0) {
- printf( "No Ethernet interface found -- no remote boot possible.\n" );
- return( -2 );
- }
-
- /* Do a BOOTP request to find out our IP address and the kernel image's
- * name; we also learn the IP and Ethernet address of our server */
- if (kname)
- strcpy( image_name, kname );
- else
- *image_name = 0;
- if ((rv = bootp( image_name )) < 0)
- return( rv );
-
- /* Now start a TFTP connection to receive the kernel image */
- if ((rv = tftp( image_name )) < 0)
- return( rv );
-
- return( 0 );
-}
-
-
-/* ll_read(), ll_lseek(), ll_close():
- * Functions for accessing the received kernel image like with read(),
- * lseek(), close().
- */
-
-int ll_read( int fd, void *buf, unsigned cnt )
-
-{ unsigned done = 0;
-
- if (!KFileSize)
- return( read( fd, buf, cnt ) );
-
- if (KFpos + cnt > KFileSize)
- cnt = KFileSize - KFpos;
-
- while( cnt > 0 ) {
- unsigned chunk = KFpos >> KFILE_CHUNK_BITS;
- unsigned endchunk = (chunk+1) << KFILE_CHUNK_BITS;
- unsigned n = cnt;
-
- if (KFpos + n > endchunk)
- n = endchunk - KFpos;
- memcpy( buf, KFile[chunk] + (KFpos & KFILE_CHUNK_MASK), n );
- cnt -= n;
- buf += n;
- done += n;
- KFpos += n;
-
- if (KFpos == endchunk) {
- free( KFile[chunk] );
- KFile[chunk] = NULL;
- }
- }
-
- return( done );
-}
-
-
-int ll_lseek( int fd, int where, int whence )
-
-{
- unsigned oldpos, oldchunk, newchunk;
-
- if (!KFileSize)
- return( lseek( fd, where, whence ) );
-
- oldpos = KFpos;
- switch( whence ) {
- case SEEK_SET:
- KFpos = where;
- break;
- case SEEK_CUR:
- KFpos += where;
- break;
- case SEEK_END:
- KFpos = KFileSize + where;
- break;
- default:
- return( -1 );
- }
- if (KFpos < 0) {
- KFpos = 0;
- return( -1 );
- }
- else if (KFpos > KFileSize) {
- KFpos = KFileSize;
- return( -1 );
- }
-
- /* free memory of skipped-over data */
- oldchunk = oldpos >> KFILE_CHUNK_BITS;
- newchunk = KFpos >> KFILE_CHUNK_BITS;
- while( oldchunk < newchunk ) {
- if (KFile[oldchunk]) {
- free( KFile[oldchunk] );
- KFile[oldchunk] = NULL;
- }
- ++oldchunk;
- }
-
- return( KFpos );
-}
-
-
-int ll_close( int fd )
-
-{
- if (!KFileSize)
- return( close( fd ) );
-
- free_kfile();
- return( 0 );
-}
-
-
-static void free_kfile( void )
-
-{ int i;
-
- for( i = 0; i < KFILE_N_CHUNKS; ++i )
- if (KFile[i]) free( KFile[i] );
-}
-
-
-
-/* --------------------------------------------------------------------- */
-/* BOOTP Procedure */
-
-
-static int bootp( char *image_name )
-
-{ BOOTP req;
- Packet _reply;
- BOOTP *reply = (BOOTP *)_reply;
- static unsigned char mincookie[] = { 99, 130, 83, 99, 255 };
- unsigned long starttime, rancopy;
- int err, len, retry;
-
- memset( (char *)&req, 0, sizeof(req) );
- /* Now fill in the packet... */
- req.bootp.op = BOOTREQUEST;
- req.bootp.htype = 1; /* 10Mb/s Ethernet */
- req.bootp.hlen = 6;
- memcpy( req.bootp.chaddr, &MyHwaddr, ETHADDRLEN );
-
- /* Put in the minimal RFC1497 Magic cookie */
- memcpy( req.bootp.vend, mincookie, sizeof(mincookie) );
- /* Put the user precified bootfile name in place */
- memcpy( req.bootp.file, image_name, strlen(image_name)+1);
-
- starttime = _hz_200;
- for( retry = 0; retry < BOOTP_RETRYS; ++retry ) {
-
- /* Initialize server addresses and own IP to defaults */
- ServerIPaddr = IP_Broadcast_Addr; /* 255.255.255.255 */
- MyIPaddr = IP_Unknown_Addr; /* 0.0.0.0 */
- memcpy( ServerHwaddr, Eth_Broadcast_Addr, ETHADDRLEN );
-
- if (retry)
- sleep( 3 );
-
- req.bootp.xid = rancopy = _hz_200;
- req.bootp.secs = (_hz_200 - starttime) / HZ;
-
- if ((err = udp_send( (UDP *)&req, sizeof(req.bootp),
- UDP_BOOTPC, UDP_BOOTPS )) < 0) {
- printf( "bootp send: %s\n", ErrStr[-err-1] );
- continue;
- }
-
- if ((err = udp_rcv( (UDP *)reply, &len,
- UDP_BOOTPS, UDP_BOOTPC )) < 0) {
- printf( "bootp rcv: %s\n", ErrStr[-err-1] );
- continue;
- }
- if (len < sizeof(struct bootp)) {
- printf( "received short BOOTP packet (%d bytes)\n", len );
- continue;
- }
-
- if (reply->bootp.xid == rancopy)
- /* Ok, got the answer */
- break;
- printf( "bootp: xid mismatch\n" );
- }
- if (retry >= BOOTP_RETRYS) {
- printf( "No response from a bootp server\n" );
- return( -2 );
- }
-
- ServerIPaddr = reply->bootp.siaddr;
- memcpy( ServerHwaddr, reply->ether.src_addr, ETHADDRLEN );
- printf( "\nBoot server is " );
- if (strlen(reply->bootp.sname) > 0)
- printf( "%s, IP ", reply->bootp.sname );
- print_ip( ServerIPaddr );
- printf( ", HW address " );
- print_hw( ServerHwaddr );
- printf( "\n" );
-
- MyIPaddr = reply->bootp.yiaddr;
- printf( "My IP address is " );
- print_ip( MyIPaddr );
- printf( "\n" );
-
- strcpy( image_name, reply->bootp.file );
- return( 0 );
-}
-
-
-/* --------------------------------------------------------------------- */
-/* TFTP Procedure */
-
-
-static int tftp( char *image_name )
-
-{ TFTP spkt;
- Packet _rpkt;
- TFTP *rpkt = (TFTP *)&_rpkt;
- unsigned short mytid, rtid = 0;
- int blk, retries, i, wpos, err, len, datalen;
- static char rotchar[4] = { '|', '/', '-', '\\' };
-
- retries = 5;
- /* Construct and send a read request */
- repeat_req:
- spkt.tftp.req.opcode = TFTP_RRQ;
- strcpy( spkt.tftp.req.name, image_name );
- strcpy( spkt.tftp.req.name + strlen(spkt.tftp.req.name) + 1, "octet" );
- mytid = _hz_200 & 0xffff;
-
- if ((err = udp_send( (UDP *)&spkt, sizeof(spkt.tftp.req.opcode) +
- strlen(image_name) + 1 +
- strlen( "octect" ) +1,
- mytid, UDP_TFTP )) < 0) {
- printf( "TFTP RREQ: %s\n", ErrStr[-err-1] );
- if (--retries > 0)
- goto repeat_req;
- return( err == ETIMEO ? -2 : -1 );
- }
-
- retries = 5;
- for( i = 0; i < KFILE_N_CHUNKS; ++i )
- KFile[i] = NULL;
- wpos = 0;
- printf( "Receiving kernel image %s:\n", image_name );
-
- for( blk = 1; ; ++blk ) {
-
- repeat_data:
- if ((err = udp_rcv( (UDP *)rpkt, &len, rtid, mytid )) < 0) {
- printf( "TFTP rcv: %s\n", ErrStr[-err-1] );
- if (--retries > 0)
- goto repeat_data;
- goto err;
- }
- if (rtid == 0)
- /* Store the remote port at the first packet received */
- rtid = rpkt->udp.src_port;
-
- if (rpkt->tftp.opcode == TFTP_ERROR) {
- if (strlen(rpkt->tftp.error.str) > 0)
- printf( "TFTP error: %s\n", rpkt->tftp.error.str );
- else
- printf( "TFTP error #%d (no description)\n",
- rpkt->tftp.error.errcode );
- goto err;
- }
- else if (rpkt->tftp.opcode != TFTP_DATA) {
- printf( "Bad TFTP packet type: %d\n", rpkt->tftp.opcode );
- if (--retries > 0)
- goto repeat_data;
- goto err;
- }
-
- if (rpkt->tftp.data.nr != blk) {
- /* doubled data packet; ignore it */
- goto repeat_data;
- }
- datalen = len - sizeof(rpkt->tftp.data.opcode) -
- sizeof(rpkt->tftp.data.nr);
-
- /* store data */
- if (datalen > 0) {
- int chunk = wpos >> KFILE_CHUNK_BITS;
- if (chunk >= KFILE_N_CHUNKS) {
- printf( "TFTP: file too large! Aborting.\n" );
- out_of_mem:
- spkt.tftp.error.opcode = TFTP_ERROR;
- spkt.tftp.error.errcode = 3;
- strcpy( spkt.tftp.error.str, "Out of memory" );
- udp_send( (UDP *)&spkt, sizeof(spkt.tftp.ack), mytid, rtid );
- goto err;
- }
- if (!KFile[chunk]) {
- if (!(KFile[chunk] = malloc( KFILE_CHUNK_SIZE ))) {
- printf( "TFTP: Out of memory for kernel image\n" );
- goto out_of_mem;
- }
- }
- memcpy( KFile[chunk] + (wpos & KFILE_CHUNK_MASK),
- rpkt->tftp.data.data, datalen );
- wpos += datalen;
-
-#define DISPLAY_BITS 13
- if ((wpos & ((1 << DISPLAY_BITS)-1)) == 0) {
- printf( "\r %c %7d Bytes ",
- rotchar[(wpos>>DISPLAY_BITS)&3], wpos );
- fflush( stdout );
- }
- }
-
- /* Send ACK packet */
- repeat_ack:
- spkt.tftp.ack.opcode = TFTP_ACK;
- spkt.tftp.ack.nr = blk;
- if ((err = udp_send( (UDP *)&spkt, sizeof(spkt.tftp.ack),
- mytid, rtid )) < 0) {
- printf( "TFTP ACK: %s\n", ErrStr[-err-1] );
- if (--retries > 0)
- goto repeat_ack;
- goto err;
- }
-
- if (datalen < 512) {
- /* This was the last packet */
- printf( "\r %7d Bytes done\n\n", wpos );
- break;
- }
-
- retries = 5;
- }
-
- KFileSize = wpos;
- return( 0 );
-
- err:
- free_kfile();
- return( -1 );
-}
-
-
-
-/* --------------------------------------------------------------------- */
-/* UDP/IP Protocol Quick Hack Implementation */
-
-
-static int udp_send( UDP *pkt, int len, int fromport, int toport )
-
-{
- /* UDP layer */
- pkt->udp.src_port = fromport;
- pkt->udp.dst_port = toport;
- pkt->udp.len = (len += sizeof(struct udphdr));
- pkt->udp.chksum = 0; /* Too lazy to calculate :-) */
-
- /* IP layer */
- pkt->ip.version = 4;
- pkt->ip.ihl = 5;
- pkt->ip.tos = 0;
- pkt->ip.tot_len = (len += sizeof(struct iphdr));
- pkt->ip.id = 0;
- pkt->ip.frag_off = 0;
- pkt->ip.ttl = 255;
- pkt->ip.protocol = 17; /* UDP */
- pkt->ip.src_addr = MyIPaddr;
- pkt->ip.dst_addr = ServerIPaddr;
- pkt->ip.chksum = 0;
- pkt->ip.chksum = ip_checksum( &pkt->ip );
-
- /* Ethernet layer */
- memcpy( &pkt->ether.dst_addr, ServerHwaddr, ETHADDRLEN );
- memcpy( &pkt->ether.src_addr, MyHwaddr, ETHADDRLEN );
- pkt->ether.type = 0x0800;
- len += sizeof(struct etherhdr);
-
- return( eth_send( (Packet *)pkt, len ) );
-}
-
-
-static unsigned short ip_checksum( struct iphdr *buf )
-
-{ unsigned long sum = 0, wlen = 5;
-
- __asm__ ("subqw #1,%2\n"
- "1:\t"
- "movel %1@+,%/d0\n\t"
- "addxl %/d0,%0\n\t"
- "dbra %2,1b\n\t"
- "movel %0,%/d0\n\t"
- "swap %/d0\n\t"
- "addxw %/d0,%0\n\t"
- "clrw %/d0\n\t"
- "addxw %/d0,%0"
- : "=d" (sum), "=a" (buf), "=d" (wlen)
- : "0" (sum), "1" (buf), "2" (wlen)
- : "d0");
- return( (~sum) & 0xffff );
-}
-
-
-static int udp_rcv( UDP *pkt, int *len, int fromport, int atport )
-
-{ int err;
-
- repeat:
- if ((err = eth_rcv( (Packet *)pkt, len )))
- return( err );
-
- /* Ethernet layer */
- if (pkt->ether.type == 0x0806) {
- /* ARP */
- ARP *pk = (ARP *)pkt;
- unsigned char *shw, *sip, *thw, *tip;
-
- if (pk->arp.hrd != 1 || pk->arp.pro != 0x0800 ||
- pk->arp.op != 1 || MyIPaddr == IP_Unknown_Addr)
- /* Wrong hardware type or protocol; or reply -> ignore */
- goto repeat;
- shw = pk->arp.addr;
- sip = shw + pk->arp.hln;
- thw = sip + pk->arp.pln;
- tip = thw + pk->arp.hln;
-
- if (memcmp( tip, &MyIPaddr, pk->arp.pln ) == 0) {
- memcpy( thw, shw, pk->arp.hln );
- memcpy( tip, sip, pk->arp.pln );
- memcpy( shw, &MyHwaddr, pk->arp.hln );
- memcpy( sip, &MyIPaddr, pk->arp.pln );
-
- memcpy( &pk->ether.dst_addr, thw, ETHADDRLEN );
- memcpy( &pk->ether.src_addr, &MyHwaddr, ETHADDRLEN );
- eth_send( (Packet *)pk, *len );
- }
- goto repeat;
- }
- else if (pkt->ether.type != 0x0800) {
- printf( "Unknown Ethernet packet type %04x received\n",
- pkt->ether.type );
- goto repeat;
- }
-
- /* IP layer */
- if (MyIPaddr != IP_Unknown_Addr && pkt->ip.dst_addr != MyIPaddr) {
- printf( "Received packet for wrong IP address\n" );
- goto repeat;
- }
- if (ServerIPaddr != IP_Unknown_Addr &&
- ServerIPaddr != IP_Broadcast_Addr &&
- pkt->ip.src_addr != ServerIPaddr) {
- printf( "Received packet from wrong server\n" );
- goto repeat;
- }
- /* If IP header is longer than 5 longs, delete the options */
- if (pkt->ip.ihl > 5) {
- char *udpstart = (char *)((long *)&pkt->ip + pkt->ip.ihl);
- memmove( &pkt->udp, udpstart, *len - (udpstart-(char *)pkt) );
- }
-
- /* UDP layer */
- if (fromport != 0 && pkt->udp.src_port != fromport) {
- printf( "Received packet from wrong port %d\n", pkt->udp.src_port );
- goto repeat;
- }
- if (pkt->udp.dst_port != atport) {
- printf( "Received packet at wrong port %d\n", pkt->udp.dst_port );
- goto repeat;
- }
-
- *len = pkt->udp.len - sizeof(struct udphdr);
- return( 0 );
-}
-
-
-/* --------------------------------------------------------------------- */
-/* Address Printing */
-
-
-static void print_ip( IPADDR addr )
-
-{
- printf( "%ld.%ld.%ld.%ld",
- (addr >> 24) & 0xff,
- (addr >> 16) & 0xff,
- (addr >> 8) & 0xff,
- addr & 0xff );
-}
-
-
-static void print_hw( HWADDR addr )
-
-{
- printf( "%02x:%02x:%02x:%02x:%02x:%02x",
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
-}
-
-
-/* --------------------------------------------------------------------- */
-/* Ethernet Interface Abstraction Layer */
-
-
-#ifdef ETHLL_LANCE
-#include "ethlance.h"
-#endif
-
-static ETHIF_SWITCH *PossibleInterfaces[] = {
-#ifdef ETHLL_LANCE
- &LanceSwitch,
-#endif
-};
-
-#define N_PossibleInterfaces (sizeof(PossibleInterfaces)/sizeof(*PossibleInterfaces))
-
-/* Detected interface */
-static ETHIF_SWITCH *Ethif = NULL;
-
-
-static int check_ethif( void )
-
-{ int i;
-
- /* Check for configured interfaces */
- Ethif = NULL;
- for( i = 0; i < N_PossibleInterfaces; ++i ) {
- if (PossibleInterfaces[i]->probe() >= 0) {
- Ethif = PossibleInterfaces[i];
- break;
- }
- }
- if (!Ethif)
- return( -1 );
-
- if (Ethif->init() < 0) {
- printf( "Ethernet interface initialization failed\n" );
- return( -1 );
- }
- Ethif->get_hwaddr( &MyHwaddr );
- return( 0 );
-}
-
-
-static int eth_send( Packet *pkt, int len )
-
-{
- return( Ethif->snd( pkt, len ));
-}
-
-
-static int eth_rcv( Packet *pkt, int *len )
-
-{
- return( Ethif->rcv( pkt, len ));
-}
-
-
-#if 0
-static void dump_packet( UDP *pkt )
-
-{ int i, l;
- unsigned char *p;
-
- printf( "Packet dump:\n" );
-
- printf( "Ethernet header:\n" );
- printf( " dst addr: " ); print_hw( pkt->ether.dst_addr ); printf( "\n" );
- printf( " src addr: " ); print_hw( pkt->ether.src_addr ); printf( "\n" );
- printf( " type: %04x\n", pkt->ether.type );
-
- printf( "IP header:\n" );
- printf( " version: %d\n", pkt->ip.version );
- printf( " hdr len: %d\n", pkt->ip.ihl );
- printf( " tos: %d\n", pkt->ip.tos );
- printf( " tot_len: %d\n", pkt->ip.tot_len );
- printf( " id: %d\n", pkt->ip.id );
- printf( " frag_off: %d\n", pkt->ip.frag_off );
- printf( " ttl: %d\n", pkt->ip.ttl );
- printf( " prot: %d\n", pkt->ip.protocol );
- printf( " src addr: " ); print_ip( pkt->ip.src_addr ); printf( "\n" );
- printf( " dst addr: " ); print_ip( pkt->ip.dst_addr ); printf( "\n" );
-
- printf( "UDP header:\n" );
- printf( " src port: %d\n", pkt->udp.src_port );
- printf( " dst port: %d\n", pkt->udp.dst_port );
- printf( " len: %d\n", pkt->udp.len );
-
- printf( "Data:" );
- l = pkt->udp.len - sizeof(pkt->udp);
- p = (unsigned char *)&pkt->udp + sizeof(pkt->udp);
- for( i = 0; i < l; ++i ) {
- if ((i % 32) == 0)
- printf( "\n %04x ", i );
- printf( "%02x ", *p );
- }
- printf( "\n" );
-}
-#endif
diff --git a/arch/m68k/boot/atari/bootp.h b/arch/m68k/boot/atari/bootp.h
index 0ee96cdcc..e69de29bb 100644
--- a/arch/m68k/boot/atari/bootp.h
+++ b/arch/m68k/boot/atari/bootp.h
@@ -1,44 +0,0 @@
-#ifndef _bootp_h
-#define _bootp_h
-
-/* --------------------------------------------------------------------- */
-/* Ethernet Definitions */
-
-#define PKTLEN 1544
-typedef unsigned char Packet[PKTLEN];
-
-#define ETHADDRLEN 6
-typedef unsigned char HWADDR[ETHADDRLEN];
-
-typedef struct {
- int (*probe)( void );
- int (*init)( void );
- void (*get_hwaddr)( HWADDR *addr );
- int (*snd)( Packet *pkt, int len );
- int (*rcv)( Packet *pkt, int *len );
-} ETHIF_SWITCH;
-
-
-/* error codes */
-#define ETIMEO -1 /* Timeout */
-#define ESEND -2 /* General send error (carrier, abort, ...) */
-#define ERCV -3 /* General receive error */
-#define EFRAM -4 /* Framing error */
-#define EOVERFL -5 /* Overflow (too long packet) */
-#define ECRC -6 /* CRC error */
-
-
-typedef unsigned long IPADDR;
-
-
-/***************************** Prototypes *****************************/
-
-int get_remote_kernel( const char *kname );
-int ll_read( int fd, void *buf, unsigned cnt );
-int ll_lseek( int fd, int where, int whence );
-int ll_close( int fd );
-
-/************************* End of Prototypes **************************/
-
-#endif /* _bootp_h */
-
diff --git a/arch/m68k/boot/atari/bootstrap.c b/arch/m68k/boot/atari/bootstrap.c
index 84c6a6e4b..e69de29bb 100644
--- a/arch/m68k/boot/atari/bootstrap.c
+++ b/arch/m68k/boot/atari/bootstrap.c
@@ -1,1602 +0,0 @@
-/*
-** bootstrap.c -- Load and launch the Atari Linux kernel
-**
-** Copyright 1993 by Arjan Knor
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file COPYING in the main directory of this archive
-** for more details.
-**
-** History:
-** 01 Feb 1997 Implemented kernel decompression (Roman)
-** 28 Nov 1996 Fixed and tested previous change (James)
-** 27 Nov 1996 Compatibility with bootinfo interface version 1.0 (Geert)
-** 12 Nov 1996 Fixed and tested previous change (Andreas)
-** 18 Aug 1996 Updated for the new boot information structure (untested!)
-** (Geert)
-** 10 Dec 1995 BOOTP/TFTP support (Roman)
-** 03 Oct 1995 Allow kernel to be loaded to TT ram again (Andreas)
-** 11 Jul 1995 Add support for ELF format kernel (Andreas)
-** 16 Jun 1995 Adapted to Linux 1.2: kernel always loaded into ST ram
-** (Andreas)
-** 14 Nov 1994 YANML (Yet Another New Memory Layout :-) kernel
-** start address is KSTART_ADDR + PAGE_SIZE, this
-** does not need the ugly kludge with
-** -fwritable-strings (++andreas)
-** 09 Sep 1994 Adapted to the new memory layout: All the boot_info entry
-** mentions all ST-Ram and the mover is located somewhere
-** in the middle of memory (roman)
-** Added the default arguments file known from the other
-** bootstrap version
-** 19 Feb 1994 Changed everything so that it works? (rdv)
-** 14 Mar 1994 New mini-copy routine used (rdv)
-*/
-
-
-#define BOOTINFO_COMPAT_1_0 /* bootinfo interface version 1.0 compatible */
-/* support compressed kernels? */
-#define ZKERNEL
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stddef.h>
-#include <string.h>
-#include <ctype.h>
-#include "sysvars.h"
-#include <osbind.h>
-#include <sys/types.h>
-#include <sys/file.h>
-
-/* linux specific include files */
-#include <linux/a.out.h>
-#include <linux/elf.h>
-#include <asm/page.h>
-
-#define _LINUX_TYPES_H /* Hack to prevent including <linux/types.h> */
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-/* Atari bootstrap include file */
-#include "bootstrap.h"
-
-#define MIN_RAMSIZE (3) /* 3 MB */
-#define TEMP_STACKSIZE 256
-
-extern char *optarg;
-extern int optind;
-static void get_default_args( int *argc, char ***argv );
-static int create_bootinfo(void);
-#ifdef BOOTINFO_COMPAT_1_0
-static int create_compat_bootinfo(void);
-#endif /* BOOTINFO_COMPAT_1_0 */
-static int add_bi_record(u_short tag, u_short size, const void *data);
-static int add_bi_string(u_short tag, const u_char *s);
-/* This is missing in <unistd.h> */
-extern int sync (void);
-
-/* Bootinfo */
-static struct atari_bootinfo bi;
-
-#ifdef BOOTINFO_COMPAT_1_0
-static struct compat_bootinfo compat_bootinfo;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-#define MAX_BI_SIZE (4096)
-static u_long bi_size;
-static union {
-struct bi_record record;
- u_char fake[MAX_BI_SIZE];
-} bi_union;
-
-u_long *cookiejar;
-u_long userstk;
-
-/* getcookie -- function to get the value of the given cookie. */
-static int getcookie(char *cookie, u_long *value)
-{
- int i = 0;
-
- while(cookiejar[i] != 0L) {
- if(cookiejar[i] == *(u_long *)cookie) {
- *value = cookiejar[i + 1];
- return 1;
- }
- i += 2;
- }
- return -1;
-}
-
-static void usage(void)
-{
- fprintf(stderr, "Usage:\n"
- "\tbootstrap [-dst] [-k kernel_executable] [-r ramdisk_file]"
- " [option...]\n");
- exit(EXIT_FAILURE);
-}
-
-/*
- * Copy the kernel and the ramdisk to their final resting places.
- *
- * I assume that the kernel data and the ramdisk reside somewhere
- * in the middle of the memory.
- *
- * This program itself should be somewhere in the first 4096 bytes of memory
- * where the kernel never will be. In this way it can never be overwritten
- * by itself.
- *
- * At this point the registers have:
- * a0: the start of the final kernel
- * a1: the start of the current kernel
- * a2: the end of the final ramdisk
- * a3: the end of the current ramdisk
- * d0: the kernel size
- * d1: the ramdisk size
- */
-asm ("
-.text
-.globl _copyall, _copyallend
-_copyall:
-
- movel a0,a4 /* save the start of the kernel for booting */
-
-1: movel a1@+,a0@+ /* copy the kernel starting at the beginning */
- subql #4,d0
- jcc 1b
-
- tstl d1
- beq 3f
-
-2: movel a3@-,a2@- /* copy the ramdisk starting at the end */
- subql #4,d1
- jcc 2b
-
-3: jmp a4@ /* jump to the start of the kernel */
-_copyallend:
-");
-
-extern char copyall, copyallend;
-
-
-/* Test for a Medusa: This is the only machine on which address 0 is
- * writeable!
- * ...err! On the Afterburner040 (for the Falcon) it's the same... So we do
- * another test with 0x00ff82fe, that gives a bus error on the Falcon, but is
- * in the range where the Medusa always asserts DTACK.
- * On the Hades address 0 is writeable as well and it asserts DTACK on
- * address 0x00ff82fe. To test if the machine is a Hades, address 0xb0000000
- * is tested. On the Medusa this gives a bus error.
- */
-
-int test_medusa( void )
-
-{ int rv = 0;
-
- __asm__ __volatile__
- ( "movel 0x8,a0\n\t"
- "movel sp,a1\n\t"
- "moveb 0x0,d1\n\t"
- "movel #Lberr,0x8\n\t"
- "moveq #0,%0\n\t"
- "clrb 0x0\n\t"
- "nop \n\t"
- "moveb d1,0x0\n\t"
- "nop \n\t"
- "tstb 0x00ff82fe\n\t"
- "nop \n\t"
- "moveq #1,%0\n\t"
- "tstb 0xb0000000\n\t"
- "nop \n\t"
- "moveq #0,%0\n"
- "Lberr:\t"
- "movel a1,sp\n\t"
- "movel a0,0x8"
- : "=d" (rv)
- : /* no inputs */
- : "d1", "a0", "a1", "memory" );
-
- return( rv );
-}
-
-
-/* Test if FPU instructions are executed in hardware, or if they're
- emulated in software. For this, the F-line vector is temporarily
- replaced. */
-
-int test_software_fpu(void)
-{
- int rv = 0;
-
- __asm__ __volatile__
- ( "movel 0x2c,a0\n\t"
- "movel sp,a1\n\t"
- "movel #Lfline,0x2c\n\t"
- "moveq #1,%0\n\t"
- "fnop \n\t"
- "nop \n\t"
- "moveq #0,%0\n"
- "Lfline:\t"
- "movel a1,sp\n\t"
- "movel a0,0x2c"
- : "=d" (rv)
- : /* no inputs */
- : "a0", "a1" );
-
- return rv;
-}
-
-
-void get_medusa_bank_sizes( u_long *bank1, u_long *bank2 )
-
-{ static u_long save_addr;
- u_long test_base, saved_contents[16];
-#define TESTADDR(i) (*((u_long *)((char *)test_base + i*8*MB)))
-#define TESTPAT 0x12345678
- unsigned short oldflags;
- int i;
-
- /* This ensures at least that none of the test addresses conflicts
- * with the test code itself */
- test_base = ((unsigned long)&save_addr & 0x007fffff) | 0x20000000;
- *bank1 = *bank2 = 0;
-
- /* Interrupts must be disabled because arbitrary addresses may be
- * temporarily overwritten, even code of an interrupt handler */
- __asm__ __volatile__ ( "movew sr,%0; oriw #0x700,sr" : "=g" (oldflags) : );
- disable_cache();
-
- /* save contents of the test addresses */
- for( i = 0; i < 16; ++i )
- saved_contents[i] = TESTADDR(i);
-
- /* write 0s into all test addresses */
- for( i = 0; i < 16; ++i )
- TESTADDR(i) = 0;
-
- /* test for bank 1 */
-#if 0
- /* This is Freddi's original test, but it didn't work. */
- TESTADDR(0) = TESTADDR(1) = TESTPAT;
- if (TESTADDR(1) == TESTPAT) {
- if (TESTADDR(2) == TESTPAT)
- *bank1 = 8*MB;
- else if (TESTADDR(3) == TESTPAT)
- *bank1 = 16*MB;
- else
- *bank1 = 32*MB;
- }
- else {
- if (TESTADDR(2) == TESTPAT)
- *bank1 = 0;
- else
- *bank1 = 16*MB;
- }
-#else
- TESTADDR(0) = TESTPAT;
- if (TESTADDR(1) == TESTPAT)
- *bank1 = 8*MB;
- else if (TESTADDR(2) == TESTPAT)
- *bank1 = 16*MB;
- else if (TESTADDR(4) == TESTPAT)
- *bank1 = 32*MB;
- else
- *bank1 = 64*MB;
-#endif
-
- /* test for bank2 */
- if (TESTADDR(8) != 0)
- *bank2 = 0;
- else {
- TESTADDR(8) = TESTPAT;
- if (TESTADDR(9) != 0) {
- if (TESTADDR(10) == TESTPAT)
- *bank2 = 8*MB;
- else
- *bank2 = 32*MB;
- }
- else {
- TESTADDR(9) = TESTPAT;
- if (TESTADDR(10) == TESTPAT)
- *bank2 = 16*MB;
- else
- *bank2 = 64*MB;
- }
- }
-
- /* restore contents of the test addresses and restore interrupt mask */
- for( i = 0; i < 16; ++i )
- TESTADDR(i) = saved_contents[i];
- __asm__ __volatile__ ( "movew %0,sr" : : "g" (oldflags) );
-}
-
-#undef TESTADDR
-#undef TESTPAT
-
-
-static int check_bootinfo_version(char *memptr)
-{
- struct bootversion *bv = (struct bootversion *)memptr;
- unsigned long version = 0;
- int i, kernel_major, kernel_minor, boots_major, boots_minor;
-
- printf( "\n" );
- if (bv->magic == BOOTINFOV_MAGIC) {
- for( i = 0; bv->machversions[i].machtype != 0; ++i ) {
- if (bv->machversions[i].machtype == MACH_ATARI) {
- version = bv->machversions[i].version;
- break;
- }
- }
- }
- if (!version)
- printf("Kernel has no bootinfo version info, assuming 0.0\n");
-
- kernel_major = BI_VERSION_MAJOR(version);
- kernel_minor = BI_VERSION_MINOR(version);
- boots_major = BI_VERSION_MAJOR(ATARI_BOOTI_VERSION);
- boots_minor = BI_VERSION_MINOR(ATARI_BOOTI_VERSION);
- printf("Bootstrap's bootinfo version: %d.%d\n",
- boots_major, boots_minor);
- printf("Kernel's bootinfo version : %d.%d\n",
- kernel_major, kernel_minor);
-
- switch (kernel_major) {
- case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
- if (kernel_minor > boots_minor) {
- printf("Warning: Bootinfo version of bootstrap and kernel "
- "differ!\n");
- printf(" Certain features may not work.\n");
- }
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
- printf("(using backwards compatibility mode)\n");
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- printf("\nThis bootstrap is too %s for this kernel!\n",
- boots_major < kernel_major ? "old" : "new");
- return 0;
- }
- return kernel_major;
-}
-
-
-#ifdef USE_BOOTP
-# include "bootp.h"
-#else
-# define ll_read read
-# define ll_lseek lseek
-# define ll_close close
-#endif
-
-#ifdef ZKERNEL
-static int load_zkernel( int fd );
-static int kread( int fd, void *buf, unsigned cnt );
-static int klseek( int fd, int where, int whence );
-static int kclose( int fd );
-#else
-# define kread read
-# define klseek lseek
-# define kclose close
-#endif
-
-/* ++andreas: this must be inline due to Super */
-static inline void boot_exit (int) __attribute__ ((noreturn));
-static inline void boot_exit(int status)
-{
- /* first go back to user mode */
- (void)Super(userstk);
- getchar();
- exit(status);
-}
-
-int main(int argc, char *argv[])
-{
- int debugflag = 0, ch, kfd, rfd = -1, i, ignore_ttram = 0;
- int load_to_stram = 0;
- char *ramdisk_name, *kernel_name, *memptr;
- u_long ST_ramsize, TT_ramsize, memreq;
- u_long cpu_type, fpu_type, mch_type, mint;
- struct exec kexec;
- int elf_kernel = 0;
- Elf32_Ehdr kexec_elf;
- Elf32_Phdr *kernel_phdrs = NULL;
- u_long start_mem, mem_size, rd_size, text_offset = 0, kernel_size;
- int prefer_bootp = 1, kname_set = 0, n_knames;
-#ifdef USE_BOOTP
- int err;
-#endif
- char kname_list[5][64];
- void *bi_ptr;
-
- ramdisk_name = NULL;
- kernel_name = "vmlinux";
-
- /* print the startup message */
- puts("\fLinux/68k Atari Bootstrap version 2.2"
-#ifdef USE_BOOTP
- " (with BOOTP)"
-#endif
- );
- puts("Copyright 1993,1994 by Arjan Knor, Robert de Vries, Roman Hodek, Andreas Schwab\n");
-
- /* ++roman: If no arguments on the command line, read them from
- * file */
- if (argc == 1)
- get_default_args( &argc, &argv );
-
- /* machine is Atari */
- bi.machtype = MACH_ATARI;
-
- /* check arguments */
- while ((ch = getopt(argc, argv, "bdtsk:r:")) != EOF)
- switch (ch) {
- case 'd':
- debugflag = 1;
- break;
- case 't':
- ignore_ttram = 1;
- break;
- case 's':
- load_to_stram = 1;
- break;
- case 'k':
- kernel_name = optarg;
- kname_set = 1;
- break;
- case 'r':
- ramdisk_name = optarg;
- break;
- case 'b':
- prefer_bootp = 0;
- break;
- case '?':
- default:
- usage();
- }
-
- argc -= optind;
- argv += optind;
-
- /* We have to access some system variables to get
- * the information we need, so we must switch to
- * supervisor mode first.
- */
- userstk = Super(0L);
-
- /* get the info we need from the cookie-jar */
- cookiejar = *_p_cookies;
- if(cookiejar == 0L) {
- /* if we find no cookies, it's probably an ST */
- fprintf(stderr, "Error: No cookiejar found. Is this an ST?\n");
- boot_exit(EXIT_FAILURE);
- }
-
- /* Exit if MiNT/MultiTOS is running. */
- if(getcookie("MiNT", &mint) != -1)
- {
- puts("Warning: MiNT is running\n");
-#if 0
- puts("Linux cannot be started when MiNT is running. Aborting...\n");
- boot_exit(EXIT_FAILURE);
-#endif
- }
-
- /* get _CPU, _FPU and _MCH */
- getcookie("_CPU", &cpu_type);
- getcookie("_FPU", &fpu_type);
- getcookie("_MCH", &mch_type);
-
- /* check if we are on a 68030/40 with FPU */
- if ((cpu_type != 30 && cpu_type != 40 && cpu_type != 60))
- {
- puts("Machine type currently not supported. Aborting...");
- boot_exit(EXIT_FAILURE);
- }
-
- switch(cpu_type) {
- case 0:
- case 10: break;
- case 20: bi.cputype = CPU_68020; bi.mmutype = MMU_68851; break;
- case 30: bi.cputype = CPU_68030; bi.mmutype = MMU_68030; break;
- case 40: bi.cputype = CPU_68040; bi.mmutype = MMU_68040; break;
- case 60: bi.cputype = CPU_68060; bi.mmutype = MMU_68060; break;
- default:
- fprintf(stderr, "Error: Unknown CPU type. Aborting...\n");
- boot_exit(EXIT_FAILURE);
- break;
- }
-
- printf("CPU: %ld; ", cpu_type + 68000);
- printf("FPU: ");
-
- /* check for FPU; in case of a '040 or '060, don't look at _FPU itself,
- * some software may set it to wrong values (68882 or the like) */
- if (cpu_type == 40) {
- bi.fputype = FPU_68040;
- puts( "68040\n" );
- }
- else if (cpu_type == 60) {
- bi.fputype = FPU_68060;
- puts( "68060\n" );
- }
- else {
- switch ((fpu_type >> 16) & 7) {
- case 0:
- puts("not present\n");
- break;
- case 1:
- puts("SFP004 not supported. Assuming no FPU.");
- break;
- case 2:
- /* try to determine real type */
- if (fpu_idle_frame_size () != 0x18)
- goto m68882;
- /* fall through */
- case 4:
- bi.fputype = FPU_68881;
- puts("68881\n");
- break;
- case 6:
- m68882:
- bi.fputype = FPU_68882;
- puts("68882\n");
- break;
- default:
- puts("Unknown FPU type. Assuming no FPU.");
- break;
- }
- }
- /* ++roman: If an FPU was announced in the cookie, test
- whether it is a real hardware FPU or a software emulator! */
- if (bi.fputype) {
- if (test_software_fpu()) {
- bi.fputype = 0;
- puts("FPU: software emulated. Assuming no FPU.");
- }
- }
-
- /* Get the amounts of ST- and TT-RAM. */
- /* The size must be a multiple of 1MB. */
- i = 0;
-
- if (!test_medusa()) {
- struct {
- unsigned short version; /* version - currently 1 */
- unsigned long fr_start; /* start addr FastRAM */
- unsigned long fr_len; /* length FastRAM */
- } *magn_cookie;
- struct {
- unsigned long version;
- unsigned long fr_start; /* start addr */
- unsigned long fr_len; /* length */
- } *fx_cookie;
-
- TT_ramsize = 0;
- if (!ignore_ttram) {
- /* "Original" or properly emulated TT-Ram */
- if (*ramtop) {
- /* the 'ramtop' variable at 0x05a4 is not
- * officially documented. We use it anyway
- * because it is the only way to get the TTram size.
- * (It is zero if there is no TTram.)
- */
- bi.memory[i].addr = TT_RAM_BASE;
- bi.memory[i].size = (*ramtop - TT_RAM_BASE) & ~(MB - 1);
- TT_ramsize = bi.memory[i].size / MB;
- i++;
- printf("TT-RAM: %ld Mb; ", TT_ramsize);
- }
-
- /* test for MAGNUM alternate RAM
- * added 26.9.1995 M. Schwingen, rincewind@discworld.oche.de
- */
- if (getcookie("MAGN", (u_long *)&magn_cookie) != -1) {
- bi.memory[i].addr = magn_cookie->fr_start;
- bi.memory[i].size = magn_cookie->fr_len & ~(MB - 1);
- TT_ramsize += bi.memory[i].size / MB;
- printf("MAGNUM alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
- i++;
- }
-
- /* BlowUps FX */
- if (getcookie("BPFX", (u_long *)&fx_cookie) != -1 && fx_cookie) {
- /* if fx is set (cookie call above),
- * we assume that BlowUps FX-card
- * is installed. (Nat!)
- */
- bi.memory[i].addr = fx_cookie->fr_start;
- bi.memory[i].size = fx_cookie->fr_len & ~(MB - 1);
- printf("FX alternate RAM: %ld Mb; ", bi.memory[i].size/MB);
- i++;
- }
- }
-
- bi.memory[i].addr = 0;
- bi.memory[i].size = *phystop & ~(MB - 1);
- ST_ramsize = bi.memory[i].size / MB;
- i++;
- printf("ST-RAM: %ld Mb\n", ST_ramsize );
-
- bi.num_memory = i;
-
- if (load_to_stram && i > 1) {
- /* Put ST-RAM first in the list of mem blocks */
- struct mem_info temp = bi.memory[i - 1];
- bi.memory[i - 1] = bi.memory[0];
- bi.memory[0] = temp;
- }
- }
- else {
- u_long bank1, bank2, medusa_st_ram;
-
- get_medusa_bank_sizes( &bank1, &bank2 );
- medusa_st_ram = *phystop & ~(MB - 1);
- bank1 -= medusa_st_ram;
- TT_ramsize = 0;
-
- bi.memory[i].addr = 0;
- bi.memory[i].size = medusa_st_ram;
- ST_ramsize = bi.memory[i].size / MB;
- i++;
- printf("Medusa pseudo ST-RAM from bank 1: %ld Mb; ", ST_ramsize );
-
- if (!ignore_ttram && bank1 > 0) {
- bi.memory[i].addr = 0x20000000 + medusa_st_ram;
- bi.memory[i].size = bank1;
- TT_ramsize += bank1;
- i++;
- printf("TT-RAM bank 1: %ld Mb; ", bank1/MB );
- }
-
- if (!ignore_ttram && bank2 > 0) {
- bi.memory[i].addr = 0x24000000;
- bi.memory[i].size = bank2;
- TT_ramsize += bank2;
- i++;
- printf("TT-RAM bank 2: %ld Mb; ", bank2/MB );
- }
-
- bi.num_memory = i;
- printf("\n");
- }
-
- /* verify that there is enough RAM; ST- and TT-RAM combined */
- if (ST_ramsize + TT_ramsize < MIN_RAMSIZE) {
- puts("Not enough RAM. Aborting...");
- boot_exit(10);
- }
-
-#if 0
- /* Get language/keyboard info */
- /* TODO: do we need this ? */
- /* Could be used to auto-select keyboard map later on. (rdv) */
- if (getcookie("_AKP",&language) == -1)
- {
- /* Get the language info from the OS-header */
- os_header = *_sysbase;
- os_header = os_header->os_beg;
- lang = (os_header->os_conf) >> 1;
- printf("Language: ");
- switch(lang) {
- case HOL: puts("Dutch"); break; /* Own country first :-) */
- case USA: puts("American"); break;
- case SWG: puts("Switzerland (German)"); break;
- case FRG: puts("German"); break;
- case FRA: puts("French"); break;
- case SWF: puts("Switzerland (French)"); break;
- case UK: puts("English"); break;
- case SPA: puts("Spanish"); break;
- case ITA: puts("Italian"); break;
- case SWE: puts("Swedish"); break;
- case TUR: puts("Turkey"); break;
- case FIN: puts("Finnish"); break;
- case NOR: puts("Norwegian"); break;
- case DEN: puts("Danish"); break;
- case SAU: puts("Saudi-Arabian"); break;
- default: puts("Unknown"); break;
- }
- }
- else
- {
- printf("Language: ");
- switch(language & 0x0F)
- {
- case 1: printf("German "); break;
- case 2: printf("French "); break;
- case 4: printf("Spanish "); break;
- case 5: printf("Italian "); break;
- case 7: printf("Swiss French "); break;
- case 8: printf("Swiss German "); break;
- default: printf("English ");
- }
- printf("Keyboard type :");
- switch(language >> 8)
- {
- case 1: printf("German "); break;
- case 2: printf("French "); break;
- case 4: printf("Spanish "); break;
- case 5: printf("Italian "); break;
- case 7: printf("Swiss French "); break;
- case 8: printf("Swiss German "); break;
- default: printf("English ");
- }
- printf("\n");
- }
-#endif
-
- /* Pass contents of the _MCH cookie to the kernel */
- bi.mch_cookie = mch_type;
-
- /*
- * Copy command line options into the kernel command line.
- */
- i = 0;
- while (argc--) {
- if ((i+strlen(*argv)+1) < CL_SIZE) {
- i += strlen(*argv) + 1;
- if (bi.command_line[0])
- strcat (bi.command_line, " ");
- strcat (bi.command_line, *argv++);
- }
- }
- printf ("Command line is '%s'\n", bi.command_line);
-
- start_mem = bi.memory[0].addr;
- mem_size = bi.memory[0].size;
-
- /* tell us where the kernel will go */
- printf("\nThe kernel will be located at 0x%08lx\n", start_mem);
-
-#ifdef TEST
- /*
- ** Temporary exit point for testing
- */
- boot_exit(-1);
-#endif /* TEST */
-
- i = 0;
-#ifdef USE_BOOTP
- if (!kname_set)
- kname_list[i++][0] = '\0'; /* default kernel which BOOTP server says */
-#endif
-#ifdef ZKERNEL
- strcpy( kname_list[i], kernel_name );
- strcat( kname_list[i], ".gz" );
- ++i;
-#endif
- strcpy( kname_list[i++], kernel_name );
-#ifdef ZKERNEL
- if (!kname_set)
- strcpy( kname_list[i++], "vmlinuz" );
-#endif
- n_knames = i;
-
- kfd = -1;
-#ifdef USE_BOOTP
- if (prefer_bootp) {
- for( i = 0; i < n_knames; ++i ) {
- if ((err = get_remote_kernel( kname_list[i] )) >= 0)
- goto kernel_open;
- if (err < -1) /* fatal error; retries don't help... */
- break;
- }
- printf( "\nremote boot failed; trying local kernel\n" );
- }
-#endif
- for( i = 0; i < n_knames; ++i ) {
- if ((kfd = open( kname_list[i], O_RDONLY )) != -1)
- goto kernel_open;
- }
-#ifdef USE_BOOTP
- if (!prefer_bootp) {
- printf( "\nlocal kernel failed; trying remote boot\n" );
- for( i = 0; i < n_knames; ++i ) {
- if ((err = get_remote_kernel( kname_list[i] )) >= 0)
- goto kernel_open;
- if (err < -1) /* fatal error; retries don't help... */
- break;
- }
- }
-#endif
- fprintf( stderr, "Unable to open any kernel file\n(Tried " );
- for( i = 0; i < n_knames; ++i ) {
- fprintf( stderr, "%s%s", kname_list[i],
- i < n_knames-2 ? ", " :
- i == n_knames-2 ? ", and " :
- ")\n" );
- }
- boot_exit( EXIT_FAILURE );
-
- kernel_open:
-
- if (kread (kfd, (void *)&kexec, sizeof(kexec)) != sizeof(kexec))
- {
- fprintf (stderr, "Unable to read exec header from %s\n", kernel_name);
- boot_exit (EXIT_FAILURE);
- }
-
-#ifdef ZKERNEL
- if (((unsigned char *)&kexec)[0] == 037 &&
- (((unsigned char *)&kexec)[1] == 0213 ||
- ((unsigned char *)&kexec)[1] == 0236)) {
- /* That's a compressed kernel */
- printf( "Kernel is compressed\n" );
- if (load_zkernel( kfd )) {
- printf( "Decompression error -- aborting\n" );
- boot_exit( EXIT_FAILURE );
- }
- }
-#endif
-
- switch (N_MAGIC(kexec)) {
- case ZMAGIC:
- text_offset = N_TXTOFF(kexec);
- break;
- case QMAGIC:
- text_offset = sizeof(kexec);
- /* the text size includes the exec header; remove this */
- kexec.a_text -= sizeof(kexec);
- break;
- default:
- /* Try to parse it as an ELF header */
- klseek (kfd, 0, SEEK_SET);
- if (kread (kfd, (void *)&kexec_elf, sizeof (kexec_elf)) == sizeof (kexec_elf)
- && memcmp (&kexec_elf.e_ident[EI_MAG0], ELFMAG, SELFMAG) == 0)
- {
- elf_kernel = 1;
- /* A few plausibility checks */
- if (kexec_elf.e_type != ET_EXEC || kexec_elf.e_machine != EM_68K
- || kexec_elf.e_version != EV_CURRENT)
- {
- fprintf (stderr, "Invalid ELF header contents in kernel\n");
- boot_exit (EXIT_FAILURE);
- }
- /* Load the program headers */
- kernel_phdrs = (Elf32_Phdr *) Malloc (kexec_elf.e_phnum * sizeof (Elf32_Phdr));
- if (kernel_phdrs == NULL)
- {
- fprintf (stderr, "Unable to allocate memory for program headers\n");
- boot_exit (EXIT_FAILURE);
- }
- klseek (kfd, kexec_elf.e_phoff, SEEK_SET);
- if (kread (kfd, (void *) kernel_phdrs,
- kexec_elf.e_phnum * sizeof (*kernel_phdrs))
- != kexec_elf.e_phnum * sizeof (*kernel_phdrs))
- {
- fprintf (stderr, "Unable to read program headers from %s\n",
- kernel_name);
- boot_exit (EXIT_FAILURE);
- }
- break;
- }
- fprintf (stderr, "Wrong magic number %lo in kernel header\n",
- N_MAGIC(kexec));
- boot_exit (EXIT_FAILURE);
- }
-
- /* Load the kernel one page after start of mem */
- start_mem += PAGE_SIZE;
- mem_size -= PAGE_SIZE;
- /* Align bss size to multiple of four */
- if (!elf_kernel)
- kexec.a_bss = (kexec.a_bss + 3) & ~3;
-
- /* init ramdisk */
- if(ramdisk_name) {
- if((rfd = open(ramdisk_name, O_RDONLY)) == -1) {
- fprintf(stderr, "Unable to open ramdisk file %s\n",
- ramdisk_name);
- boot_exit(EXIT_FAILURE);
- }
- bi.ramdisk.size = lseek(rfd, 0, SEEK_END);
- }
- else
- bi.ramdisk.size = 0;
-
- /* calculate the total required amount of memory */
- if (elf_kernel)
- {
- u_long min_addr = 0xffffffff, max_addr = 0;
- for (i = 0; i < kexec_elf.e_phnum; i++)
- {
- if (min_addr > kernel_phdrs[i].p_vaddr)
- min_addr = kernel_phdrs[i].p_vaddr;
- if (max_addr < kernel_phdrs[i].p_vaddr + kernel_phdrs[i].p_memsz)
- max_addr = kernel_phdrs[i].p_vaddr + kernel_phdrs[i].p_memsz;
- }
- /* This is needed for newer linkers that include the header in
- the first segment. */
- if (min_addr == 0)
- {
- min_addr = PAGE_SIZE;
- kernel_phdrs[0].p_vaddr += PAGE_SIZE;
- kernel_phdrs[0].p_offset += PAGE_SIZE;
- kernel_phdrs[0].p_filesz -= PAGE_SIZE;
- kernel_phdrs[0].p_memsz -= PAGE_SIZE;
- }
- kernel_size = max_addr - min_addr;
- }
- else
- kernel_size = kexec.a_text + kexec.a_data + kexec.a_bss;
-
- rd_size = bi.ramdisk.size;
- if (rd_size + kernel_size > mem_size - MB/2 && bi.num_memory > 1)
- /* If running low on ST ram load ramdisk into alternate ram. */
- bi.ramdisk.addr = (u_long) bi.memory[1].addr + bi.memory[1].size - rd_size;
- else
- /* Else hopefully there is enough ST ram. */
- bi.ramdisk.addr = (u_long)start_mem + mem_size - rd_size;
-
- /* create the bootinfo structure */
- if (!create_bootinfo())
- boot_exit (EXIT_FAILURE);
-
- memreq = kernel_size + bi_size;
-#ifdef BOOTINFO_COMPAT_1_0
- if (sizeof(compat_bootinfo) > bi_size)
- memreq = kernel_size+sizeof(compat_bootinfo);
-#endif /* BOOTINFO_COMPAT_1_0 */
- /* align load address of ramdisk image, read() is sloooow on odd addr. */
- memreq = ((memreq + 3) & ~3) + rd_size;
-
- /* allocate RAM for the kernel */
- if (!(memptr = (char *)Malloc (memreq)))
- {
- fprintf (stderr, "Unable to allocate memory for kernel and ramdisk\n");
- boot_exit (EXIT_FAILURE);
- }
- else
- fprintf(stderr, "kernel at address %lx\n", (u_long) memptr);
-
- (void)memset(memptr, 0, memreq);
-
- /* read the text and data segments from the kernel image */
- if (elf_kernel)
- {
- for (i = 0; i < kexec_elf.e_phnum; i++)
- {
- if (klseek (kfd, kernel_phdrs[i].p_offset, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to segment %d\n", i);
- boot_exit (EXIT_FAILURE);
- }
- if (kread (kfd, memptr + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
- kernel_phdrs[i].p_filesz)
- != kernel_phdrs[i].p_filesz)
- {
- fprintf (stderr, "Failed to read segment %d\n", i);
- boot_exit (EXIT_FAILURE);
- }
- }
- }
- else
- {
- if (klseek (kfd, text_offset, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to text\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- if (kread (kfd, memptr, kexec.a_text) != kexec.a_text)
- {
- fprintf (stderr, "Failed to read text\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- /* data follows immediately after text */
- if (kread (kfd, memptr + kexec.a_text, kexec.a_data) != kexec.a_data)
- {
- fprintf (stderr, "Failed to read data\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- }
- kclose (kfd);
-
- /* Check kernel's bootinfo version */
- switch (check_bootinfo_version(memptr)) {
- case BI_VERSION_MAJOR(ATARI_BOOTI_VERSION):
- bi_ptr = &bi_union.record;
- break;
-
-#ifdef BOOTINFO_COMPAT_1_0
- case BI_VERSION_MAJOR(COMPAT_ATARI_BOOTI_VERSION):
- if (!create_compat_bootinfo()) {
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- bi_ptr = &compat_bootinfo;
- bi_size = sizeof(compat_bootinfo);
- break;
-#endif /* BOOTINFO_COMPAT_1_0 */
-
- default:
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
-
- /* copy the boot_info struct to the end of the kernel image */
- memcpy ((void *)(memptr + kernel_size), bi_ptr, bi_size);
-
- /* read the ramdisk image */
- if (rfd != -1)
- {
- if (lseek (rfd, 0, SEEK_SET) == -1)
- {
- fprintf (stderr, "Failed to seek to beginning of ramdisk file\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- if (read (rfd, memptr + memreq - rd_size,
- rd_size) != rd_size)
- {
- fprintf (stderr, "Failed to read ramdisk file\n");
- Mfree ((void *)memptr);
- boot_exit (EXIT_FAILURE);
- }
- close (rfd);
- }
-
- /* for those who want to debug */
- if (debugflag)
- {
- if (bi.ramdisk.size)
- printf ("RAM disk at %#lx, size is %ld\n",
- (u_long)(memptr + memreq - rd_size),
- bi.ramdisk.size);
-
- if (elf_kernel)
- {
- for (i = 0; i < kexec_elf.e_phnum; i++)
- {
- printf ("Kernel segment %d at %#lx, size %ld\n", i,
- start_mem + kernel_phdrs[i].p_vaddr - PAGE_SIZE,
- kernel_phdrs[i].p_memsz);
- }
- }
- else
- {
- printf ("\nKernel text at %#lx, code size %d\n",
- start_mem, kexec.a_text);
- printf ("Kernel data at %#lx, data size %d\n",
- start_mem + kexec.a_text, kexec.a_data );
- printf ("Kernel bss at %#lx, bss size %d\n",
- start_mem + kexec.a_text + kexec.a_data, kexec.a_bss );
- }
- printf ("\nboot_info is at %#lx\n",
- start_mem + kernel_size);
- printf ("\nKernel entry is %#lx\n",
- elf_kernel ? kexec_elf.e_entry : kexec.a_entry);
- printf ("ramdisk dest top is %#lx\n", bi.ramdisk.addr + rd_size);
- printf ("ramdisk lower limit is %#lx\n",
- (u_long)(memptr + memreq - rd_size));
- printf ("ramdisk src top is %#lx\n", (u_long)(memptr + memreq));
-
- printf ("Type a key to continue the Linux boot...");
- fflush (stdout);
- getchar();
- }
-
- printf("Booting Linux...\n");
-
- sync ();
-
- /* turn off interrupts... */
- disable_interrupts();
-
- /* turn off caches... */
- disable_cache();
-
- /* ..and any MMU translation */
- disable_mmu();
-
- /* ++guenther: allow reset if launched with MiNT */
- *(long*)0x426 = 0;
-
- /* copy mover code to a safe place if needed */
- memcpy ((void *) 0x400, &copyall, &copyallend - &copyall);
-
- /* setup stack */
- change_stack ((void *) PAGE_SIZE);
-
- /*
- * On the Atari you can have two situations:
- * 1. One piece of contiguous RAM (Falcon)
- * 2. Two pieces of contiguous RAM (TT)
- * In case 2 you can load your program into ST-ram and load your data in
- * any old RAM you have left.
- * In case 1 you could overwrite your own program when copying the
- * kernel and ramdisk to their final positions.
- * To solve this the mover code is copied to a safe place first.
- * Then this program jumps to the mover code. After the mover code
- * has finished it jumps to the start of the kernel in its new position.
- * I thought the memory just after the interrupt vector table was a safe
- * place because it is used by TOS to store some system variables.
- * This range goes from 0x400 to approx. 0x5B0.
- * This is more than enough for the miniscule mover routine (16 bytes).
- */
-
- jump_to_mover((char *) start_mem, memptr,
- (char *) bi.ramdisk.addr + rd_size, memptr + memreq,
- kernel_size + bi_size, rd_size,
- (void *) 0x400);
-
- for (;;);
- /* NOTREACHED */
-}
-
-
-
-#define MAXARGS 30
-
-static void get_default_args( int *argc, char ***argv )
-
-{ FILE *f;
- static char *nargv[MAXARGS];
- char arg[256], *p;
- int c, quote, state;
-
- if (!(f = fopen( "bootargs", "r" )))
- return;
-
- *argc = 1;
- if (***argv)
- nargv[0] = **argv;
- else
- nargv[0] = "bootstrap";
- *argv = nargv;
-
- quote = state = 0;
- p = arg;
- while( (c = fgetc(f)) != EOF ) {
-
- if (state == 0) {
- /* outside args, skip whitespace */
- if (!isspace(c)) {
- state = 1;
- p = arg;
- }
- }
-
- if (state) {
- /* inside an arg: copy it into 'arg', obeying quoting */
- if (!quote && (c == '\'' || c == '"'))
- quote = c;
- else if (quote && c == quote)
- quote = 0;
- else if (!quote && isspace(c)) {
- /* end of this arg */
- *p = 0;
- nargv[(*argc)++] = strdup(arg);
- state = 0;
- }
- else
- *p++ = c;
- }
- }
- if (state) {
- /* last arg finished by EOF! */
- *p = 0;
- nargv[(*argc)++] = strdup(arg);
- }
- fclose( f );
-
- nargv[*argc] = 0;
-}
-
-
- /*
- * Create the Bootinfo Structure
- */
-
-static int create_bootinfo(void)
-{
- int i;
- struct bi_record *record;
-
- /* Initialization */
- bi_size = 0;
-
- /* Generic tags */
- if (!add_bi_record(BI_MACHTYPE, sizeof(bi.machtype), &bi.machtype))
- return(0);
- if (!add_bi_record(BI_CPUTYPE, sizeof(bi.cputype), &bi.cputype))
- return(0);
- if (!add_bi_record(BI_FPUTYPE, sizeof(bi.fputype), &bi.fputype))
- return(0);
- if (!add_bi_record(BI_MMUTYPE, sizeof(bi.mmutype), &bi.mmutype))
- return(0);
- for (i = 0; i < bi.num_memory; i++)
- if (!add_bi_record(BI_MEMCHUNK, sizeof(bi.memory[i]), &bi.memory[i]))
- return(0);
- if (bi.ramdisk.size)
- if (!add_bi_record(BI_RAMDISK, sizeof(bi.ramdisk), &bi.ramdisk))
- return(0);
- if (!add_bi_string(BI_COMMAND_LINE, bi.command_line))
- return(0);
-
- /* Atari tags */
- if (!add_bi_record(BI_ATARI_MCH_COOKIE, sizeof(bi.mch_cookie),
- &bi.mch_cookie))
- return(0);
-
- /* Trailer */
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = BI_LAST;
- bi_size += sizeof(bi_union.record.tag);
-
- return(1);
-}
-
-
- /*
- * Add a Record to the Bootinfo Structure
- */
-
-static int add_bi_record(u_short tag, u_short size, const void *data)
-{
- struct bi_record *record;
- u_short size2;
-
- size2 = (sizeof(struct bi_record)+size+3)&-4;
- if (bi_size+size2+sizeof(bi_union.record.tag) > MAX_BI_SIZE) {
- fprintf (stderr, "Can't add bootinfo record. Ask a wizard to enlarge me.\n");
- return(0);
- }
- record = (struct bi_record *)((u_long)&bi_union.record+bi_size);
- record->tag = tag;
- record->size = size2;
- memcpy(record->data, data, size);
- bi_size += size2;
- return(1);
-}
-
-
- /*
- * Add a String Record to the Bootinfo Structure
- */
-
-static int add_bi_string(u_short tag, const u_char *s)
-{
- return add_bi_record(tag, strlen(s)+1, (void *)s);
-}
-
-
-#ifdef BOOTINFO_COMPAT_1_0
-
- /*
- * Create the Bootinfo structure for backwards compatibility mode
- */
-
-static int create_compat_bootinfo(void)
-{
- u_int i;
-
- compat_bootinfo.machtype = bi.machtype;
- if (bi.cputype & CPU_68020)
- compat_bootinfo.cputype = COMPAT_CPU_68020;
- else if (bi.cputype & CPU_68030)
- compat_bootinfo.cputype = COMPAT_CPU_68030;
- else if (bi.cputype & CPU_68040)
- compat_bootinfo.cputype = COMPAT_CPU_68040;
- else if (bi.cputype & CPU_68060)
- compat_bootinfo.cputype = COMPAT_CPU_68060;
- else {
- printf("CPU type 0x%08lx not supported by kernel\n", bi.cputype);
- return(0);
- }
- if (bi.fputype & FPU_68881)
- compat_bootinfo.cputype |= COMPAT_FPU_68881;
- else if (bi.fputype & FPU_68882)
- compat_bootinfo.cputype |= COMPAT_FPU_68882;
- else if (bi.fputype & FPU_68040)
- compat_bootinfo.cputype |= COMPAT_FPU_68040;
- else if (bi.fputype & FPU_68060)
- compat_bootinfo.cputype |= COMPAT_FPU_68060;
- else {
- printf("FPU type 0x%08lx not supported by kernel\n", bi.fputype);
- return(0);
- }
- compat_bootinfo.num_memory = bi.num_memory;
- if (compat_bootinfo.num_memory > COMPAT_NUM_MEMINFO) {
- printf("Warning: using only %d blocks of memory\n",
- COMPAT_NUM_MEMINFO);
- compat_bootinfo.num_memory = COMPAT_NUM_MEMINFO;
- }
- for (i = 0; i < compat_bootinfo.num_memory; i++) {
- compat_bootinfo.memory[i].addr = bi.memory[i].addr;
- compat_bootinfo.memory[i].size = bi.memory[i].size;
- }
- if (bi.ramdisk.size) {
- compat_bootinfo.ramdisk_size = (bi.ramdisk.size+1023)/1024;
- compat_bootinfo.ramdisk_addr = bi.ramdisk.addr;
- } else {
- compat_bootinfo.ramdisk_size = 0;
- compat_bootinfo.ramdisk_addr = 0;
- }
- strncpy(compat_bootinfo.command_line, bi.command_line, COMPAT_CL_SIZE);
- compat_bootinfo.command_line[COMPAT_CL_SIZE-1] = '\0';
-
- compat_bootinfo.bi_atari.hw_present = 0;
- compat_bootinfo.bi_atari.mch_cookie = bi.mch_cookie;
- return(1);
-}
-#endif /* BOOTINFO_COMPAT_1_0 */
-
-
-#ifdef ZKERNEL
-
-#define ZFILE_CHUNK_BITS 16 /* chunk is 64 KB */
-#define ZFILE_CHUNK_SIZE (1 << ZFILE_CHUNK_BITS)
-#define ZFILE_CHUNK_MASK (ZFILE_CHUNK_SIZE-1)
-#define ZFILE_N_CHUNKS (2*1024*1024/ZFILE_CHUNK_SIZE)
-
-/* variables for storing the uncompressed data */
-static char *ZFile[ZFILE_N_CHUNKS];
-static int ZFileSize = 0;
-static int ZFpos = 0;
-static int Zwpos = 0;
-
-static int Zinfd = 0; /* fd of compressed file */
-
-/*
- * gzip declarations
- */
-
-#define OF(args) args
-
-#define memzero(s, n) memset ((s), 0, (n))
-
-typedef unsigned char uch;
-typedef unsigned short ush;
-typedef unsigned long ulg;
-
-#define INBUFSIZ 4096
-#define WSIZE 0x8000 /* window size--must be a power of two, and */
- /* at least 32K for zip's deflate method */
-
-static uch *inbuf;
-static uch *window;
-
-static unsigned insize = 0; /* valid bytes in inbuf */
-static unsigned inptr = 0; /* index of next byte to be processed in inbuf */
-static unsigned outcnt = 0; /* bytes in output buffer */
-static int exit_code = 0;
-static long bytes_out = 0;
-
-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-
-/* Diagnostic functions (stubbed out) */
-#define Assert(cond,msg)
-#define Trace(x)
-#define Tracev(x)
-#define Tracevv(x)
-#define Tracec(c,x)
-#define Tracecv(c,x)
-
-#define STATIC static
-
-static int fill_inbuf(void);
-static void flush_window(void);
-static void error(char *m);
-static void gzip_mark(void **);
-static void gzip_release(void **);
-
-#include "../../../../lib/inflate.c"
-
-static void gzip_mark( void **ptr )
-{
-}
-
-static void gzip_release( void **ptr )
-{
-}
-
-
-/*
- * Fill the input buffer. This is called only when the buffer is empty
- * and at least one byte is really needed.
- */
-static int fill_inbuf( void )
-{
- if (exit_code)
- return -1;
-
- insize = ll_read( Zinfd, inbuf, INBUFSIZ );
- if (insize <= 0)
- return -1;
-
- inptr = 1;
- return( inbuf[0] );
-}
-
-/*
- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
- * (Used for the decompressed data only.)
- */
-static void flush_window( void )
-{
- ulg c = crc; /* temporary variable */
- unsigned n;
- uch *in, ch;
- int chunk = Zwpos >> ZFILE_CHUNK_BITS;
-
- if (chunk >= ZFILE_N_CHUNKS) {
- fprintf( stderr, "compressed image too large! Aborting.\n" );
- boot_exit( EXIT_FAILURE );
- }
- if (!ZFile[chunk]) {
- if (!(ZFile[chunk] = (char *)Malloc( ZFILE_CHUNK_SIZE ))) {
- fprintf( stderr, "Out of memory for decompresing kernel image\n" );
- boot_exit( EXIT_FAILURE );
- }
- }
- memcpy( ZFile[chunk] + (Zwpos & ZFILE_CHUNK_MASK), window, outcnt );
- Zwpos += outcnt;
-
-#define DISPLAY_BITS 13
- if ((Zwpos & ((1 << DISPLAY_BITS)-1)) == 0) {
- printf( "." );
- fflush( stdout );
- }
-
- in = window;
- for (n = 0; n < outcnt; n++) {
- ch = *in++;
- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
- }
- crc = c;
- bytes_out += (ulg)outcnt;
- outcnt = 0;
-}
-
-static void error( char *x )
-{
- fprintf( stderr, "\n%s", x);
- exit_code = 1;
-}
-
-static int load_zkernel( int fd )
-{
- int i, err;
-
- for( i = 0; i < ZFILE_N_CHUNKS; ++i )
- ZFile[i] = NULL;
- Zinfd = fd;
- ll_lseek( fd, 0, SEEK_SET );
-
- if (!(inbuf = (uch *)Malloc( INBUFSIZ ))) {
- fprintf( stderr, "Couldn't allocate gunzip buffer\n" );
- boot_exit( EXIT_FAILURE );
- }
- if (!(window = (uch *)Malloc( WSIZE ))) {
- fprintf( stderr, "Couldn't allocate gunzip window\n" );
- boot_exit( EXIT_FAILURE );
- }
-
- printf( "Uncompressing kernel image " );
- fflush( stdout );
- makecrc();
- if (!(err = gunzip()))
- printf( "done\n" );
- ZFileSize = Zwpos;
- ll_close( Zinfd ); /* input file not needed anymore */
-
- Mfree( inbuf );
- Mfree( window );
- return( err );
-}
-
-/* Note about the read/lseek wrapper and its memory management: It assumes
- * that all seeks are only forward, and thus data already read or skipped can
- * be freed. This is true for current organization of bootstrap and kernels.
- * Little exception: The struct kexec at the start of the file. After reading
- * it, there may be a seek back to the end of the file. But this currently
- * doesn't hurt. Same considerations apply to the TFTP file buffers. (Roman)
- */
-
-static int kread( int fd, void *buf, unsigned cnt )
-{
- unsigned done = 0;
-
- if (!ZFileSize)
- return( ll_read( fd, buf, cnt ) );
-
- if (ZFpos + cnt > ZFileSize)
- cnt = ZFileSize - ZFpos;
-
- while( cnt > 0 ) {
- unsigned chunk = ZFpos >> ZFILE_CHUNK_BITS;
- unsigned endchunk = (chunk+1) << ZFILE_CHUNK_BITS;
- unsigned n = cnt;
-
- if (ZFpos + n > endchunk)
- n = endchunk - ZFpos;
- memcpy( buf, ZFile[chunk] + (ZFpos & ZFILE_CHUNK_MASK), n );
- cnt -= n;
- buf += n;
- done += n;
- ZFpos += n;
-
- if (ZFpos == endchunk) {
- Mfree( ZFile[chunk] );
- ZFile[chunk] = NULL;
- }
- }
-
- return( done );
-}
-
-
-static int klseek( int fd, int where, int whence )
-{
- unsigned oldpos, oldchunk, newchunk;
-
- if (!ZFileSize)
- return( ll_lseek( fd, where, whence ) );
-
- oldpos = ZFpos;
- switch( whence ) {
- case SEEK_SET:
- ZFpos = where;
- break;
- case SEEK_CUR:
- ZFpos += where;
- break;
- case SEEK_END:
- ZFpos = ZFileSize + where;
- break;
- default:
- return( -1 );
- }
- if (ZFpos < 0) {
- ZFpos = 0;
- return( -1 );
- }
- else if (ZFpos > ZFileSize) {
- ZFpos = ZFileSize;
- return( -1 );
- }
-
- /* free memory of skipped-over data */
- oldchunk = oldpos >> ZFILE_CHUNK_BITS;
- newchunk = ZFpos >> ZFILE_CHUNK_BITS;
- while( oldchunk < newchunk ) {
- if (ZFile[oldchunk]) {
- Mfree( ZFile[oldchunk] );
- ZFile[oldchunk] = NULL;
- }
- ++oldchunk;
- }
-
- return( ZFpos );
-}
-
-
-static void free_zfile( void )
-{
- int i;
-
- for( i = 0; i < ZFILE_N_CHUNKS; ++i )
- if (ZFile[i]) Mfree( ZFile[i] );
-}
-
-static int kclose( int fd )
-{
- if (ZFileSize) {
- free_zfile();
- return( 0 );
- }
- else
- return( ll_close( fd ) );
-}
-
-
-
-#endif /* ZKERNEL */
diff --git a/arch/m68k/boot/atari/bootstrap.h b/arch/m68k/boot/atari/bootstrap.h
index 594916dfe..e69de29bb 100644
--- a/arch/m68k/boot/atari/bootstrap.h
+++ b/arch/m68k/boot/atari/bootstrap.h
@@ -1,171 +0,0 @@
-/*
-** bootstrap.h -- This file is a part of the Atari bootloader.
-**
-** Copyright 1993 by Arjan Knor
-**
-** Modified by Andreas Schwab
-** - clear transparent translation registers
-** Modified 18-Aug-96 by Geert Uytterhoeven
-** - Updated for the new boot information structure (untested!)
-** Modified 1996-11-12 by Andreas Schwab
-** - Fixed and tested previous change
-**
-** This file is subject to the terms and conditions of the GNU General Public
-** License. See the file COPYING in the main directory of this archive
-** for more details.
-**
-*/
-
-#ifndef BOOTSTRAP_H
-#define BOOTSTRAP_H
-
- /*
- * Atari Bootinfo Definitions
- *
- * All limits herein are `soft' limits, i.e. they don't put constraints
- * on the actual parameters in the kernel.
- */
-
-struct atari_bootinfo {
- unsigned long machtype; /* machine type */
- unsigned long cputype; /* system CPU */
- unsigned long fputype; /* system FPU */
- unsigned long mmutype; /* system MMU */
- int num_memory; /* # of memory blocks found */
- struct mem_info memory[NUM_MEMINFO]; /* memory description */
- struct mem_info ramdisk; /* ramdisk description */
- char command_line[CL_SIZE]; /* kernel command line parameters */
- unsigned long mch_cookie; /* _MCH cookie from TOS */
-};
-
-
-/* _MCH cookie values */
-#define MACH_ST 0
-#define MACH_STE 1
-#define MACH_TT 2
-#define MACH_FALCON 3
-
-/* some constants for memory handling */
-#define ST_RAM 0
-#define TT_RAM 1
-#define TT_RAM_BASE (u_long)(0x01000000)
-#define MB (1024 * 1024)
-#define START_MEM (bi.memory[0].addr)
-#define MEM_SIZE (bi.memory[0].size)
-
-/* the various CPU- and FPU-types */
-#define AFF_68000 (1)
-#define AFF_68020 (2)
-#define AFF_68030 (4)
-#define AFF_68040 (8)
-#define AFF_68881 (16)
-#define AFF_68882 (32)
-
-/* the possible OS-languages */
-#define USA 0
-#define FRG 1
-#define FRA 2
-#define UK 3
-#define SPA 4
-#define ITA 5
-#define SWE 6
-#define SWF 7
-#define SWG 8
-#define TUR 9
-#define FIN 10
-#define NOR 11
-#define DEN 12
-#define SAU 13
-#define HOL 14
-
-/* some inline functions */
-
-static __inline int fpu_idle_frame_size (void)
-{
- char fpu_frame[216];
- __asm__ __volatile__ ("fnop"::);
- __asm__ __volatile__ ("fsave %0@" : : "a" (fpu_frame));
- return fpu_frame[1];
-}
-
-static __inline void change_stack (u_long *stackp)
-{
- __asm__ volatile ("movel %0,sp\n\t" :: "g" (stackp) : "sp");
-}
-
-static __inline void disable_interrupts (void)
-{
- __asm__ volatile ("orw #0x700,sr":);
-}
-
-extern struct atari_bootinfo bi;
-static __inline void disable_cache (void)
-{
- __asm__ volatile ("movec %0,cacr" :: "d" (0));
- if (bi.cputype & CPU_68060) {
- /* '060: clear branch cache after disabling it;
- * disable superscalar operation (and enable FPU) */
- __asm__ volatile ("movec %0,cacr" :: "d" (0x00400000));
- __asm__ volatile ("moveq #0,d0;"
- ".long 0x4e7b0808" /* movec d0,pcr */
- : /* no outputs */
- : /* no inputs */
- : "d0");
- }
-}
-
-static __inline void disable_mmu (void)
-{
- if (bi.cputype & (CPU_68040|CPU_68060)) {
- __asm__ volatile ("moveq #0,d0;"
- ".long 0x4e7b0003;" /* movec d0,tc */
- ".long 0x4e7b0004;" /* movec d0,itt0 */
- ".long 0x4e7b0005;" /* movec d0,itt1 */
- ".long 0x4e7b0006;" /* movec d0,dtt0 */
- ".long 0x4e7b0007" /* movec d0,dtt1 */
- : /* no outputs */
- : /* no inputs */
- : "d0");
- }
- else {
- __asm__ volatile ("subl #4,sp\n\t"
- "pmove tc,sp@\n\t"
- "bclr #7,sp@\n\t"
- "pmove sp@,tc\n\t"
- "addl #4,sp");
- if (bi.cputype & CPU_68030) {
- __asm__ volatile ("clrl sp@-\n\t"
- ".long 0xf0170800\n\t" /* pmove sp@,tt0 */
- ".long 0xf0170c00\n\t" /* pmove sp@,tt1 */
- "addl #4,sp\n");
- }
- }
-}
-
-static __inline void jump_to_mover (void *, void *, void *, void *, int, int,
- void *) __attribute__ ((noreturn));
-static __inline void jump_to_mover (void *kernel_start, void *mem_start,
- void *ramdisk_end, void *mem_end,
- int kernel_size, int ramdisk_size,
- void *mover_addr)
-{
- asm volatile ("movel %0,a0\n\t"
- "movel %1,a1\n\t"
- "movel %2,a2\n\t"
- "movel %3,a3\n\t"
- "movel %4,d0\n\t"
- "movel %5,d1\n\t"
- "jmp %6@\n"
- : /* no outputs */
- : "g" (kernel_start), "g" (mem_start),
- "g" (ramdisk_end), "g" (mem_end),
- "g" (kernel_size), "g" (ramdisk_size),
- "a" (mover_addr)
- : "a0", "a1", "a2", "a3", "d0", "d1");
-
- /* Avoid warning that function may return */
- for (;;) ;
-}
-
-#endif /* BOOTSTRAP_H */
-
diff --git a/arch/m68k/boot/atari/ethlance.c b/arch/m68k/boot/atari/ethlance.c
index 3b248c4af..e69de29bb 100644
--- a/arch/m68k/boot/atari/ethlance.c
+++ b/arch/m68k/boot/atari/ethlance.c
@@ -1,435 +0,0 @@
-
-#include <stdio.h>
-#include <string.h>
-
-#include "bootp.h"
-#include "ethlance.h"
-
-
-struct {
- volatile unsigned short *memaddr;
- volatile unsigned short *ioaddr;
-} lance_addr_list[] = {
- { (void *)0xfe010000, (void *)0xfe00fff0 }, /* RieblCard VME in TT */
- { (void *)0xfec10000, (void *)0xfec0fff0 }, /* RieblCard VME in MegaSTE
- (highest byte stripped) */
- { (void *)0xfee00000, (void *)0xfeff7000 }, /* RieblCard in ST
- (highest byte stripped) */
- { (void *)0xfecf0000, (void *)0xfecffff0 }, /* PAMCard VME in TT and MSTE
- (highest byte stripped) */
-};
-
-#define N_LANCE_ADDR (sizeof(lance_addr_list)/sizeof(*lance_addr_list))
-
-#define TX_RING_SIZE 1
-#define TX_RING_LEN_BITS 0
-
-#define RX_RING_SIZE 16
-#define RX_RING_LEN_BITS (4 << 5)
-
-#define offsetof(type,elt) ((unsigned long)(&(((type *)0)->elt)))
-
-/* The LANCE Rx and Tx ring descriptors. */
-struct lance_rx_head {
- unsigned short base; /* Low word of base addr */
- volatile unsigned char flag;
- unsigned char base_hi; /* High word of base addr (unused) */
- short buf_length; /* This length is 2s complement! */
- short msg_length; /* This length is "normal". */
-};
-
-struct lance_tx_head {
- unsigned short base; /* Low word of base addr */
- volatile unsigned char flag;
- unsigned char base_hi; /* High word of base addr (unused) */
- short length; /* Length is 2s complement! */
- volatile short misc;
-};
-
-struct ringdesc {
- unsigned short adr_lo; /* Low 16 bits of address */
- unsigned char len; /* Length bits */
- unsigned char adr_hi; /* High 8 bits of address (unused) */
-};
-
-struct lance_packet {
- volatile unsigned char data[PKTLEN];
-};
-
-/* The LANCE initialization block, described in databook. */
-struct lance_init_block {
- unsigned short mode; /* Pre-set mode */
- unsigned char hwaddr[6]; /* Physical ethernet address */
- unsigned filter[2]; /* Multicast filter (unused). */
- /* Receive and transmit ring base, along with length bits. */
- struct ringdesc rx_ring;
- struct ringdesc tx_ring;
-};
-
-/* The whole layout of the Lance shared memory */
-struct lance_memory {
- struct lance_init_block init;
- struct lance_tx_head tx_head[TX_RING_SIZE];
- struct lance_rx_head rx_head[RX_RING_SIZE];
- struct lance_packet tx_packet[TX_RING_SIZE];
- struct lance_packet rx_packet[TX_RING_SIZE];
-};
-
-#define RIEBL_MAGIC 0x09051990
-#define RIEBL_MAGIC_ADDR ((unsigned long *)(((char *)MEM) + 0xee8a))
-#define RIEBL_HWADDR_ADDR ((unsigned char *)(((char *)MEM) + 0xee8e))
-#define RIEBL_IVEC_ADDR ((unsigned short *)(((char *)MEM) + 0xfffe))
-
-struct lance_ioreg {
-/* base+0x0 */ volatile unsigned short data;
-/* base+0x2 */ volatile unsigned short addr;
- unsigned char _dummy1[3];
-/* base+0x7 */ volatile unsigned char ivec;
- unsigned char _dummy2[5];
-/* base+0xd */ volatile unsigned char eeprom;
- unsigned char _dummy3;
-/* base+0xf */ volatile unsigned char mem;
-};
-
-enum lance_type {
- OLD_RIEBL, /* old Riebl card without battery */
- NEW_RIEBL, /* new Riebl card with battery */
- PAM_CARD /* PAM card with EEPROM */
-} CardType;
-
-HWADDR dev_addr;
-
-/* This is a default address for the old RieblCards without a battery
- * that have no ethernet address at boot time. 00:00:36:04 is the
- * prefix for Riebl cards, the 00:00 at the end is arbitrary.
- */
-
-HWADDR OldRieblDefHwaddr = {
- 0x00, 0x00, 0x36, 0x04, 0x00, 0x00
-};
-
-struct lance_ioreg *IO;
-struct lance_memory *MEM;
-
-#define DREG IO->data
-#define AREG IO->addr
-#define REGA(a) ( AREG = (a), DREG )
-
-int CurRx;
-
-
-/* Definitions for the Lance */
-
-/* tx_head flags */
-#define TMD1_ENP 0x01
-#define TMD1_STP 0x02
-#define TMD1_DEF 0x04
-#define TMD1_ONE 0x08
-#define TMD1_MORE 0x10
-#define TMD1_ERR 0x40
-#define TMD1_OWN 0x80
-
-#define TMD1_OWN_CHIP TMD1_OWN
-#define TMD1_OWN_HOST 0
-
-/* tx_head misc field */
-#define TMD3_TDR 0x03FF
-#define TMD3_RTRY 0x0400
-#define TMD3_LCAR 0x0800
-#define TMD3_LCOL 0x1000
-#define TMD3_UFLO 0x4000
-#define TMD3_BUFF3 0x8000
-
-/* rx_head flags */
-#define RMD1_ENP 0x01
-#define RMD1_STP 0x02
-#define RMD1_BUFF 0x04
-#define RMD1_CRC 0x08
-#define RMD1_OFLO 0x10
-#define RMD1_FRAM 0x20
-#define RMD1_ERR 0x40
-#define RMD1_OWN 0x80
-
-#define RMD1_OWN_CHIP RMD1_OWN
-#define RMD1_OWN_HOST 0
-
-/* register names */
-#define CSR0 0
-#define CSR1 1
-#define CSR2 2
-#define CSR3 3
-
-/* CSR0 */
-#define CSR0_INIT 0x0001 /* initialize */
-#define CSR0_STRT 0x0002 /* start */
-#define CSR0_STOP 0x0004 /* stop */
-#define CSR0_TDMD 0x0008 /* transmit demand */
-#define CSR0_TXON 0x0010 /* transmitter on */
-#define CSR0_RXON 0x0020 /* receiver on */
-#define CSR0_INEA 0x0040 /* interrupt enable */
-#define CSR0_INTR 0x0080 /* interrupt active */
-#define CSR0_IDON 0x0100 /* initialization done */
-#define CSR0_TINT 0x0200 /* transmitter interrupt */
-#define CSR0_RINT 0x0400 /* receiver interrupt */
-#define CSR0_MERR 0x0800 /* memory error */
-#define CSR0_MISS 0x1000 /* missed frame */
-#define CSR0_CERR 0x2000 /* carrier error (no heartbeat :-) */
-#define CSR0_BABL 0x4000 /* babble: tx-ed too many bits */
-#define CSR0_ERR 0x8000 /* error */
-
-/* CSR3 */
-#define CSR3_BCON 0x0001
-#define CSR3_ACON 0x0002
-#define CSR3_BSWP 0x0004
-
-
-#define HZ 200
-#define _hz_200 (*(volatile unsigned long *)0x4ba)
-
-
-
-
-/***************************** Prototypes *****************************/
-
-static int lance_probe( void );
-static int addr_readable( volatile void *regp, int wordflag );
-static int lance_init( void );
-static void lance_get_hwaddr( HWADDR *addr );
-static int lance_snd( Packet *pkt, int len );
-static int lance_rcv( Packet *pkt, int *len );
-
-/************************* End of Prototypes **************************/
-
-
-
-ETHIF_SWITCH LanceSwitch = {
- lance_probe, lance_init, lance_get_hwaddr,
- lance_snd, lance_rcv
-};
-
-
-static int lance_probe( void )
-
-{ int i;
-
- for( i = 0; i < N_LANCE_ADDR; ++i ) {
- if (addr_readable( lance_addr_list[i].memaddr, 1 ) &&
- (lance_addr_list[i].memaddr[0] = 1,
- lance_addr_list[i].memaddr[0] == 1) &&
- (lance_addr_list[i].memaddr[0] = 0,
- lance_addr_list[i].memaddr[0] == 0) &&
- addr_readable( lance_addr_list[i].ioaddr, 1 )) {
- break;
- }
- }
- if (i == N_LANCE_ADDR) return( -1 );
-
- IO = (struct lance_ioreg *)lance_addr_list[i].ioaddr;
- MEM = (struct lance_memory *)lance_addr_list[i].memaddr;
- REGA( CSR0 ) = CSR0_STOP;
-
- return( 0 );
-}
-
-
-static int addr_readable( volatile void *regp, int wordflag )
-
-{ int ret;
- long *vbr, save_berr;
-
- __asm__ __volatile__ ( "movec %/vbr,%0" : "=r" (vbr) : );
- save_berr = vbr[2];
-
- __asm__ __volatile__
- ( "movel %/sp,%/d1\n\t"
- "movel #Lberr,%2@\n\t"
- "moveq #0,%0\n\t"
- "tstl %3\n\t"
- "bne 1f\n\t"
- "tstb %1@\n\t"
- "bra 2f\n"
-"1: tstw %1@\n"
-"2: moveq #1,%0\n"
-"Lberr: movel %/d1,%/sp"
- : "=&d" (ret)
- : "a" (regp), "a" (&vbr[2]), "rm" (wordflag)
- : "d1", "memory"
- );
-
- vbr[2] = save_berr;
-
- return( ret );
-}
-
-
-static int lance_init( void )
-
-{ int i;
-
- /* Now test for type: If the eeprom I/O port is readable, it is a
- * PAM card */
- if (addr_readable( &(IO->eeprom), 0 )) {
- /* Switch back to Ram */
- i = IO->mem;
- CardType = PAM_CARD;
- }
- else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
- CardType = NEW_RIEBL;
- }
- else
- CardType = OLD_RIEBL;
-
- /* Get the ethernet address */
- switch( CardType ) {
- case OLD_RIEBL:
- /* No ethernet address! (Set some default address) */
- memcpy( dev_addr, OldRieblDefHwaddr, ETHADDRLEN );
- break;
- case NEW_RIEBL:
- memcpy( dev_addr, RIEBL_HWADDR_ADDR, ETHADDRLEN );
- break;
- case PAM_CARD:
- i = IO->eeprom;
- for( i = 0; i < ETHADDRLEN; ++i )
- dev_addr[i] =
- ((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
- ((((unsigned short *)MEM)[i*2+1] & 0x0f));
- i = IO->mem;
- break;
- }
-
- MEM->init.mode = 0x0000; /* Disable Rx and Tx. */
- for( i = 0; i < ETHADDRLEN; i++ )
- MEM->init.hwaddr[i] = dev_addr[i^1]; /* <- 16 bit swap! */
- MEM->init.filter[0] = 0x00000000;
- MEM->init.filter[1] = 0x00000000;
- MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
- MEM->init.rx_ring.adr_hi = 0;
- MEM->init.rx_ring.len = RX_RING_LEN_BITS;
- MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
- MEM->init.tx_ring.adr_hi = 0;
- MEM->init.tx_ring.len = TX_RING_LEN_BITS;
-
- REGA( CSR3 ) = CSR3_BSWP | (CardType == PAM_CARD ? CSR3_ACON : 0);
- REGA( CSR2 ) = 0;
- REGA( CSR1 ) = 0;
- REGA( CSR0 ) = CSR0_INIT | CSR0_STRT;
-
- i = 1000000;
- while( i-- > 0 )
- if (DREG & CSR0_IDON)
- break;
- if (i < 0 || (DREG & CSR0_ERR)) {
- DREG = CSR0_STOP;
- return( -1 );
- }
- DREG = CSR0_IDON;
-
- for (i = 0; i < TX_RING_SIZE; i++) {
- MEM->tx_head[i].base = offsetof( struct lance_memory, tx_packet[i] );
- MEM->tx_head[i].flag = TMD1_OWN_HOST;
- MEM->tx_head[i].base_hi = 0;
- MEM->tx_head[i].length = 0;
- MEM->tx_head[i].misc = 0;
- }
-
- for (i = 0; i < RX_RING_SIZE; i++) {
- MEM->rx_head[i].base = offsetof( struct lance_memory, rx_packet[i] );
- MEM->rx_head[i].flag = TMD1_OWN_CHIP;
- MEM->rx_head[i].base_hi = 0;
- MEM->rx_head[i].buf_length = -PKTLEN;
- MEM->rx_head[i].msg_length = 0;
- }
- CurRx = 0;
-
- return( 0 );
-}
-
-
-static void lance_get_hwaddr( HWADDR *addr )
-
-{
- memcpy( addr, dev_addr, ETHADDRLEN );
-}
-
-
-static int lance_snd( Packet *pkt, int len )
-
-{ unsigned long timeout;
-
- /* The old LANCE chips doesn't automatically pad buffers to min. size. */
- len = (len < 60) ? 60 : len;
- /* PAM-Card has a bug: Can only send packets with even number of bytes! */
- if (CardType == PAM_CARD && (len & 1))
- ++len;
-
- MEM->tx_head[0].length = -len;
- MEM->tx_head[0].misc = 0;
- memcpy( (void *)&MEM->tx_packet[0].data, pkt, len );
- MEM->tx_head[0].base = offsetof(struct lance_memory, tx_packet[0]);
- MEM->tx_head[0].base_hi = 0;
- MEM->tx_head[0].flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
-
- /* Trigger an immediate send poll. */
- REGA( CSR0 ) = CSR0_TDMD;
-
- /* Wait for packet being sent */
- timeout = _hz_200 + 3*HZ;
- while( (MEM->tx_head[0].flag & TMD1_OWN_CHIP) &&
- !MEM->tx_head[0].misc &&
- _hz_200 < timeout )
- ;
-
- if ((MEM->tx_head[0].flag & TMD1_OWN) == TMD1_OWN_HOST &&
- !(MEM->tx_head[0].misc & TMD1_ERR))
- /* sent ok */
- return( 0 );
-
- /* failure */
- if (_hz_200 >= timeout)
- return( ETIMEO );
- if (MEM->tx_head[0].misc & TMD3_UFLO) {
- /* On FIFO errors, must re-turn on TX! */
- DREG = CSR0_STRT;
- }
-
- return( ESEND );
-}
-
-
-static int lance_rcv( Packet *pkt, int *len )
-
-{ unsigned long timeout;
- int stat;
-
- /* Wait for a packet */
- timeout = _hz_200 + 4*HZ;
- while( (MEM->rx_head[CurRx].flag & TMD1_OWN_CHIP) &&
- _hz_200 < timeout )
- ;
- /* Not ours -> was a timeout */
- if (((stat = MEM->rx_head[CurRx].flag) & TMD1_OWN) == TMD1_OWN_CHIP)
- return( ETIMEO );
-
- /* Check for errors */
- if (stat != (RMD1_ENP|RMD1_STP)) {
- MEM->rx_head[CurRx].flag &= (RMD1_ENP|RMD1_STP);
- if (stat & RMD1_FRAM) return( EFRAM );
- if (stat & RMD1_OFLO) return( EOVERFL );
- if (stat & RMD1_CRC) return( ECRC );
- return( ERCV );
- }
-
- /* Get the packet */
- *len = MEM->rx_head[CurRx].msg_length & 0xfff;
- memcpy( pkt, (void *)&MEM->rx_packet[CurRx].data, *len );
-
- /* Give the buffer back to the chip */
- MEM->rx_head[CurRx].buf_length = -PKTLEN;
- MEM->rx_head[CurRx].flag |= RMD1_OWN_CHIP;
- CurRx = (CurRx + 1) % RX_RING_SIZE;
-
- return( 0 );
-}
-
-
diff --git a/arch/m68k/boot/atari/ethlance.h b/arch/m68k/boot/atari/ethlance.h
index 4f9c90241..e69de29bb 100644
--- a/arch/m68k/boot/atari/ethlance.h
+++ b/arch/m68k/boot/atari/ethlance.h
@@ -1,7 +0,0 @@
-
-#ifndef _ethlance_h
-#define _ethlance_h
-
-extern ETHIF_SWITCH LanceSwitch;
-
-#endif /* _ethlance_h */
diff --git a/arch/m68k/boot/atari/sysvars.h b/arch/m68k/boot/atari/sysvars.h
index 087d9f695..e69de29bb 100644
--- a/arch/m68k/boot/atari/sysvars.h
+++ b/arch/m68k/boot/atari/sysvars.h
@@ -1,22 +0,0 @@
-typedef struct _osheader
-{
- unsigned short os_entry;
- unsigned short os_version;
- void *reseth;
- struct _osheader *os_beg;
- void *os_end;
- long os_rsv1;
- void *os_magic;
- long os_date;
- unsigned short os_conf;
- unsigned short os_dosdate;
- char **p_root;
- unsigned char **pkbshift;
- void **p_run;
- char *p_rsv2;
-} OSHEADER;
-
-#define phystop ((unsigned long *)0x42e)
-#define _sysbase ((OSHEADER **)0x4f2)
-#define _p_cookies ((unsigned long **)0x5a0)
-#define ramtop ((unsigned long *)0x5a4)
diff --git a/arch/m68k/config.in b/arch/m68k/config.in
index b963687ae..2390fb6fc 100644
--- a/arch/m68k/config.in
+++ b/arch/m68k/config.in
@@ -218,6 +218,10 @@ define_bool CONFIG_VT y
define_bool CONFIG_VT_CONSOLE y
define_bool CONFIG_FB_CONSOLE y
+if [ "$CONFIG_ATARI" = "y" ]; then
+ define_bool CONFIG_NVRAM y
+fi
+
tristate 'Parallel printer support' CONFIG_PRINTER
if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate 'Multiface Card III parallel support' CONFIG_MULTIFACE_III_LP $CONFIG_PRINTER
@@ -243,6 +247,7 @@ if [ "$CONFIG_AMIGA" = "y" ]; then
dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
dep_tristate 'GVP IO-Extender PLIP support' CONFIG_GVPIOEXT_PLIP $CONFIG_GVPIOEXT
tristate 'Multiface Card III serial support' CONFIG_MULTIFACE_III_TTY
+ bool 'Hisoft Whippet PCMCIA serial support' CONFIG_WHIPPET
fi
if [ "$CONFIG_ATARI_MFPSER" = "y" -o "$CONFIG_ATARI_SCC" = "y" -o \
"$CONFIG_ATARI_MIDI" = "y" -o "$CONFIG_AMIGA_BUILTIN_SERIAL" = "y" -o \
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index 18763c58b..65f71d5a9 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -152,9 +152,6 @@ CONFIG_NETDEVICES=y
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_DCACHE_PRELOAD is not set
-# CONFIG_OMIRR is not set
-# CONFIG_TRANS_NAMES is not set
CONFIG_MINIX_FS=y
CONFIG_EXT2_FS=y
CONFIG_FAT_FS=y
diff --git a/arch/m68k/ifpsp060/iskeleton.S b/arch/m68k/ifpsp060/iskeleton.S
index 35542d4f1..d068d5a16 100644
--- a/arch/m68k/ifpsp060/iskeleton.S
+++ b/arch/m68k/ifpsp060/iskeleton.S
@@ -37,6 +37,7 @@
#include <linux/linkage.h>
#include <asm/entry.h>
+
|################################
| (1) EXAMPLE CALL-OUTS #
| #
diff --git a/arch/m68k/kernel/console.c b/arch/m68k/kernel/console.c
index 204f4d3cc..5e7b29717 100644
--- a/arch/m68k/kernel/console.c
+++ b/arch/m68k/kernel/console.c
@@ -420,7 +420,10 @@ int vc_resize(unsigned long lines, unsigned long columns)
set_scrmem(fg_console, 0);
set_origin(fg_console);
#endif /* XXX */
- update_screen(fg_console);
+ /* don't update in graphics mode */
+ if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
+ update_screen(fg_console);
+
set_cursor(fg_console);
return 0;
@@ -512,8 +515,9 @@ void vc_resize_con(unsigned long lines, unsigned long columns,
console_table[currcons]->winsize = ws;
}
- if (currcons == fg_console)
- update_screen(fg_console);
+ /* don't update in graphics mode */
+ if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
+ update_screen(fg_console);
}
void vc_disallocate(unsigned int currcons)
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 33542ca96..459e9e93a 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -190,7 +190,7 @@ SYMBOL_NAME_LABEL(ret_from_interrupt)
andw #ALLOWINT,%sr
/* check if we need to do software interrupts */
-
+
movel SYMBOL_NAME(bh_active),%d0
andl SYMBOL_NAME(bh_mask),%d0
jeq SYMBOL_NAME(ret_from_exception)
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index 36a4072ac..116c3cb27 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -273,6 +273,9 @@ Ltest_berr:
movel %d2,%a0@
lea %pc@(SYMBOL_NAME(is_medusa)),%a0
movel %d3,%a0@
+ lea %pc@(Liobase),%a0
+ movel %d2,%a0@ /* On a Hades the iobase must be set
+ before opening the serial port. */
Lnotypetest:
#endif
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index ad0662f22..27883a86e 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -283,8 +283,9 @@ asmlinkage int sys_execve(char *name, char **argv, char **envp)
struct pt_regs *regs = (struct pt_regs *) &name;
lock_kernel();
- error = getname(name, &filename);
- if (error)
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c
index e29509cac..9c56fed37 100644
--- a/arch/m68k/kernel/sys_m68k.c
+++ b/arch/m68k/kernel/sys_m68k.c
@@ -205,11 +205,10 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
return -ENOSYS;
}
-/* Convert virtual address VADDR to physical address PADDR, recording
- in VALID whether the virtual address is actually mapped. */
-#define virt_to_phys_040(vaddr, paddr, valid) \
-{ \
- unsigned long _mmusr; \
+/* Convert virtual address VADDR to physical address PADDR */
+#define virt_to_phys_040(vaddr) \
+({ \
+ unsigned long _mmusr, _paddr; \
\
__asm__ __volatile__ (".chip 68040\n\t" \
"ptestr (%1)\n\t" \
@@ -217,20 +216,14 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
".chip 68k" \
: "=r" (_mmusr) \
: "a" (vaddr)); \
- if (!(_mmusr & MMU_R_040)) \
- (valid) = 0; \
- else \
- { \
- (valid) = 1; \
- (paddr) = _mmusr & PAGE_MASK; \
- } \
-}
+ _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0; \
+ _paddr; \
+})
static inline int
cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
{
- unsigned long paddr;
- int valid;
+ unsigned long paddr, i;
switch (scope)
{
@@ -261,19 +254,31 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
break;
case FLUSH_SCOPE_LINE:
- len >>= 4;
/* Find the physical address of the first mapped page in the
address range. */
- for (;;)
- {
- virt_to_phys_040 (addr, paddr, valid);
- if (valid)
- break;
- if (len <= PAGE_SIZE / 16)
- return 0;
- len -= (PAGE_SIZE - (addr & PAGE_MASK)) / 16;
- addr = (addr + PAGE_SIZE) & PAGE_MASK;
- }
+ if ((paddr = virt_to_phys_040(addr))) {
+ paddr += addr & ~(PAGE_MASK | 15);
+ len = (len + (addr & 15) + 15) >> 4;
+ } else {
+ unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
+
+ if (len <= tmp)
+ return 0;
+ addr += tmp;
+ len -= tmp;
+ tmp = PAGE_SIZE;
+ for (;;)
+ {
+ if ((paddr = virt_to_phys_040(addr)))
+ break;
+ if (len <= tmp)
+ return 0;
+ addr += tmp;
+ len -= tmp;
+ }
+ len = (len + 15) >> 4;
+ }
+ i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
while (len--)
{
switch (cache)
@@ -301,36 +306,33 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
: : "a" (paddr));
break;
}
- addr += 16;
- if (len)
+ if (!--i && len)
{
- if ((addr & (PAGE_SIZE-1)) < 16)
+ addr += PAGE_SIZE;
+ i = PAGE_SIZE / 16;
+ /* Recompute physical address when crossing a page
+ boundary. */
+ for (;;)
{
- /* Recompute physical address when crossing a page
- boundary. */
- for (;;)
- {
- virt_to_phys_040 (addr, paddr, valid);
- if (valid)
- break;
- if (len <= PAGE_SIZE / 16)
- return 0;
- len -= (PAGE_SIZE - (addr & PAGE_MASK)) / 16;
- addr = (addr + PAGE_SIZE) & PAGE_MASK;
- }
+ if ((paddr = virt_to_phys_040(addr)))
+ break;
+ if (len <= i)
+ return 0;
+ len -= i;
+ addr += PAGE_SIZE;
}
- else
- paddr += 16;
}
+ else
+ paddr += 16;
}
break;
default:
case FLUSH_SCOPE_PAGE:
+ len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- virt_to_phys_040 (addr, paddr, valid);
- if (!valid)
+ if (!(paddr = virt_to_phys_040(addr)))
continue;
switch (cache)
{
@@ -363,21 +365,21 @@ cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
return 0;
}
-#define virt_to_phys_060(vaddr, paddr, valid) \
-{ \
+#define virt_to_phys_060(vaddr) \
+({ \
+ unsigned long paddr; \
__asm__ __volatile__ (".chip 68060\n\t" \
"plpar (%0)\n\t" \
".chip 68k" \
: "=a" (paddr) \
: "0" (vaddr)); \
- (valid) = 1; /* XXX */ \
-}
+ (paddr); /* XXX */ \
+})
static inline int
cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
{
- unsigned long paddr;
- int valid;
+ unsigned long paddr, i;
switch (scope)
{
@@ -407,19 +409,30 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
break;
case FLUSH_SCOPE_LINE:
- len >>= 4;
/* Find the physical address of the first mapped page in the
address range. */
- for (;;)
- {
- virt_to_phys_060 (addr, paddr, valid);
- if (valid)
- break;
- if (len <= PAGE_SIZE / 16)
- return 0;
- len -= (PAGE_SIZE - (addr & PAGE_MASK)) / 16;
- addr = (addr + PAGE_SIZE) & PAGE_MASK;
- }
+ len += addr & 15;
+ addr &= -16;
+ if (!(paddr = virt_to_phys_060(addr))) {
+ unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
+
+ if (len <= tmp)
+ return 0;
+ addr += tmp;
+ len -= tmp;
+ tmp = PAGE_SIZE;
+ for (;;)
+ {
+ if ((paddr = virt_to_phys_060(addr)))
+ break;
+ if (len <= tmp)
+ return 0;
+ addr += tmp;
+ len -= tmp;
+ }
+ }
+ len = (len + 15) >> 4;
+ i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
while (len--)
{
switch (cache)
@@ -447,36 +460,35 @@ cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
: : "a" (paddr));
break;
}
- addr += 16;
- if (len)
+ if (!--i && len)
{
- if ((addr & (PAGE_SIZE-1)) < 16)
- {
- /* Recompute the physical address when crossing a
- page boundary. */
- for (;;)
- {
- virt_to_phys_060 (addr, paddr, valid);
- if (valid)
- break;
- if (len <= PAGE_SIZE / 16)
- return 0;
- len -= (PAGE_SIZE - (addr & PAGE_MASK)) / 16;
- addr = (addr + PAGE_SIZE) & PAGE_MASK;
- }
- }
- else
- paddr += 16;
+ addr += PAGE_SIZE;
+ i = PAGE_SIZE / 16;
+ /* Recompute physical address when crossing a page
+ boundary. */
+ for (;;)
+ {
+ if ((paddr = virt_to_phys_060(addr)))
+ break;
+ if (len <= i)
+ return 0;
+ len -= i;
+ addr += PAGE_SIZE;
+ }
}
+ else
+ paddr += 16;
}
break;
default:
case FLUSH_SCOPE_PAGE:
+ len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
+ addr &= PAGE_MASK; /* Workaround for bug in some
+ revisions of the 68060 */
for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
{
- virt_to_phys_060 (addr, paddr, valid);
- if (!valid)
+ if (!(paddr = virt_to_phys_060(addr)))
continue;
switch (cache)
{
diff --git a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile
index dd834efd9..f632508f0 100644
--- a/arch/mips/boot/Makefile
+++ b/arch/mips/boot/Makefile
@@ -41,7 +41,6 @@ zdisk: zImage
fi
dep:
- $(CPP) -M *.[cS] > .depend
clean:
rm -f zImage zImage.tmp mkboot
diff --git a/arch/mips/config.in b/arch/mips/config.in
index 22aff787f..35903797a 100644
--- a/arch/mips/config.in
+++ b/arch/mips/config.in
@@ -84,7 +84,7 @@ bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
if [ "$CONFIG_SGI" != "y" ]; then
- tristate 'Parallel port support' CONFIG_PARPORT
+ tristate 'Parallel port support' CONFIG_PNP_PARPORT
fi
endmenu
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 082dc7520..a40178f36 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -1,4 +1,4 @@
-/* $Id: irixsig.c,v 1.3 1997/07/24 11:28:49 ralf Exp $
+/* $Id: irixsig.c,v 1.3 1997/07/29 03:04:27 ralf Exp $
* irixsig.c: WHEEE, IRIX signals! YOW, am I compatable or what?!?!
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -142,7 +142,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
if (!(signr = current->exit_code))
continue;
@@ -180,7 +180,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
continue;
@@ -679,7 +679,7 @@ repeat:
REMOVE_LINKS(p);
p->p_pptr = p->p_opptr;
SET_LINKS(p);
- notify_parent(p);
+ notify_parent(p, SIGCHLD);
} else
release(p);
goto end_waitsys;
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index e61911549..97a11abc4 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -488,7 +488,7 @@ asmlinkage void syscall_trace(void)
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
/*
* this isn't the same as continuing with a signal, but it will do
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 1c18ce912..34ed87fb6 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -4,7 +4,7 @@
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1994, 1995, 1996 Ralf Baechle
*
- * $Id: signal.c,v 1.3 1997/06/25 14:48:36 ralf Exp $
+ * $Id: signal.c,v 1.3 1997/06/25 20:08:49 ralf Exp $
*/
#include <linux/config.h>
#include <linux/sched.h>
@@ -292,7 +292,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
current->exit_code = signr;
current->state = TASK_STOPPED;
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
if (!(signr = current->exit_code))
continue;
@@ -332,7 +332,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
SA_NOCLDSTOP))
- notify_parent(current);
+ notify_parent(current, SIGCHLD);
schedule();
continue;
diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
index 66d66ce5b..fd1b39bca 100644
--- a/arch/mips/kernel/syscalls.h
+++ b/arch/mips/kernel/syscalls.h
@@ -7,7 +7,7 @@
*
* Copyright (C) 1995, 1996, 1997 by Ralf Baechle
*
- * $Id: syscalls.h,v 1.4 1997/06/25 20:07:40 ralf Exp $
+ * $Id: syscalls.h,v 1.5 1997/07/20 14:57:27 ralf Exp $
*/
/*
@@ -210,3 +210,5 @@ SYS(sys_poll, 3)
SYS(sys_nfsservctl, 3)
SYS(sys_setresgid, 3) /* 4190 */
SYS(sys_getresgid, 3)
+SYS(sys_setresgid, 3) /* 4190 */
+SYS(sys_getresgid, 3)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index e87e5084b..c1b672e76 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.4 1997/07/19 19:03:18 root Exp $
+/* $Id: sysirix.c,v 1.3 1997/07/20 15:32:25 ralf Exp $
* sysirix.c: IRIX system call emulation.
*
* Copyright (C) 1996 David S. Miller
@@ -751,6 +751,8 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
}
error = 0;
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
@@ -1514,6 +1516,8 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
error = 0;
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
@@ -1877,6 +1881,8 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
error = 0;
+dput_and_out:
+ dput(dentry);
out:
unlock_kernel();
return error;
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index cdbcacb43..b7ceea080 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -196,6 +196,8 @@ static void default_be_board_handler(struct pt_regs *regs)
/*
* Assume it would be too dangerous to continue ...
*/
+ printk ("BE HANDLER\n");
+ show_regs (regs);
force_sig(SIGBUS, current);
}
diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c
index 553508056..0c7f81877 100644
--- a/arch/mips/lib/dump_tlb.c
+++ b/arch/mips/lib/dump_tlb.c
@@ -16,12 +16,27 @@
#include <asm/page.h>
#include <asm/pgtable.h>
+static char *region_map [] = {
+ "u", "s", "k", "!"
+};
+
+static char *cache_map [] = {
+ "c/nc/wt/nwa,",
+ "c/nc/wt/wa, ",
+ "uncached, ",
+ "c/nc/wb, "
+ "unknown, ",
+ "unknown, ",
+ "unknown, ",
+ "unknown, "
+};
+
void
dump_tlb(int first, int last)
{
int i;
int wired;
- unsigned int pagemask;
+ unsigned int pagemask, c0, c1, r;
unsigned long long entryhi, entrylo0, entrylo1;
wired = read_32bit_cp0_register(CP0_WIRED);
@@ -48,14 +63,25 @@ dump_tlb(int first, int last)
/*
* Only print entries in use
*/
- printk("\nIndex: %2d %08x", i, pagemask);
-
- printk(" %08x %08x", (unsigned int)(entryhi >> 32),
- (unsigned int) entryhi);
- printk(" %08x %08x", (unsigned int)(entrylo0 >> 32),
- (unsigned int) entrylo0);
- printk(" %08x %08x", (unsigned int)(entrylo1 >> 32),
- (unsigned int) entrylo1);
+ printk("\nIndex: %2d pgmask=%08x ", i, pagemask);
+
+ r = entryhi >> 62;
+ c0 = (entrylo0 >> 3) & 7;
+ c1 = (entrylo1 >> 3) & 7;
+
+ printk("%s vpn2=%08x "
+ "[pfn=%06x c=%d d=%d v=%d g=%d]"
+ "[pfn=%06x c=%d d=%d v=%d g=%d]",
+ region_map [r], (entryhi >> 13) & 0xffffffff,
+ (entrylo0 >> 6) & 0xffffff, c0,
+ (entrylo0 & 4) ? 1 : 0,
+ (entrylo0 & 2) ? 1 : 0,
+ (entrylo0 & 1),
+ (entrylo1 >> 6) & 0xffffff, c1,
+ (entrylo1 & 4) ? 1 : 0,
+ (entrylo1 & 2) ? 1 : 0,
+ (entrylo1 & 1));
+
}
}
printk("\n");
diff --git a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c
index c00d63bc8..2b32ca455 100644
--- a/arch/mips/mm/r4xx0.c
+++ b/arch/mips/mm/r4xx0.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
*
- * $Id: r4xx0.c,v 1.4 1997/07/01 09:00:50 ralf Exp $
+ * $Id: r4xx0.c,v 1.5 1997/07/29 22:54:52 tsbogend Exp $
*/
#include <linux/config.h>
@@ -1943,7 +1943,7 @@ static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
int oldpid, newpid, idx;
#ifdef DEBUG_TLB
- printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
+ printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
#endif
newpid = (vma->vm_mm->context & 0xff);
page &= (PAGE_MASK << 1);
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index af577c5ae..ac2719977 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -25,61 +25,62 @@ HOSTCC = gcc
CC = gcc$(SUFFIX)
CFLAGSINC = -D__KERNEL__ -I$(TOPDIR)/include -D__powerpc__
CFLAGS = $(CFLAGSINC) \
- -Wstrict-prototypes \
- -fomit-frame-pointer \
+ -Wstrict-prototypes -fomit-frame-pointer \
-fno-builtin \
- -finhibit-size-directive -fno-strength-reduce\
- -O2 -fsigned-char -pipe -mstring -mmultiple
+ -finhibit-size-directive \
+ -O2 -fsigned-char -pipe -ffixed-r2 -mstring -mmultiple -msoft-float
+# -fverbose-asm
CPP = $(CC) -E $(CFLAGS)
AR = ar$(SUFFIX)
RANLIB = ranlib$(SUFFIX)
STRIP = strip$(SUFFIX)
NM = nm$(SUFFIX)
-ifdef CONFIG_603
-CFLAGS := $(CFLAGS) -mcpu=603 -DCPU=603
+ifdef CONFIG_601
+CFLAGS := $(CFLAGS) -mcpu=601 -DCPU=601
endif
-ifdef CONFIG_603e
-CFLAGS := $(CFLAGS) -mcpu=603e -DCPU=603e
+ifdef CONFIG_603
+CFLAGS := $(CFLAGS) -mcpu=603 -DCPU=603
endif
ifdef CONFIG_604
CFLAGS := $(CFLAGS) -mcpu=604 -DCPU=604
endif
-#
-# NFS_ROOT_NAME specifies the default name of the directory to mount
-# as root via NFS, if the kernel does not get the "root=" option from
-# the boot loader. The "%s" will be replaced by the IP-number of the
-# local system.
-#
-NFS_ROOT = -DNFS_ROOT="\"/joplin/ppc/root\""
-
HEAD := arch/ppc/kernel/head.o
ARCH_SUBDIRS = arch/ppc/kernel arch/ppc/mm arch/ppc/lib
SUBDIRS := $(SUBDIRS) $(ARCH_SUBDIRS)
ARCHIVES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(ARCHIVES)
-
+CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES)
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
-netboot: vmlinux
+checks:
+ @$(MAKE) -C arch/$(ARCH)/kernel checks
+
+netboot: checks vmlinux
@$(MAKEBOOT) netboot
-znetboot: vmlinux
+znetboot: checks vmlinux
@$(MAKEBOOT) znetboot
-zImage: vmlinux
+#rcpboot: checks vmlinux
+# @$(MAKEBOOT) rcpboot
+
+zImage: checks vmlinux
@$(MAKEBOOT) zImage
-floppy: vmlinux
+floppy: checks vmlinux
@$(MAKEBOOT) floppy
-install: vmlinux
+install: checks vmlinux
@$(MAKEBOOT) install
+vmlinux.coff : checks vmlinux
+ $(MAKE) -C arch/ppc/coffboot/ vmlinux.coff
+
arch/ppc/kernel: dummy
$(MAKE) linuxsubdirs SUBDIRS=arch/ppc/kernel
@@ -89,12 +90,24 @@ arch/ppc/mm: dummy
arch/ppc/lib: dummy
$(MAKE) linuxsubdirs SUBDIRS=arch/ppc/lib
+diffs:
+ arch/ppc/mkdiff
+
+tar:
+ arch/ppc/mktar
archclean:
- rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h TAGS
+ rm -f arch/ppc/kernel/mk_defs arch/ppc/kernel/ppc_defs.h arch/ppc/kernel/checks TAGS
+ rm -f `find arch/ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print`
+ rm -f `find include/asm-ppc/ \( -name '*.[oas]' -o -name '*~' -o -name '#*#' \) -print`
@$(MAKEBOOT) clean
archdep:
+ $(MAKE) -C arch/ppc/boot fastdep
+ $(MAKE) -C arch/ppc/kernel fastdep
+ $(MAKE) -C arch/ppc/mm fastdep
+ $(MAKE) -C arch/ppc/lib fastdep
+
+tags :
+ etags arch/ppc/*/*.c arch/ppc/*/*.S include/asm/* */*.c
-corttags :
- etags arch/ppc/*/*.c include/asm/* */*.c drivers/*/*.c net/*.c
diff --git a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile
index 7b4ed71f6..5dcac750e 100644
--- a/arch/ppc/boot/Makefile
+++ b/arch/ppc/boot/Makefile
@@ -7,6 +7,7 @@
#
# Copyright (C) 1994 by Linus Torvalds
# Adapted for PowerPC by Gary Thomas
+# modified by Cort (cort@cs.nmt.edu)
#
.c.s:
@@ -22,7 +23,7 @@
ZLINKFLAGS = -T ../ld.script -Ttext 0x00800000
-GZIP_FLAGS = -9
+GZIP_FLAGS = -v9
SYSTEM = $(TOPDIR)/vmlinux
@@ -32,49 +33,51 @@ CFLAGS = -O2 -DSTDC_HEADERS -I$(TOPDIR)/include
all: $(TOPDIR)/zImage
-mkboot : cortstrip.c
- $(HOSTCC) $(CFLAGSINC) -Wl,-static -o mkboot cortstrip.c
+mkprep : mkprep.c
+ $(HOSTCC) $(CFLAGSINC) -o mkprep mkprep.c
+
+find_name : find_name.c
+ $(HOSTCC) $(CFLAGSINC) -o find_name find_name.c
mk_type41: mk_type41.c
- $(HOSTCC) $(CFLAGSINC) -Wl,-static -o mk_type41 mk_type41.c
+ $(HOSTCC) $(CFLAGSINC) -o mk_type41 mk_type41.c
+
+piggyback: piggyback.c
+ $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c
-floppy: zImage $(TOPDIR)/vmlinux
+floppy: $(TOPDIR)/vmlinux zImage
dd if=$(TOPDIR)/zImage of=/dev/fd0H1440 bs=64b
-netboot : $(TOPDIR)/vmlinux mkboot
- mkboot $(TOPDIR)/vmlinux $(TOPDIR)/netboot
-# rcp $(TOPDIR)/netboot charon:/usr/tftpboot/vmlinux
+netboot : $(TOPDIR)/vmlinux mkprep
+ mkprep $(TOPDIR)/vmlinux $(TOPDIR)/netboot
+
+znetboot : zvmlinux mkprep
+ mkprep zvmlinux $(TOPDIR)/znetboot
+ cp $(TOPDIR)/znetboot /usr/local/tftpboot/vmlinux
-znetboot : mkboot zvmlinux
- mkboot zvmlinux $(TOPDIR)/znetboot
+rcpboot : znetboot
rcp $(TOPDIR)/znetboot charon:/usr/tftpboot/vmlinux
-zImage: mk_type41 zvmlinux
-# make znetboot ourselves since using the normal dep
-# will rcp it -- Cort
- mkboot zvmlinux $(TOPDIR)/znetboot
- mk_type41 $(TOPDIR)/znetboot $(TOPDIR)/zImage
+zImage: zvmlinux mkprep
+ mkprep -pbp zvmlinux $(TOPDIR)/zImage
install: zImage
dd if=$(TOPDIR)/zImage of=/dev/sda4
ln -s /dev/sda4 $(INSTALL_PATH)/vmlinuz
cp $(TOPDIR)/System.map $(INSTALL_PATH)/
-zvmlinux: $(OBJECTS) $(SYSTEM) piggyback netboot $(TOPDIR)/vmlinux
- gzip ${GZIP_FLAGS} <$(TOPDIR)/netboot | ./piggyback | $(AS) -o piggy.o
+zvmlinux: $(OBJECTS) $(SYSTEM) mkprep find_name
+ mkprep $(TOPDIR)/vmlinux -|gzip ${GZIP_FLAGS}|mkprep -asm - -|$(AS) -o piggy.o
$(LD) $(ZLINKFLAGS) -o zvmlinux $(OBJECTS) piggy.o
- rm -f piggy.o xx_boot
-
-head.o: head.s
-
-head.s: head.S $(TOPDIR)/include/linux/tasks.h
- $(CPP) -traditional head.S -o head.s
-
-piggyback: piggyback.c
- $(HOSTCC) $(CFLAGS) -o piggyback piggyback.c
+ rm -f piggy.o
clean:
- rm -f piggyback zvmlinux mk_type41 mkprep mkboot
+ rm -f piggyback zvmlinux mk_type41 mkprep mkboot find_name
rm -f $(TOPDIR)/{zImage,znetboot,netboot}
+fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
dep:
+ $(CPP) -M *.S *.c > .depend
+
diff --git a/arch/ppc/boot/cortstrip.c b/arch/ppc/boot/cortstrip.c
index 78856d2bb..e69de29bb 100644
--- a/arch/ppc/boot/cortstrip.c
+++ b/arch/ppc/boot/cortstrip.c
@@ -1,73 +0,0 @@
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-/* amount to skip */
-#define PLACE 65536
-
-/* size of read buffer */
-#define SIZE 0x100000
-
-/* crude program to strip the elf header to make a bootable
- image via tftp
- */
-
-
-int main(int argc, char **argv )
-{
- int fd, fdo;
- unsigned char data[SIZE];
- int i, n, skip;
-
-#if 0
- if ( argc != 3 )
- {
- fprintf(stderr,"%s infile outfile\n", argv[0]);
- exit(-1);
- }
-#endif
-
-
- fd = open(argv[1], O_RDONLY);
- if ( fd == -1 )
- {
- fprintf(stderr,"Couldn't open %s\n", argv[1]);
- perror("open()");
- exit(-1);
- }
-
- fdo = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC,0755);
- if ( fdo == -1 )
- {
- fprintf(stderr,"Couldn't open %s\n", argv[2]);
- perror("open()");
- exit(-1);
- }
-
-#if 0
- skip = atoi(argv[3]);
-#else
- skip = PLACE;
-#endif
- i = lseek(fd, skip, SEEK_SET);
- /*printf("lseek'd %d bytes\n", i);*/
- if ( i == -1 )
- {
- perror("lseek()");
- }
-
- while ( (n = read(fd, data, SIZE)) > 0 )
- {
- /*printf("Read %d bytes\n", n);*/
- i = write(fdo, data, n);
- /*printf("Wrote %d bytes\n", i); */
- }
-
-
- close(fdo);
- close(fd);
- return(0);
-}
-
-
diff --git a/arch/ppc/boot/gzip.h b/arch/ppc/boot/gzip.h
index 2f738b945..9d8e54a4b 100644
--- a/arch/ppc/boot/gzip.h
+++ b/arch/ppc/boot/gzip.h
@@ -271,7 +271,7 @@ extern int fill_inbuf OF((void));
extern void flush_outbuf OF((void));
extern void flush_window OF((void));
extern char *strlwr OF((char *s));
-extern char *basename OF((char *fname));
+/*extern char *basename OF((char *fname));*/
extern char *add_envopt OF((int *argcp, char ***argvp, char *env));
extern void error OF((char *m));
extern void warn OF((char *a, char *b));
diff --git a/arch/ppc/boot/head.S b/arch/ppc/boot/head.S
index 35dacd514..6b25cb157 100644
--- a/arch/ppc/boot/head.S
+++ b/arch/ppc/boot/head.S
@@ -1,5 +1,6 @@
#include "../kernel/ppc_defs.h"
#include "../kernel/ppc_asm.tmpl"
+#include <asm/processor.h>
.text
diff --git a/arch/ppc/boot/inflate.c b/arch/ppc/boot/inflate.c
index 848fef6ae..1beecacdb 100644
--- a/arch/ppc/boot/inflate.c
+++ b/arch/ppc/boot/inflate.c
@@ -9,7 +9,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: inflate.c,v 0.10 1993/02/04 13:21:06 jloup Exp $";
+static char rcsid[] = "$Id: inflate.c,v 1.1.1.1 1997/02/25 05:18:11 cort Exp $";
#endif
#include "gzip.h"
diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c
index 0b1638562..a983ea106 100644
--- a/arch/ppc/boot/misc.c
+++ b/arch/ppc/boot/misc.c
@@ -327,7 +327,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
_put_MSR(_get_MSR() & ~0x0030);
vga_init(0xC0000000);
- clear_screen();
+ /*clear_screen();*/
output_ptr = 0;
@@ -373,93 +373,6 @@ show_residual_data(RESIDUAL *res)
#endif
}
-#if 0
-verify_ram()
-{
- unsigned long loc;
- puts("Clearing memory:");
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- *(unsigned long *)loc = 0x0;
- }
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- if (*(unsigned long *)loc != 0x0)
- {
- puts(" - failed at ");
- puthex(loc);
- puts(": ");
- puthex(*(unsigned long *)loc);
- while (1);
- }
- }
- puts("0");
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- *(unsigned long *)loc = 0xFFFFFFFF;
- }
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- if (*(unsigned long *)loc != 0xFFFFFFFF)
- {
- puts(" - failed at ");
- puthex(loc);
- puts(": ");
- puthex(*(unsigned long *)loc);
- while (1);
- }
- }
- puts("1");
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- *(unsigned long *)loc = loc;
- }
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- if (*(unsigned long *)loc != loc)
- {
- puts(" - failed at ");
- puthex(loc);
- puts(": ");
- puthex(*(unsigned long *)loc);
- while (1);
- }
- }
- puts("?");
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- *(unsigned long *)loc = 0xDEADB00B;
- }
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- if (*(unsigned long *)loc != 0xDEADB00B)
- {
- puts(" - failed at ");
- puthex(loc);
- puts(": ");
- puthex(*(unsigned long *)loc);
- while (1);
- }
- }
- puts(">");
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- *(unsigned long *)loc = 0x0;
- }
- for (loc = 0; loc <= 0x400000; loc += 4);
- {
- if (*(unsigned long *)loc != 0x0)
- {
- puts(" - failed at ");
- puthex(loc);
- puts(": ");
- puthex(*(unsigned long *)loc);
- while (1);
- }
- }
- puts("\n");
-}
-
do_cksum(unsigned long loc)
{
unsigned int ptr, cksum;
@@ -582,7 +495,6 @@ test_data(unsigned long load_addr)
}
return (errors == 0);
}
-#endif
void puthex(unsigned long val)
{
diff --git a/arch/ppc/boot/mk_type41.c b/arch/ppc/boot/mk_type41.c
index 4e2a7b3aa..e69de29bb 100644
--- a/arch/ppc/boot/mk_type41.c
+++ b/arch/ppc/boot/mk_type41.c
@@ -1,208 +0,0 @@
-/*
- * This program will make a type 0x41 load image from an
- * executable file. Note: assumes that the executable has
- * already been "flattened" by 'mkboot'.
- *
- * usage: mk_type41 flat-file image
- */
-
-#include <stdio.h>
-#include <errno.h>
-#ifdef linux
-#include <asm/stat.h>
-#else
-#include <sys/stat.h>
-#endif
-
-_LE(long val, unsigned char *le)
-{
- le[0] = val;
- le[1] = val >> 8;
- le[2] = val >> 16;
- le[3] = val >> 24;
-}
-
-main(int argc, char *argv[])
-{
- int in_fd, out_fd, len, size;
- struct stat info;
- char buf[8192];
- struct hdr
- {
- unsigned long entry_point;
- unsigned long image_length;
- } hdr;
- if (argc != 3)
- {
- fprintf(stderr, "usage: mk_type41 <boot-file> <image>\n");
- exit(1);
- }
- if ((in_fd = open(argv[1], 0)) < 0)
- {
- fprintf(stderr, "Can't open input file: '%s': %s\n", argv[1], strerror(errno));
- exit(2);
- }
- if ((out_fd = creat(argv[2], 0666)) < 0)
- {
- fprintf(stderr, "Can't create output file: '%s': %s\n", argv[2], strerror(errno));
- exit(2);
- }
- if (fstat(in_fd, &info) < 0)
- {
- fprintf(stderr, "Can't get info on input file: %s\n", strerror(errno));
- exit(4);
- }
- write_prep_boot_partition(out_fd);
- _LE(0x400, &hdr.entry_point);
- _LE(info.st_size+0x400, &hdr.image_length);
- lseek(out_fd, 0x200, 0);
- if (write(out_fd, &hdr, sizeof(hdr)) != sizeof(hdr))
- {
- fprintf(stderr, "Can't write output file: %s\n", strerror(errno));
- exit(5);
- }
- lseek(out_fd, 0x400, 0);
- while ((len = read(in_fd, buf, sizeof(buf))) > 0)
- {
- if (write(out_fd, buf, len) != len)
- {
- fprintf(stderr, "Can't write output file: %s\n", strerror(errno));
- exit(5);
- }
- }
- if (len < 0)
- {
- fprintf(stderr, "Can't read input file: %s\n", strerror(errno));
- exit(6);
- }
- close(in_fd);
- close(out_fd);
-}
-
-/* Adapted from IBM Naked Application Package (NAP) */
-
-#define Align(value,boundary) \
- (((value) + (boundary) - 1) & ~((boundary) - 1))
-
-#define HiByte(word) ((word_t)(word) >> 8)
-#define LoByte(word) ((word_t)(word) & 0xFF)
-
-#define HiWord(dword) ((dword_t)(dword) >> 16)
-#define LoWord(dword) ((dword_t)(dword) & 0xFFFF)
-
-/*
- * Little-endian stuff
- */
-#define LeWord(word) \
- (((word_t)(word) >> 8) | ((word_t)(word) << 8))
-
-#define LeDword(dword) \
- (LeWord(LoWord(dword)) << 16) | LeWord(HiWord(dword))
-
-#define PcDword(dword) \
- (LeWord(LoWord(dword)) << 16) | LeWord(HiWord(dword))
-
-
-typedef unsigned long dword_t;
-typedef unsigned short word_t;
-typedef unsigned char byte_t;
-typedef byte_t block_t[512];
-typedef byte_t page_t[4096];
-
-/*
- * Partition table entry
- * - from the PReP spec
- */
-typedef struct partition_entry {
- byte_t boot_indicator;
- byte_t starting_head;
- byte_t starting_sector;
- byte_t starting_cylinder;
-
- byte_t system_indicator;
- byte_t ending_head;
- byte_t ending_sector;
- byte_t ending_cylinder;
-
- dword_t beginning_sector;
- dword_t number_of_sectors;
-} partition_entry_t;
-
-#define BootActive 0x80
-#define SystemPrep 0x41
-
-
-/*
- * Writes the "boot record", which contains the partition table, to the
- * diskette, followed by the dummy PC boot block and load image descriptor
- * block. It returns the number of bytes it has written to the load
- * image.
- *
- * The boot record is the first block of the diskette and identifies the
- * "PReP" partition. The "PReP" partition contains the "load image" starting
- * at offset zero within the partition. The first block of the load image is
- * a dummy PC boot block. The second block is the "load image descriptor"
- * which contains the size of the load image and the entry point into the
- * image. The actual boot image starts at offset 1024 bytes (third sector)
- * in the partition.
- */
-void
-write_prep_boot_partition(int out_fd)
-{
- block_t block;
- partition_entry_t *pe = (partition_entry_t *)&block[0x1BE];
- dword_t *entry = (dword_t *)&block[0];
- dword_t *length = (dword_t *)&block[4];
-
- bzero( &block, sizeof block );
-
- /*
- * Magic marker
- */
- block[510] = 0x55;
- block[511] = 0xAA;
-
- /*
- * Build a "PReP" partition table entry in the boot record
- * - "PReP" may only look at the system_indicator
- */
- pe->boot_indicator = BootActive;
- pe->system_indicator = SystemPrep;
-
- /*
- * The first block of the diskette is used by this "boot record" which
- * actually contains the partition table. (The first block of the
- * partition contains the boot image, but I digress...) We'll set up
- * one partition on the diskette and it shall contain the rest of the
- * diskette.
- */
- pe->starting_head = 0; /* zero-based */
- pe->starting_sector = 2; /* one-based */
- pe->starting_cylinder = 0; /* zero-based */
-
- pe->ending_head = 1; /* assumes two heads */
- pe->ending_sector = 18; /* assumes 18 sectors/track */
- pe->ending_cylinder = 79; /* assumes 80 cylinders/diskette */
-
- /*
- * The "PReP" software ignores the above fields and just looks at
- * the next two.
- * - size of the diskette is (assumed to be)
- * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
- * - unlike the above sector numbers, the beginning sector is zero-based!
- */
-#if 0
- pe->beginning_sector = LeDword(1);
-#else
- /* This has to be 0 on the PowerStack? */
- pe->beginning_sector = LeDword(0);
-#endif
- pe->number_of_sectors = LeDword(2*18*80-1);
-
- /*
- * Write the partition table
- */
- lseek( out_fd, 0, 0 );
- write( out_fd, block, sizeof block );
-}
-
diff --git a/arch/ppc/boot/mkprep.c b/arch/ppc/boot/mkprep.c
index a79ad98f2..417334670 100644
--- a/arch/ppc/boot/mkprep.c
+++ b/arch/ppc/boot/mkprep.c
@@ -1,19 +1,54 @@
/*
- * This program will make a type 0x41 load image from an
- * executable file. Note: assumes that the executable has
- * already been "flattened" by 'mkboot'.
- *
- * usage: mk_type41 flat-file image
+ * Makes a prep bootable image which can be dd'd onto
+ * a disk device to make a bootdisk. Will take
+ * as input a elf executable, strip off the header
+ * and write out a boot image as:
+ * 1) default - strips elf header
+ * suitable as a network boot image
+ * 2) -pbp - strips elf header and writes out prep boot partition image
+ * cat or dd onto disk for booting
+ * 3) -asm - strips elf header and writes out as asm data
+ * useful for generating data for a compressed image
+ * -- Cort
*/
-#include <stdio.h>
-#include <errno.h>
#ifdef linux
+#include <linux/types.h>
#include <asm/stat.h>
+/*#include <asm/byteorder.h>*/ /* the byte swap funcs don't work here -- Cort */
#else
+#include <unistd.h>
#include <sys/stat.h>
#endif
-#include <asm/byteorder.h> /* use same as kernel -- Cort */
+
+#include <stdio.h>
+#include <errno.h>
+
+#define cpu_to_le32(x) le32_to_cpu((x))
+unsigned long le32_to_cpu(unsigned long x)
+{
+ return (((x & 0x000000ffU) << 24) |
+ ((x & 0x0000ff00U) << 8) |
+ ((x & 0x00ff0000U) >> 8) |
+ ((x & 0xff000000U) >> 24));
+}
+
+
+#define cpu_to_le16(x) le16_to_cpu((x))
+unsigned short le16_to_cpu(unsigned short x)
+{
+ return (((x & 0x00ff) << 8) |
+ ((x & 0xff00) >> 8));
+}
+
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be16(x) (x)
+#define be16_to_cpu(x) (x)
+
+/* size of read buffer */
+#define SIZE 0x1000
+
typedef unsigned long dword_t;
typedef unsigned short word_t;
@@ -21,119 +56,239 @@ typedef unsigned char byte_t;
typedef byte_t block_t[512];
typedef byte_t page_t[4096];
-_LE(long val, unsigned char *le)
-{
- le[0] = val;
- le[1] = val >> 8;
- le[2] = val >> 16;
- le[3] = val >> 24;
-}
/*
* Partition table entry
* - from the PReP spec
*/
typedef struct partition_entry {
- byte_t boot_indicator;
- byte_t starting_head;
- byte_t starting_sector;
- byte_t starting_cylinder;
-
- byte_t system_indicator;
- byte_t ending_head;
- byte_t ending_sector;
- byte_t ending_cylinder;
-
- dword_t beginning_sector;
- dword_t number_of_sectors;
+ byte_t boot_indicator;
+ byte_t starting_head;
+ byte_t starting_sector;
+ byte_t starting_cylinder;
+
+ byte_t system_indicator;
+ byte_t ending_head;
+ byte_t ending_sector;
+ byte_t ending_cylinder;
+
+ dword_t beginning_sector;
+ dword_t number_of_sectors;
} partition_entry_t;
#define BootActive 0x80
#define SystemPrep 0x41
+void copy_image(int , int);
+void write_prep_partition(int , int );
+void write_asm_data( int in, int out );
+
+unsigned int elfhdr_size = 65536;
int main(int argc, char *argv[])
{
- struct stat info;
- char buf[8192];
- int in_fd, out_fd,len;
+ int in_fd, out_fd;
+ int argptr = 1;
+ unsigned int prep = 0;
+ unsigned int asmoutput = 0;
+
+ if ( (argc < 3) || (argc > 4) )
+ {
+ fprintf(stderr, "usage: %s [-pbp] [-asm] <boot-file> <image>\n",argv[0]);
+ exit(-1);
+ }
+
+ /* needs to handle args more elegantly -- but this is a small/simple program */
+
+ /* check for -pbp */
+ if ( !strcmp( argv[argptr], "-pbp" ) )
+ {
+ prep = 1;
+ argptr++;
+ }
+
+ /* check for -asm */
+ if ( !strcmp( argv[argptr], "-asm" ) )
+ {
+ asmoutput = 1;
+ argptr++;
+ }
+
+ /* input file */
+ if ( !strcmp( argv[argptr], "-" ) )
+ in_fd = 0; /* stdin */
+ else
+ if ((in_fd = open( argv[argptr] , 0)) < 0)
+ exit(-1);
+ argptr++;
+
+ /* output file */
+ if ( !strcmp( argv[argptr], "-" ) )
+ out_fd = 1; /* stdout */
+ else
+ if ((out_fd = creat( argv[argptr] , 0755)) < 0)
+ exit(-1);
+ argptr++;
+
+ /* skip elf header in input file */
+ lseek(in_fd, elfhdr_size, SEEK_SET);
+
+ /* write prep partition if necessary */
+ if ( prep )
+ write_prep_partition( in_fd, out_fd );
+
+ /* write input image to bootimage */
+ if ( asmoutput )
+ write_asm_data( in_fd, out_fd );
+ else
+ copy_image(in_fd, out_fd);
+
+ return 0;
+}
+
+void write_prep_partition(int in, int out)
+{
unsigned char block[512];
partition_entry_t *pe = (partition_entry_t *)&block[0x1BE];
- dword_t *entry = (dword_t *)&block[0x50];
- dword_t *length = (dword_t *)&block[0x51];
+ dword_t *entry = (dword_t *)&block[0];
+ dword_t *length = (dword_t *)&block[sizeof(long)];
+ struct stat info;
- if (argc != 3)
- {
- fprintf(stderr, "usage: mk_type41 <boot-file> <image>\n");
- exit(1);
- }
- if ((in_fd = open(argv[1], 0)) < 0)
- {
- exit(2);
- }
- if ((out_fd = creat(argv[2], 0755)) < 0)
- {
- exit(2);
- }
+ if (fstat(in, &info) < 0)
+ {
+ fprintf(stderr,"info failed\n");
+ exit(-1);
+ }
+
+ bzero( block, sizeof block );
- bzero( &block, sizeof block );
-
+
+ /* set entry point and boot image size */
+ *entry = cpu_to_le32(0x400);
+ /* need use size - elfheader? */
+ *length = cpu_to_le32(info.st_size+0x400);
/*
- * Magic marker
+ * Writes the "boot record", which contains the partition table, to the
+ * diskette, followed by the dummy PC boot block and load image descriptor
+ * block. It returns the number of bytes it has written to the load
+ * image.
+ *
+ * The boot record is the first block of the diskette and identifies the
+ * "PReP" partition. The "PReP" partition contains the "load image" starting
+ * at offset zero within the partition. The first block of the load image is
+ * a dummy PC boot block. The second block is the "load image descriptor"
+ * which contains the size of the load image and the entry point into the
+ * image. The actual boot image starts at offset 1024 bytes (third sector)
+ * in the partition.
*/
+
+ /* sets magic number for msdos partition (used by linux) */
block[510] = 0x55;
block[511] = 0xAA;
+ /*
+ * Build a "PReP" partition table entry in the boot record
+ * - "PReP" may only look at the system_indicator
+ */
pe->boot_indicator = BootActive;
pe->system_indicator = SystemPrep;
- pe->starting_head = 0; /* zero-based */
- pe->starting_sector = 2; /* one-based */
- pe->starting_cylinder = 0; /* zero-based */
-
- pe->ending_head = 1; /* assumes two heads */
- pe->ending_sector = 18; /* assumes 18 sectors/track */
- pe->ending_cylinder = 79; /* assumes 80 cylinders/diskette */
+ /*
+ * The first block of the diskette is used by this "boot record" which
+ * actually contains the partition table. (The first block of the
+ * partition contains the boot image, but I digress...) We'll set up
+ * one partition on the diskette and it shall contain the rest of the
+ * diskette.
+ */
+ pe->starting_head = 0; /* zero-based */
+ pe->starting_sector = 2; /* one-based */
+ pe->starting_cylinder = 0; /* zero-based */
+ pe->ending_head = 1; /* assumes two heads */
+ pe->ending_sector = 18; /* assumes 18 sectors/track */
+ pe->ending_cylinder = 79; /* assumes 80 cylinders/diskette */
+ /*
+ * The "PReP" software ignores the above fields and just looks at
+ * the next two.
+ * - size of the diskette is (assumed to be)
+ * (2 tracks/cylinder)(18 sectors/tracks)(80 cylinders/diskette)
+ * - unlike the above sector numbers, the beginning sector is zero-based!
+ */
#if 0
-#if 0
- pe->beginning_sector = LeDword(1);
+ pe->beginning_sector = cpu_to_le32(1);
#else
- /* This has to be 0 on the PowerStack? */
- pe->beginning_sector = LeDword(0);
-#endif
- pe->number_of_sectors = LeDword(2*18*80-1);
-#endif
+ /* This has to be 0 on the PowerStack? */
+ pe->beginning_sector = cpu_to_le32(0);
+#endif
+/*pe->number_of_sectors = cpu_to_le32(2*18*80-1);*/
+
+ write( out, block, sizeof(block) );
+ write( out, entry, sizeof(*entry) );
+ write( out, length, sizeof(*length) );
+ /* set file position to 2nd sector where image will be written */
+ lseek( out, 0x400, SEEK_SET );
+}
+
+
+
+void
+copy_image(int in, int out)
+{
+ char buf[SIZE];
+ int n;
+
+ while ( (n = read(in, buf, SIZE)) > 0 )
+ write(out, buf, n);
+}
+
+
+void
+write_asm_data( int in, int out )
+{
+ int i, cnt, pos, len;
+ unsigned int cksum, val;
+ unsigned char *lp;
+ unsigned char buf[SIZE];
+ unsigned char str[256];
- if (fstat(in_fd, &info) < 0)
+ write( out, "\t.data\n\t.globl input_data\ninput_data:\n",
+ strlen( "\t.data\n\t.globl input_data\ninput_data:\n" ) );
+ pos = 0;
+ cksum = 0;
+ while ((len = read(in, buf, sizeof(buf))) > 0)
+ {
+ cnt = 0;
+ lp = (unsigned char *)buf;
+ len = (len + 3) & ~3; /* Round up to longwords */
+ for (i = 0; i < len; i += 4)
{
- exit(4);
+ if (cnt == 0)
+ {
+ write( out, "\t.long\t", strlen( "\t.long\t" ) );
+ }
+ sprintf( str, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
+ write( out, str, strlen(str) );
+ val = *(unsigned long *)lp;
+ cksum ^= val;
+ lp += 4;
+ if (++cnt == 4)
+ {
+ cnt = 0;
+ sprintf( str, " # %x \n", pos+i-12);
+ write( out, str, strlen(str) );
+ } else
+ {
+ write( out, ",", 1 );
+ }
}
- /* begin execution at 0x400 */
- _LE(0x400,(unsigned char *)entry);
- _LE(info.st_size+0x400,length);
-
- lseek( out_fd, 0, 0 );
- /* write out 1st block */
- write( out_fd, block, sizeof block );
-
- /* copy image */
-#if 1
- lseek(out_fd, 0x400, 0);
- while ((len = read(in_fd, buf, sizeof(buf))) > 0)
- {
- if (write(out_fd, buf, len) != len)
- {
- exit(5);
- }
- }
- if (len < 0)
- {
- exit(6);
- }
- close(in_fd);
- close(out_fd);
-#endif
- return 0;
-}
+ if (cnt)
+ {
+ write( out, "0\n", 2 );
+ }
+ pos += len;
+ }
+ sprintf(str, "\t.globl input_len\ninput_len:\t.long\t0x%x\n", pos);
+ write( out, str, strlen(str) );
+ fprintf(stderr, "cksum = %x\n", cksum);
+}
diff --git a/arch/ppc/boot/piggyback.c b/arch/ppc/boot/piggyback.c
index ca9fc2957..e69de29bb 100644
--- a/arch/ppc/boot/piggyback.c
+++ b/arch/ppc/boot/piggyback.c
@@ -1,64 +0,0 @@
-#include <stdio.h>
-
-extern long ce_exec_config[];
-
-main(int argc, char *argv[])
-{
- int i, cnt, pos, len;
- unsigned int cksum, val;
- unsigned char *lp;
- unsigned char buf[8192];
- if (argc != 1)
- {
- fprintf(stderr, "usage: %s <in-file >out-file\n", argv[0]);
- exit(1);
- }
- fprintf(stdout, "#\n");
- fprintf(stdout, "# Miscellaneous data structures:\n");
- fprintf(stdout, "# WARNING - this file is automatically generated!\n");
- fprintf(stdout, "#\n");
- fprintf(stdout, "\n");
- fprintf(stdout, "\t.data\n");
- fprintf(stdout, "\t.globl input_data\n");
- fprintf(stdout, "input_data:\n");
- pos = 0;
- cksum = 0;
- while ((len = read(0, buf, sizeof(buf))) > 0)
- {
- cnt = 0;
- lp = (unsigned char *)buf;
- len = (len + 3) & ~3; /* Round up to longwords */
- for (i = 0; i < len; i += 4)
- {
- if (cnt == 0)
- {
- fprintf(stdout, "\t.long\t");
- }
- fprintf(stdout, "0x%02X%02X%02X%02X", lp[0], lp[1], lp[2], lp[3]);
- val = *(unsigned long *)lp;
- cksum ^= val;
- lp += 4;
- if (++cnt == 4)
- {
- cnt = 0;
- fprintf(stdout, " # %x \n", pos+i-12);
- fflush(stdout);
- } else
- {
- fprintf(stdout, ",");
- }
- }
- if (cnt)
- {
- fprintf(stdout, "0\n");
- }
- pos += len;
- }
- fprintf(stdout, "\t.globl input_len\n");
- fprintf(stdout, "input_len:\t.long\t0x%x\n", pos);
- fflush(stdout);
- fclose(stdout);
- fprintf(stderr, "cksum = %x\n", cksum);
- exit(0);
-}
-
diff --git a/arch/ppc/boot/unzip.c b/arch/ppc/boot/unzip.c
index 0c660adcf..fcebd9dd8 100644
--- a/arch/ppc/boot/unzip.c
+++ b/arch/ppc/boot/unzip.c
@@ -17,7 +17,7 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: unzip.c,v 0.9 1993/02/10 16:07:22 jloup Exp $";
+static char rcsid[] = "$Id: unzip.c,v 1.1.1.1 1997/02/25 05:18:11 cort Exp $";
#endif
#include "gzip.h"
diff --git a/arch/ppc/boot/vreset.c b/arch/ppc/boot/vreset.c
index 7da3670c8..3bc3936c6 100644
--- a/arch/ppc/boot/vreset.c
+++ b/arch/ppc/boot/vreset.c
@@ -7,6 +7,864 @@
* Steve Sellgren
* San Francisco Indigo Company
* sfindigo!sellgren@uunet.uu.net
+ *
+ * Original concept by:
+ * Gary Thomas <gdt@linuxppc.org>
+ * Adapted for Moto boxes by:
+ * Pat Kane & Mark Scott, 1996
+ * Adapted for IBM portables by:
+ * Takeshi Ishimoto
+ * Multi-console support:
+ * Terje Malmedal <terje.malmedal@usit.uio.no>
+ */
+
+#include "iso_font.h"
+#include <linux/delay.h>
+
+extern char *vidmem;
+extern int lines, cols;
+/* estimate for delay */
+unsigned long loops_per_sec = 50000000;;
+/*
+ * VGA Register
+ */
+struct VgaRegs
+{
+ unsigned short io_port;
+ unsigned char io_index;
+ unsigned char io_value;
+};
+
+/*
+ * Default console text mode registers used to reset
+ * graphics adapter.
+ */
+#define NREGS 54
+#define ENDMK 0xFFFF /* End marker */
+
+#define S3Vendor 0x5333
+#define CirrusVendor 0x1013
+#define DiamondVendor 0x100E
+#define MatroxVendor 0x102B
+#define ParadiseVendor 0x101C
+
+struct VgaRegs GenVgaTextRegs[NREGS+1] = {
+/* port index value */
+ /* SR Regs */
+ 0x3c4, 0x1, 0x0,
+ 0x3c4, 0x2, 0x3,
+ 0x3c4, 0x3, 0x0,
+ 0x3c4, 0x4, 0x2,
+ /* CR Regs */
+ 0x3d4, 0x0, 0x5f,
+ 0x3d4, 0x1, 0x4f,
+ 0x3d4, 0x2, 0x50,
+ 0x3d4, 0x3, 0x82,
+ 0x3d4, 0x4, 0x55,
+ 0x3d4, 0x5, 0x81,
+ 0x3d4, 0x6, 0xbf,
+ 0x3d4, 0x7, 0x1f,
+ 0x3d4, 0x8, 0x00,
+ 0x3d4, 0x9, 0x4f,
+ 0x3d4, 0xa, 0x0d,
+ 0x3d4, 0xb, 0x0e,
+ 0x3d4, 0xc, 0x00,
+ 0x3d4, 0xd, 0x00,
+ 0x3d4, 0xe, 0x00,
+ 0x3d4, 0xf, 0x00,
+ 0x3d4, 0x10, 0x9c,
+ 0x3d4, 0x11, 0x8e,
+ 0x3d4, 0x12, 0x8f,
+ 0x3d4, 0x13, 0x28,
+ 0x3d4, 0x14, 0x1f,
+ 0x3d4, 0x15, 0x96,
+ 0x3d4, 0x16, 0xb9,
+ 0x3d4, 0x17, 0xa3,
+ /* GR Regs */
+ 0x3ce, 0x0, 0x0,
+ 0x3ce, 0x1, 0x0,
+ 0x3ce, 0x2, 0x0,
+ 0x3ce, 0x3, 0x0,
+ 0x3ce, 0x4, 0x0,
+ 0x3ce, 0x5, 0x10,
+ 0x3ce, 0x6, 0xe,
+ 0x3ce, 0x7, 0x0,
+ 0x3ce, 0x8, 0xff,
+ ENDMK
+};
+
+struct VgaRegs S3TextRegs[NREGS+1] = {
+/* port index value */
+ /* SR Regs */
+ 0x3c4, 0x1, 0x0,
+ 0x3c4, 0x2, 0x3,
+ 0x3c4, 0x3, 0x0,
+ 0x3c4, 0x4, 0x2,
+ /* CR Regs */
+ 0x3d4, 0x0, 0x5f,
+ 0x3d4, 0x1, 0x4f,
+ 0x3d4, 0x2, 0x50,
+ 0x3d4, 0x3, 0x82,
+ 0x3d4, 0x4, 0x55,
+ 0x3d4, 0x5, 0x81,
+ 0x3d4, 0x6, 0xbf,
+ 0x3d4, 0x7, 0x1f,
+ 0x3d4, 0x8, 0x00,
+ 0x3d4, 0x9, 0x4f,
+ 0x3d4, 0xa, 0x0d,
+ 0x3d4, 0xb, 0x0e,
+ 0x3d4, 0xc, 0x00,
+ 0x3d4, 0xd, 0x00,
+ 0x3d4, 0xe, 0x00,
+ 0x3d4, 0xf, 0x00,
+ 0x3d4, 0x10, 0x9c,
+ 0x3d4, 0x11, 0x8e,
+ 0x3d4, 0x12, 0x8f,
+ 0x3d4, 0x13, 0x28,
+ 0x3d4, 0x14, 0x1f,
+ 0x3d4, 0x15, 0x96,
+ 0x3d4, 0x16, 0xb9,
+ 0x3d4, 0x17, 0xa3,
+ /* GR Regs */
+ 0x3ce, 0x0, 0x0,
+ 0x3ce, 0x1, 0x0,
+ 0x3ce, 0x2, 0x0,
+ 0x3ce, 0x3, 0x0,
+ 0x3ce, 0x4, 0x0,
+ 0x3ce, 0x5, 0x10,
+ 0x3ce, 0x6, 0xe,
+ 0x3ce, 0x7, 0x0,
+ 0x3ce, 0x8, 0xff,
+ ENDMK
+};
+
+struct RGBColors
+{
+ unsigned char r, g, b;
+};
+
+/*
+ * Default console text mode color table.
+ * These values were obtained by booting Linux with
+ * text mode firmware & then dumping the registers.
+ */
+struct RGBColors TextCLUT[256] =
+{
+ /* red green blue */
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x2a,
+ 0x0, 0x2a, 0x0,
+ 0x0, 0x2a, 0x2a,
+ 0x2a, 0x0, 0x0,
+ 0x2a, 0x0, 0x2a,
+ 0x2a, 0x2a, 0x0,
+ 0x2a, 0x2a, 0x2a,
+ 0x0, 0x0, 0x15,
+ 0x0, 0x0, 0x3f,
+ 0x0, 0x2a, 0x15,
+ 0x0, 0x2a, 0x3f,
+ 0x2a, 0x0, 0x15,
+ 0x2a, 0x0, 0x3f,
+ 0x2a, 0x2a, 0x15,
+ 0x2a, 0x2a, 0x3f,
+ 0x0, 0x15, 0x0,
+ 0x0, 0x15, 0x2a,
+ 0x0, 0x3f, 0x0,
+ 0x0, 0x3f, 0x2a,
+ 0x2a, 0x15, 0x0,
+ 0x2a, 0x15, 0x2a,
+ 0x2a, 0x3f, 0x0,
+ 0x2a, 0x3f, 0x2a,
+ 0x0, 0x15, 0x15,
+ 0x0, 0x15, 0x3f,
+ 0x0, 0x3f, 0x15,
+ 0x0, 0x3f, 0x3f,
+ 0x2a, 0x15, 0x15,
+ 0x2a, 0x15, 0x3f,
+ 0x2a, 0x3f, 0x15,
+ 0x2a, 0x3f, 0x3f,
+ 0x15, 0x0, 0x0,
+ 0x15, 0x0, 0x2a,
+ 0x15, 0x2a, 0x0,
+ 0x15, 0x2a, 0x2a,
+ 0x3f, 0x0, 0x0,
+ 0x3f, 0x0, 0x2a,
+ 0x3f, 0x2a, 0x0,
+ 0x3f, 0x2a, 0x2a,
+ 0x15, 0x0, 0x15,
+ 0x15, 0x0, 0x3f,
+ 0x15, 0x2a, 0x15,
+ 0x15, 0x2a, 0x3f,
+ 0x3f, 0x0, 0x15,
+ 0x3f, 0x0, 0x3f,
+ 0x3f, 0x2a, 0x15,
+ 0x3f, 0x2a, 0x3f,
+ 0x15, 0x15, 0x0,
+ 0x15, 0x15, 0x2a,
+ 0x15, 0x3f, 0x0,
+ 0x15, 0x3f, 0x2a,
+ 0x3f, 0x15, 0x0,
+ 0x3f, 0x15, 0x2a,
+ 0x3f, 0x3f, 0x0,
+ 0x3f, 0x3f, 0x2a,
+ 0x15, 0x15, 0x15,
+ 0x15, 0x15, 0x3f,
+ 0x15, 0x3f, 0x15,
+ 0x15, 0x3f, 0x3f,
+ 0x3f, 0x15, 0x15,
+ 0x3f, 0x15, 0x3f,
+ 0x3f, 0x3f, 0x15,
+ 0x3f, 0x3f, 0x3f,
+ 0x39, 0xc, 0x5,
+ 0x15, 0x2c, 0xf,
+ 0x26, 0x10, 0x3d,
+ 0x29, 0x29, 0x38,
+ 0x4, 0x1a, 0xe,
+ 0x2, 0x1e, 0x3a,
+ 0x3c, 0x25, 0x33,
+ 0x3c, 0xc, 0x2c,
+ 0x3f, 0x3, 0x2b,
+ 0x1c, 0x9, 0x13,
+ 0x25, 0x2a, 0x35,
+ 0x1e, 0xa, 0x38,
+ 0x24, 0x8, 0x3,
+ 0x3, 0xe, 0x36,
+ 0xc, 0x6, 0x2a,
+ 0x26, 0x3, 0x32,
+ 0x5, 0x2f, 0x33,
+ 0x3c, 0x35, 0x2f,
+ 0x2d, 0x26, 0x3e,
+ 0xd, 0xa, 0x10,
+ 0x25, 0x3c, 0x11,
+ 0xd, 0x4, 0x2e,
+ 0x5, 0x19, 0x3e,
+ 0xc, 0x13, 0x34,
+ 0x2b, 0x6, 0x24,
+ 0x4, 0x3, 0xd,
+ 0x2f, 0x3c, 0xc,
+ 0x2a, 0x37, 0x1f,
+ 0xf, 0x12, 0x38,
+ 0x38, 0xe, 0x2a,
+ 0x12, 0x2f, 0x19,
+ 0x29, 0x2e, 0x31,
+ 0x25, 0x13, 0x3e,
+ 0x33, 0x3e, 0x33,
+ 0x1d, 0x2c, 0x25,
+ 0x15, 0x15, 0x5,
+ 0x32, 0x25, 0x39,
+ 0x1a, 0x7, 0x1f,
+ 0x13, 0xe, 0x1d,
+ 0x36, 0x17, 0x34,
+ 0xf, 0x15, 0x23,
+ 0x2, 0x35, 0xd,
+ 0x15, 0x3f, 0xc,
+ 0x14, 0x2f, 0xf,
+ 0x19, 0x21, 0x3e,
+ 0x27, 0x11, 0x2f,
+ 0x38, 0x3f, 0x3c,
+ 0x36, 0x2d, 0x15,
+ 0x16, 0x17, 0x2,
+ 0x1, 0xa, 0x3d,
+ 0x1b, 0x11, 0x3f,
+ 0x21, 0x3c, 0xd,
+ 0x1a, 0x39, 0x3d,
+ 0x8, 0xe, 0xe,
+ 0x22, 0x21, 0x23,
+ 0x1e, 0x30, 0x5,
+ 0x1f, 0x22, 0x3d,
+ 0x1e, 0x2f, 0xa,
+ 0x0, 0x1c, 0xe,
+ 0x0, 0x1c, 0x15,
+ 0x0, 0x1c, 0x1c,
+ 0x0, 0x15, 0x1c,
+ 0x0, 0xe, 0x1c,
+ 0x0, 0x7, 0x1c,
+ 0xe, 0xe, 0x1c,
+ 0x11, 0xe, 0x1c,
+ 0x15, 0xe, 0x1c,
+ 0x18, 0xe, 0x1c,
+ 0x1c, 0xe, 0x1c,
+ 0x1c, 0xe, 0x18,
+ 0x1c, 0xe, 0x15,
+ 0x1c, 0xe, 0x11,
+ 0x1c, 0xe, 0xe,
+ 0x1c, 0x11, 0xe,
+ 0x1c, 0x15, 0xe,
+ 0x1c, 0x18, 0xe,
+ 0x1c, 0x1c, 0xe,
+ 0x18, 0x1c, 0xe,
+ 0x15, 0x1c, 0xe,
+ 0x11, 0x1c, 0xe,
+ 0xe, 0x1c, 0xe,
+ 0xe, 0x1c, 0x11,
+ 0xe, 0x1c, 0x15,
+ 0xe, 0x1c, 0x18,
+ 0xe, 0x1c, 0x1c,
+ 0xe, 0x18, 0x1c,
+ 0xe, 0x15, 0x1c,
+ 0xe, 0x11, 0x1c,
+ 0x14, 0x14, 0x1c,
+ 0x16, 0x14, 0x1c,
+ 0x18, 0x14, 0x1c,
+ 0x1a, 0x14, 0x1c,
+ 0x1c, 0x14, 0x1c,
+ 0x1c, 0x14, 0x1a,
+ 0x1c, 0x14, 0x18,
+ 0x1c, 0x14, 0x16,
+ 0x1c, 0x14, 0x14,
+ 0x1c, 0x16, 0x14,
+ 0x1c, 0x18, 0x14,
+ 0x1c, 0x1a, 0x14,
+ 0x1c, 0x1c, 0x14,
+ 0x1a, 0x1c, 0x14,
+ 0x18, 0x1c, 0x14,
+ 0x16, 0x1c, 0x14,
+ 0x14, 0x1c, 0x14,
+ 0x14, 0x1c, 0x16,
+ 0x14, 0x1c, 0x18,
+ 0x14, 0x1c, 0x1a,
+ 0x14, 0x1c, 0x1c,
+ 0x14, 0x1a, 0x1c,
+ 0x14, 0x18, 0x1c,
+ 0x14, 0x16, 0x1c,
+ 0x0, 0x0, 0x10,
+ 0x4, 0x0, 0x10,
+ 0x8, 0x0, 0x10,
+ 0xc, 0x0, 0x10,
+ 0x10, 0x0, 0x10,
+ 0x10, 0x0, 0xc,
+ 0x10, 0x0, 0x8,
+ 0x10, 0x0, 0x4,
+ 0x10, 0x0, 0x0,
+ 0x10, 0x4, 0x0,
+ 0x10, 0x8, 0x0,
+ 0x10, 0xc, 0x0,
+ 0x10, 0x10, 0x0,
+ 0xc, 0x10, 0x0,
+ 0x8, 0x10, 0x0,
+ 0x4, 0x10, 0x0,
+ 0x0, 0x10, 0x0,
+ 0x0, 0x10, 0x4,
+ 0x0, 0x10, 0x8,
+ 0x0, 0x10, 0xc,
+ 0x0, 0x10, 0x10,
+ 0x0, 0xc, 0x10,
+ 0x0, 0x8, 0x10,
+ 0x0, 0x4, 0x10,
+ 0x8, 0x8, 0x10,
+ 0xa, 0x8, 0x10,
+ 0xc, 0x8, 0x10,
+ 0xe, 0x8, 0x10,
+ 0x10, 0x8, 0x10,
+ 0x10, 0x8, 0xe,
+ 0x10, 0x8, 0xc,
+ 0x10, 0x8, 0xa,
+ 0x10, 0x8, 0x8,
+ 0x10, 0xa, 0x8,
+ 0x10, 0xc, 0x8,
+ 0x10, 0xe, 0x8,
+ 0x10, 0x10, 0x8,
+ 0xe, 0x10, 0x8,
+ 0xc, 0x10, 0x8,
+ 0xa, 0x10, 0x8,
+ 0x8, 0x10, 0x8,
+ 0x8, 0x10, 0xa,
+ 0x8, 0x10, 0xc,
+ 0x8, 0x10, 0xe,
+ 0x8, 0x10, 0x10,
+ 0x8, 0xe, 0x10,
+ 0x8, 0xc, 0x10,
+ 0x8, 0xa, 0x10,
+ 0xb, 0xb, 0x10,
+ 0xc, 0xb, 0x10,
+ 0xd, 0xb, 0x10,
+ 0xf, 0xb, 0x10,
+ 0x10, 0xb, 0x10,
+ 0x10, 0xb, 0xf,
+ 0x10, 0xb, 0xd,
+ 0x10, 0xb, 0xc,
+ 0x10, 0xb, 0xb,
+ 0x10, 0xc, 0xb,
+ 0x10, 0xd, 0xb,
+ 0x10, 0xf, 0xb,
+ 0x10, 0x10, 0xb,
+ 0xf, 0x10, 0xb,
+ 0xd, 0x10, 0xb,
+ 0xc, 0x10, 0xb,
+ 0xb, 0x10, 0xb,
+ 0xb, 0x10, 0xc,
+ 0xb, 0x10, 0xd,
+ 0xb, 0x10, 0xf,
+ 0xb, 0x10, 0x10,
+ 0xb, 0xf, 0x10,
+ 0xb, 0xd, 0x10,
+ 0xb, 0xc, 0x10,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0
+};
+
+unsigned char AC[21] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x0C, 0x00, 0x0F, 0x08, 0x00};
+
+static int scanPCI(int start_slt);
+static int PCIVendor(int);
+static void printslots(void);
+int delayLoop(int);
+extern void puthex(unsigned long);
+extern void puts(const char *);
+static void unlockS3(void);
+
+static inline
+outw(int port, unsigned short val)
+{
+ outb(port, val >> 8);
+ outb(port+1, val);
+}
+
+#define PPC_601 1
+
+vga_init(unsigned char *ISA_mem)
+{
+ int slot;
+ struct VgaRegs *VgaTextRegs;
+
+ if ((_get_PVR()>>16) == PPC_601) {
+ return(old_vga_init(ISA_mem));
+ }
+
+#if 1
+ /* See if VGA already in TEXT mode - exit if so! */
+ outb(0x3CE, 0x06);
+ if ((inb(0x3CF) & 0x01) == 0){puts("VGA already in text mode\n"); return;}
+#endif
+
+ /* If no VGA responding in text mode, then we have some work to do...
+ */
+ slot = -1;
+ while((slot = scanPCI(slot)) > -1) { /* find video card in use */
+ unlockVideo(slot); /* enable I/O to card */
+ VgaTextRegs = GenVgaTextRegs;
+
+ switch (PCIVendor(slot)) {
+ default:
+ break;
+ case(S3Vendor):
+ unlockS3();
+ VgaTextRegs = S3TextRegs;
+ break;
+
+ case(CirrusVendor):
+ outw(0x3C4, 0x0612); /* unlock ext regs */
+ outw(0x3C4, 0x0700); /* reset ext sequence mode */
+ break;
+
+ case(ParadiseVendor): /* IBM Portable 850 */
+ outw(0x3ce, 0x0f05); /* unlock pardise registers */
+ outw(0x3c4, 0x0648);
+ outw(0x3d4, 0x2985);
+ outw(0x3d4, 0x34a6);
+ outb(0x3ce, 0x0b); /* disable linear addressing */
+ outb(0x3cf, inb(0x3cf) & ~0x30);
+ outw(0x3c4, 0x1400);
+ outb(0x3ce, 0x0e); /* disable 256 color mode */
+ outb(0x3cf, inb(0x3cf) & ~0x01);
+ outb(0xd00, 0xff); /* enable auto-centering */
+ if (!(inb(0xd01) & 0x03)) {
+ outb(0x3d4, 0x33);
+ outb(0x3d5, inb(0x3d5) & ~0x90);
+ outb(0x3d4, 0x32);
+ outb(0x3d5, inb(0x3d5) | 0x04);
+ outw(0x3d4, 0x0250);
+ outw(0x3d4, 0x07ba);
+ outw(0x3d4, 0x0900);
+ outw(0x3d4, 0x15e7);
+ outw(0x3d4, 0x2a95);
+ }
+ outw(0x3d4, 0x34a0);
+ break;
+
+ #if 0 /* Untested - probably doesn't work */
+ case(MatroxVendor):
+ case(DiamondVendor):
+ puts("VGA Chip Vendor ID: ");
+ puthex(PCIVendor(slot));
+ puts("\n");
+ delayLoop(1);
+ #endif
+ };
+
+ outw(0x3C4, 0x0120); /* disable video */
+ setTextRegs(VgaTextRegs); /* initial register setup */
+ setTextCLUT(0); /* load color lookup table */
+ loadFont(ISA_mem); /* load font */
+ setTextRegs(VgaTextRegs); /* reload registers */
+ outw(0x3C4, 0x0100); /* re-enable video */
+ clearVideoMemory();
+
+ if (PCIVendor(slot) == S3Vendor) {
+ outb(0x3c2, 0x63); /* MISC */
+ } /* endif */
+
+ #ifdef DEBUG
+ printslots();
+ delayLoop(5);
+ #endif
+
+ delayLoop(1); /* give time for the video monitor to come up */
+ }
+ return (1); /* 'CRT' I/O supported */
+}
+
+static int
+NOP(int x)
+{
+}
+
+/*
+ * Write to VGA Attribute registers.
+ */
+writeAttr(index, data, videoOn)
+ unsigned char index;
+ unsigned char data;
+ unsigned char videoOn; /* video on flag */
+{
+ unsigned char v;
+ v = inb(0x3da); /* reset attr. address toggle */
+ if (videoOn)
+ outb(0x3c0, (index & 0x1F) | 0x20);
+ else
+ outb(0x3c0, (index & 0x1F));
+ outb(0x3c0, data);
+}
+
+setTextRegs(struct VgaRegs *svp)
+{
+ int i;
+
+ /*
+ * saved settings
+ */
+ while( svp->io_port != ENDMK ) {
+ outb(svp->io_port, svp->io_index);
+ outb(svp->io_port+1, svp->io_value);
+ svp++;
+ }
+
+ outb(0x3c2, 0x67); /* MISC */
+ outb(0x3c6, 0xff); /* MASK */
+
+ for ( i = 0; i < 0x10; i++)
+ writeAttr(i, AC[i], 0); /* pallete */
+ writeAttr(0x10, 0x0c, 0); /* text mode */
+ writeAttr(0x11, 0x00, 0); /* overscan color (border) */
+ writeAttr(0x12, 0x0f, 0); /* plane enable */
+ writeAttr(0x13, 0x08, 0); /* pixel panning */
+ writeAttr(0x14, 0x00, 1); /* color select; video on */
+}
+
+setTextCLUT(int shift)
+{
+ int i;
+
+ outb(0x3C6, 0xFF);
+ i = inb(0x3C7);
+ outb(0x3C8, 0);
+ i = inb(0x3C7);
+
+ for ( i = 0; i < 256; i++) {
+ outb(0x3C9, TextCLUT[i].r << shift);
+ outb(0x3C9, TextCLUT[i].g << shift);
+ outb(0x3C9, TextCLUT[i].b << shift);
+ }
+}
+
+
+loadFont(unsigned char *ISA_mem)
+{
+ int i, j;
+ unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
+
+ outb(0x3C2, 0x67);
+ /*
+ * Load font
+ */
+ i = inb(0x3DA); /* Reset Attr toggle */
+
+ outb(0x3C0,0x30);
+ outb(0x3C0, 0x01); /* graphics mode */
+
+ outw(0x3C4, 0x0001); /* reset sequencer */
+ outw(0x3C4, 0x0204); /* write to plane 2 */
+ outw(0x3C4, 0x0406); /* enable plane graphics */
+ outw(0x3C4, 0x0003); /* reset sequencer */
+ outw(0x3CE, 0x0402); /* read plane 2 */
+ outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
+ outw(0x3CE, 0x0605); /* set graphics mode */
+
+ for (i = 0; i < sizeof(font); i += 16) {
+ for (j = 0; j < 16; j++) {
+ __asm__ volatile("eieio");
+ font_page[(2*i)+j] = font[i+j];
+ }
+ }
+}
+
+static void
+unlockS3(void)
+{
+ int s3_device_id;
+ outw(0x3d4, 0x3848);
+ outw(0x3d4, 0x39a5);
+ outb(0x3d4, 0x2d);
+ s3_device_id = inb(0x3d5) << 8;
+ outb(0x3d4, 0x2e);
+ s3_device_id |= inb(0x3d5);
+
+ if (s3_device_id != 0x8812) {
+ /* From the S3 manual */
+ outb(0x46E8, 0x10); /* Put into setup mode */
+ outb(0x3C3, 0x10);
+ outb(0x102, 0x01); /* Enable registers */
+ outb(0x46E8, 0x08); /* Enable video */
+ outb(0x3C3, 0x08);
+ outb(0x4AE8, 0x00);
+
+#if 0
+ outb(0x42E8, 0x80); /* Reset graphics engine? */
+#endif
+
+ outb(0x3D4, 0x38); /* Unlock all registers */
+ outb(0x3D5, 0x48);
+ outb(0x3D4, 0x39);
+ outb(0x3D5, 0xA5);
+ outb(0x3D4, 0x40);
+ outb(0x3D5, inb(0x3D5)|0x01);
+ outb(0x3D4, 0x33);
+ outb(0x3D5, inb(0x3D5)&~0x52);
+ outb(0x3D4, 0x35);
+ outb(0x3D5, inb(0x3D5)&~0x30);
+ outb(0x3D4, 0x3A);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x53);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x31);
+ outb(0x3D5, inb(0x3D5)&~0x4B);
+ outb(0x3D4, 0x58);
+
+ outb(0x3D5, 0);
+
+ outb(0x3D4, 0x54);
+ outb(0x3D5, 0x38);
+ outb(0x3D4, 0x60);
+ outb(0x3D5, 0x07);
+ outb(0x3D4, 0x61);
+ outb(0x3D5, 0x80);
+ outb(0x3D4, 0x62);
+ outb(0x3D5, 0xA1);
+ outb(0x3D4, 0x69); /* High order bits for cursor address */
+ outb(0x3D5, 0);
+
+ outb(0x3D4, 0x32);
+ outb(0x3D5, inb(0x3D5)&~0x10);
+ } else {
+ outw(0x3c4, 0x0806); /* IBM Portable 860 */
+ outw(0x3c4, 0x1041);
+ outw(0x3c4, 0x1128);
+ outw(0x3d4, 0x4000);
+ outw(0x3d4, 0x3100);
+ outw(0x3d4, 0x3a05);
+ outw(0x3d4, 0x6688);
+ outw(0x3d4, 0x5800); /* disable linear addressing */
+ outw(0x3d4, 0x4500); /* disable H/W cursor */
+ outw(0x3c4, 0x5410); /* enable auto-centering */
+ outw(0x3c4, 0x561f);
+ outw(0x3c4, 0x1b80); /* lock DCLK selection */
+ outw(0x3d4, 0x3900); /* lock S3 registers */
+ outw(0x3d4, 0x3800);
+ } /* endif */
+}
+
+/*
+ * cursor() sets an offset (0-1999) into the 80x25 text area
+ */
+void
+cursor(int x, int y)
+{
+ int pos = (y*cols)+x;
+ outb(0x3D4, 14);
+ outb(0x3D5, pos >> 8);
+ outb(0x3D4, 15);
+ outb(0x3D5, pos);
+}
+
+clearVideoMemory()
+{
+ int i, j;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < cols; j++) {
+ vidmem[((i*cols)+j)*2] = 0x20; /* fill with space character */
+ vidmem[((i*cols)+j)*2+1] = 0x07; /* set bg & fg attributes */
+ }
+ }
+}
+
+/* ============ */
+
+
+#define NSLOTS 8
+#define NPCIREGS 5
+
+
+/*
+ should use devfunc number/indirect method to be totally safe on
+ all machines, this works for now on 3 slot Moto boxes
+*/
+
+struct PCI_ConfigInfo {
+ unsigned long * config_addr;
+ unsigned long regs[NPCIREGS];
+} PCI_slots [NSLOTS] = {
+
+ { (unsigned long *)0x80808000, 0xDEADBEEF }, /* onboard */
+ { (unsigned long *)0x80800800, 0xDEADBEEF }, /* onboard */
+ { (unsigned long *)0x80801000, 0xDEADBEEF }, /* onboard */
+ { (unsigned long *)0x80802000, 0xDEADBEEF }, /* onboard */
+ { (unsigned long *)0x80804000, 0xDEADBEEF }, /* onboard */
+ { (unsigned long *)0x80810000, 0xDEADBEEF }, /* slot A/1 */
+ { (unsigned long *)0x80820000, 0xDEADBEEF }, /* slot B/2 */
+ { (unsigned long *)0x80840000, 0xDEADBEEF } /* slot C/3 */
+};
+
+
+
+/*
+ * The following code modifies the PCI Command register
+ * to enable memory and I/O accesses.
+ */
+unlockVideo(slot)
+{
+ volatile unsigned char * ppci;
+
+ ppci = (unsigned char * )PCI_slots[slot].config_addr;
+ ppci[4] = 0x0003; /* enable memory and I/O accesses */
+ ppci[0x10] = 0x00000; /* turn off memory mapping */
+ ppci[0x11] = 0x00000; /* mem_base = 0 */
+ ppci[0x12] = 0x00000;
+ ppci[0x13] = 0x00000;
+ __asm__ volatile("eieio");
+
+ outb(0x3d4, 0x11);
+ outb(0x3d5, 0x0e); /* unlock CR0-CR7 */
+}
+
+long
+SwapBytes(long lv) /* turn little endian into big indian long */
+{
+ long t;
+ t = (lv&0x000000FF) << 24;
+ t |= (lv&0x0000FF00) << 8;
+ t |= (lv&0x00FF0000) >> 8;
+ t |= (lv&0xFF000000) >> 24;
+ return(t);
+}
+
+
+#define DEVID 0
+#define CMD 1
+#define CLASS 2
+#define MEMBASE 4
+
+int
+scanPCI(int start_slt)
+{
+ int slt, r;
+ struct PCI_ConfigInfo *pslot;
+ int theSlot = -1;
+ int highVgaSlot = 0;
+
+ for ( slt = start_slt + 1; slt < NSLOTS; slt++) {
+ pslot = &PCI_slots[slt];
+ for ( r = 0; r < NPCIREGS; r++) {
+ pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
+ }
+ /* card in slot ? */
+ if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {
+ /* VGA ? */
+ if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) ||
+ ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
+ highVgaSlot = slt;
+ /* did firmware enable it ? */
+ if ( (pslot->regs[CMD] & 0x03) ) {
+ theSlot = slt;
+ break;
+ }
+ }
+ }
+ }
+
+ return ( theSlot );
+}
+
+/* Delay for a certain number of seconds */
+/* Note: They loop is used since 'udelay' can't handle really long counts! */
+
+int
+delayLoop(int k)
+{
+ int i;
+ while (k-- > 0) {
+ for (i = 0; i < 1000; i++) {
+ udelay(1000);
+ }
+ }
+}
+
+
+/* return Vendor ID of card in the slot */
+static
+int PCIVendor(int slotnum) {
+ struct PCI_ConfigInfo *pslot;
+
+ pslot = &PCI_slots[slotnum];
+
+return (pslot->regs[DEVID] & 0xFFFF);
+}
+
+static
+void printslots(void)
+{
+ int i;
+ struct PCI_ConfigInfo *pslot;
+ for(i=0; i < NSLOTS; i++) {
+#if 0
+ pslot = &PCI_slots[i];
+ printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
+ i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
+#else
+ puts("PCI Slot number: "); puthex(i);
+ puts(" Vendor ID: ");
+ puthex(PCIVendor(i)); puts("\n");
+#endif
+
+ }
+}
+
+/*
+ * OLD vreset.c
+ *
+ * Initialize the VGA control registers to 80x25 text mode.
+ *
+ * Adapted from a program by:
+ * Steve Sellgren
+ * San Francisco Indigo Company
+ * sfindigo!sellgren@uunet.uu.net
*/
unsigned char CRTC[24] = {
@@ -15,13 +873,8 @@ unsigned char CRTC[24] = {
0x9C, 0xAE, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3};
unsigned char SEQ[5] = {0x3, 0x0, 0x3, 0x0, 0x2};
unsigned char GC[9] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0xE, 0x0, 0xFF};
-unsigned char AC[21] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
- 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
- 0x0C, 0x00, 0x0F, 0x08, 0x00};
-
-#include "iso_font.h"
+#if 0
static const unsigned char color_LUT[] =
{
0x00, 0x00, 0x00, /* 0 - black */
@@ -41,124 +894,124 @@ static const unsigned char color_LUT[] =
0x2A, 0x2A, 0x15, /* 14 - yellow */
0x2A, 0x2A, 0x3F, /* 15 - bright white */
};
-
-static inline
-outw(int port, unsigned short val)
-{
- outb(port, val >> 8);
- outb(port+1, val);
-}
+#endif
-vga_init(unsigned char *ISA_mem)
+old_vga_init(unsigned char *ISA_mem)
{
- int i, j;
- int value;
- unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
+ int i, j;
+ int value;
+ unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
- /* See if VGA already in TEXT mode - exit if so! */
- outb(0x3CE, 0x06);
- if ((inb(0x3CF) & 0x01) == 0) return;
+ /* See if VGA already in TEXT mode - exit if so! */
+ outb(0x3CE, 0x06);
+ if ((inb(0x3CF) & 0x01) == 0) return;
- /* From the S3 manual */
- outb(0x46E8, 0x10); /* Put into setup mode */
- outb(0x3C3, 0x10);
- outb(0x102, 0x01); /* Enable registers */
- outb(0x46E8, 0x08); /* Enable video */
- outb(0x3C3, 0x08);
- outb(0x4AE8, 0x00);
-
- outb(0x42E8, 0x80); /* Reset graphics engine? */
-
- outb(0x3D4, 0x38); /* Unlock all registers */
- outb(0x3D5, 0x48);
- outb(0x3D4, 0x39);
- outb(0x3D5, 0xA5);
- outb(0x3D4, 0x40);
- outb(0x3D5, inb(0x3D5)|0x01);
- outb(0x3D4, 0x33);
- outb(0x3D5, inb(0x3D5)&~0x52);
- outb(0x3D4, 0x35);
- outb(0x3D5, inb(0x3D5)&~0x30);
- outb(0x3D4, 0x3A);
- outb(0x3D5, 0x00);
- outb(0x3D4, 0x53);
- outb(0x3D5, 0x00);
- outb(0x3D4, 0x31);
- outb(0x3D5, inb(0x3D5)&~0x4B);
- outb(0x3D4, 0x58);
- outb(0x3D5, 0);
-
- outb(0x3D4, 0x54);
- outb(0x3D5, 0x38);
- outb(0x3D4, 0x60);
- outb(0x3D5, 0x07);
- outb(0x3D4, 0x61);
- outb(0x3D5, 0x80);
- outb(0x3D4, 0x62);
- outb(0x3D5, 0xA1);
- outb(0x3D4, 0x69); /* High order bits for cursor address */
- outb(0x3D5, 0);
+ /* From the S3 manual */
+ outb(0x46E8, 0x10); /* Put into setup mode */
+ outb(0x3C3, 0x10);
+ outb(0x102, 0x01); /* Enable registers */
+ outb(0x46E8, 0x08); /* Enable video */
+ outb(0x3C3, 0x08);
+ outb(0x4AE8, 0x00);
+
+#if 0
+ outb(0x42E8, 0x80); /* Reset graphics engine? */
+#endif
+
+ outb(0x3D4, 0x38); /* Unlock all registers */
+ outb(0x3D5, 0x48);
+ outb(0x3D4, 0x39);
+ outb(0x3D5, 0xA5);
+ outb(0x3D4, 0x40);
+ outb(0x3D5, inb(0x3D5)|0x01);
+ outb(0x3D4, 0x33);
+ outb(0x3D5, inb(0x3D5)&~0x52);
+ outb(0x3D4, 0x35);
+ outb(0x3D5, inb(0x3D5)&~0x30);
+ outb(0x3D4, 0x3A);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x53);
+ outb(0x3D5, 0x00);
+ outb(0x3D4, 0x31);
+ outb(0x3D5, inb(0x3D5)&~0x4B);
+ outb(0x3D4, 0x58);
+ outb(0x3D5, 0);
+
+ outb(0x3D4, 0x54);
+ outb(0x3D5, 0x38);
+ outb(0x3D4, 0x60);
+ outb(0x3D5, 0x07);
+ outb(0x3D4, 0x61);
+ outb(0x3D5, 0x80);
+ outb(0x3D4, 0x62);
+ outb(0x3D5, 0xA1);
+ outb(0x3D4, 0x69); /* High order bits for cursor address */
+ outb(0x3D5, 0);
- outb(0x3D4, 0x32);
- outb(0x3D5, inb(0x3D5)&~0x10);
-
- outb(0x3C2, 0x67);
-
- /* Initialize DAC */
- outb(0x3C6,0xFF);
- inb(0x3C7);
- outb(0x3C8,0x00);
- inb(0x3C7);
- for (i=0; i<sizeof(color_LUT); i++) {
- outb(0x3C9, color_LUT[i]);
- }
- for (i; i<768; i += 3) {
- outb(0x3C9, 0x3F); /* White? */
- outb(0x3C9, 0x3F); /* White? */
- outb(0x3C9, 0x3F); /* White? */
- }
-
- /* Load font */
- NOP(inb(0x3DA)); /* Reset Address/Data FlipFlop for Attribute ctlr */
- outb(0x3C0,0x30); outb(0x3C0, 0x01); /* graphics mode */
- outw(0x3C4, 0x0001); /* reset sequencer */
- outw(0x3C4, 0x0204); /* write to plane 2 */
- outw(0x3C4, 0x0407); /* enable plane graphics */
- outw(0x3C4, 0x0003); /* reset sequencer */
- outw(0x3CE, 0x0402); /* read plane 2 */
- outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
- outw(0x3CE, 0x0600); /* set graphics */
- for (i = 0; i < sizeof(font); i += 16) {
- for (j = 0; j < 16; j++) {
- font_page[(2*i)+j] = font[i+j];
- }
- }
-
- for (i = 0; i < 24; i++) {
- outb(0x3D4, i);
- outb(0x3D5, CRTC[i]);
- }
- for (i = 0; i < 5; i++) {
- outb(0x3C4, i);
- outb(0x3C5, SEQ[i]);
- }
- for (i = 0; i < 9; i++) {
- outb(0x3CE, i);
- outb(0x3CF, GC[i]);
- }
- value = inb(0x3DA); /* reset flip-flop */
- for (i = 0; i < 16; i++) {
- outb(0x3C0, i);
- outb(0x3C0, AC[i]);
- }
- for (i = 16; i < 21; i++) {
- outb(0x3C0, i | 0x20);
- outb(0x3C0, AC[i]);
- }
- outb(0x3C2, 0x23);
-}
+ outb(0x3D4, 0x32);
+ outb(0x3D5, inb(0x3D5)&~0x10);
-static int
-NOP(int x)
-{
+ outb(0x3C2, 0x67);
+
+#if 0
+ /* Initialize DAC */
+ outb(0x3C6,0xFF);
+ inb(0x3C7);
+ outb(0x3C8,0x00);
+ inb(0x3C7);
+ for (i=0; i<sizeof(color_LUT); i++) {
+ outb(0x3C9, color_LUT[i]);
+ }
+ for (i; i<768; i += 3) {
+ outb(0x3C9, 0x3F); /* White? */
+ outb(0x3C9, 0x3F); /* White? */
+ outb(0x3C9, 0x3F); /* White? */
+ }
+
+ /* Load font */
+ NOP(inb(0x3DA)); /* Reset Address/Data FlipFlop for Attribute ctlr */
+ outb(0x3C0,0x30); outb(0x3C0, 0x01); /* graphics mode */
+ outw(0x3C4, 0x0001); /* reset sequencer */
+ outw(0x3C4, 0x0204); /* write to plane 2 */
+ outw(0x3C4, 0x0407); /* enable plane graphics */
+ outw(0x3C4, 0x0003); /* reset sequencer */
+ outw(0x3CE, 0x0402); /* read plane 2 */
+ outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
+ outw(0x3CE, 0x0600); /* set graphics */
+ for (i = 0; i < sizeof(font); i += 16) {
+ for (j = 0; j < 16; j++) {
+ font_page[(2*i)+j] = font[i+j];
+ }
+ }
+#else
+ outw(0x3C4, 0x0120); /* disable video */
+ setTextCLUT(2); /* load color lookup table */
+ loadFont(ISA_mem); /* load font */
+#endif
+
+ for (i = 0; i < 24; i++) {
+ outb(0x3D4, i);
+ outb(0x3D5, CRTC[i]);
+ }
+ for (i = 0; i < 5; i++) {
+ outb(0x3C4, i);
+ outb(0x3C5, SEQ[i]);
+ }
+ for (i = 0; i < 9; i++) {
+ outb(0x3CE, i);
+ outb(0x3CF, GC[i]);
+ }
+ value = inb(0x3DA); /* reset flip-flop */
+ for (i = 0; i < 16; i++) {
+ outb(0x3C0, i);
+ outb(0x3C0, AC[i]);
+ }
+ for (i = 16; i < 21; i++) {
+ outb(0x3C0, i | 0x20);
+ outb(0x3C0, AC[i]);
+ }
+ clearVideoMemory();
+ outw(0x3C4, 0x0100); /* re-enable video */
+ outb(0x3C2, 0x23);
+ return (1); /* Keyboard should work */
}
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 4211b6b00..9df35fa24 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -2,62 +2,62 @@
# For a description of the syntax of this configuration file,
# see the Configure script.
#
-mainmenu_name "Linux Kernel Configuration"
+mainmenu_name "Linux/PowerPC Kernel Configuration"
-mainmenu_option next_comment
-comment 'Code maturity level options'
+if [ "`uname`" != "Linux" ]; then
+ define_bool CONFIG_CROSSCOMPILE y
+else
+ define_bool CONFIG_NATIVE y
+fi
+
+bool 'Build PowerMac Kernel (not PReP)?' CONFIG_PMAC
+bool 'Build PReP Kernel (not PowerMac)?' CONFIG_PREP
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
-endmenu
+bool 'Used Harddrive LED on IBM 83x workstations as heartbeat?' CONFIG_HEARTBEAT
+bool 'Used PowerPC specific powersaving?' CONFIG_POWERSAVING
+choice 'Processor type' \
+ "Common CONFIG_MCOMMON \
+ 601 CONFIG_M601 \
+ 603 CONFIG_M603 \
+ 604 CONFIG_M604" Common
-mainmenu_option next_comment
-comment 'Loadable module support'
bool 'Enable loadable module support' CONFIG_MODULES
if [ "$CONFIG_MODULES" = "y" ]; then
bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
bool 'Kernel daemon support (e.g. autoload of modules)' CONFIG_KERNELD
fi
-endmenu
-mainmenu_option next_comment
-comment 'General setup'
-bool 'Kernel math emulation' CONFIG_MATH_EMULATION
+mainmenu_option next_comment
+define_bool CONFIG_PCI y
+bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
bool 'Networking support' CONFIG_NET
-bool 'PCI bios support' CONFIG_PCI
-if [ "$CONFIG_PCI" = "y" ]; then
- if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
- fi
-fi
-bool 'System V IPC' CONFIG_SYSVIPC
bool 'Sysctl support' CONFIG_SYSCTL
-tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+bool 'System V IPC' CONFIG_SYSVIPC
+
+# only elf supported, a.out is not -- Cort
+define_bool CONFIG_BINFMT_ELF y
+define_bool CONFIG_KERNEL_ELF y
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-if [ "$CONFIG_BINFMT_ELF" = "y" ]; then
- bool 'Compile kernel as ELF - if your GCC is ELF-GCC' CONFIG_KERNEL_ELF
-fi
-source drivers/block/Config.in
-if [ "$CONFIG_NET" = "y" ]; then
- source net/Config.in
-fi
+source drivers/pnp/Config.in
+source drivers/block/Config.in
mainmenu_option next_comment
comment 'SCSI support'
-
tristate 'SCSI support' CONFIG_SCSI
-
if [ "$CONFIG_SCSI" != "n" ]; then
source drivers/scsi/Config.in
fi
endmenu
+
if [ "$CONFIG_NET" = "y" ]; then
mainmenu_option next_comment
comment 'Network device support'
-
+ source net/Config.in
bool 'Network device support' CONFIG_NETDEVICES
if [ "$CONFIG_NETDEVICES" = "y" ]; then
source drivers/net/Config.in
@@ -65,9 +65,9 @@ if [ "$CONFIG_NET" = "y" ]; then
endmenu
fi
+
mainmenu_option next_comment
comment 'ISDN subsystem'
-
tristate 'ISDN support' CONFIG_ISDN
if [ "$CONFIG_ISDN" != "n" ]; then
source drivers/isdn/Config.in
@@ -76,7 +76,6 @@ endmenu
mainmenu_option next_comment
comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
-
bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
source drivers/cdrom/Config.in
@@ -84,12 +83,10 @@ fi
endmenu
source fs/Config.in
-
source drivers/char/Config.in
mainmenu_option next_comment
comment 'Sound'
-
tristate 'Sound card support' CONFIG_SOUND
if [ "$CONFIG_SOUND" != "n" ]; then
source drivers/sound/Config.in
@@ -97,11 +94,11 @@ fi
endmenu
mainmenu_option next_comment
-comment 'Kernel hacking'
-
+#comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-bool 'Kernel profiling support' CONFIG_PROFILE
-if [ "$CONFIG_PROFILE" = "y" ]; then
- int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
-fi
+#bool 'Kernel profiling support' CONFIG_PROFILE
+#if [ "$CONFIG_PROFILE" = "y" ]; then
+# int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
+#fi
endmenu
+
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index 0bfb26c01..941cd9e38 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -22,32 +22,49 @@
HOST_CC = gcc
-OBJS = misc.o setup.o port_io.o irq.o pci.o traps.o stubs.o process.o \
- signal.o ksyms.o time.o syscalls.o usercpy.o\
- support.o ptrace.o
+OBJS = misc.o port_io.o pci.o traps.o process.o \
+ signal.o syscalls.o ptrace.o ksyms.o irq.o bitops.o strcase.o ppc_htab.o
all: head.o kernel.o
+head.o: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h
-head.o: head.s
-head.s: head.S $(TOPDIR)/include/linux/tasks.h ppc_defs.h
+ifeq ($(CONFIG_PREP),y)
+OBJS += prep_setup.o prep_time.o
+endif
+
+ifeq ($(CONFIG_PMAC),y)
+OBJS += pmac_setup.o pmac_support.o align.o pmac_time.o
+endif
+
+ifeq ($(CONFIG_MODULES),y)
+OBJS = ksyms.o
+endif
-ppc_defs.h: mk_defs
- mk_defs $@
-mk_defs: mk_defs.c
- $(HOSTCC) $(CFLAGSINC) -Wl,-static ${CFLAGS} -o mk_defs mk_defs.c
+ppc_defs.h: mk_defs.c ppc_defs.head \
+ $(TOPDIR)/include/asm/mmu.h \
+ $(TOPDIR)/include/asm/processor.h \
+ $(TOPDIR)/include/asm/pgtable.h \
+ $(TOPDIR)/include/asm/ptrace.h
+ $(CC) ${CFLAGS} -S mk_defs.c
+ cp ppc_defs.head ppc_defs.h
+ grep '^#define' mk_defs.s >>ppc_defs.h
+ rm mk_defs.s
+checks: checks.c
+ $(HOSTCC) ${CFLAGS} -o checks checks.c
+ checks
kernel.o: $(OBJS)
$(LD) -r -o kernel.o $(OBJS)
- sync
-
-dep:
- $(CPP) -M *.c > .depend
fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
+dep:
+ $(CPP) -M *.S *.c > .depend
-modules:
+modules:
dummy:
diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S
index 648c7bccf..25f2dd8a0 100644
--- a/arch/ppc/kernel/head.S
+++ b/arch/ppc/kernel/head.S
@@ -1,1077 +1,422 @@
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-#include <linux/errno.h>
-#include <linux/sys.h>
-#include <asm/ppc_machine.h>
-
-#define NEWMM 1
-#define SYNC() \
- isync; \
- sync
-
-#define STATS
/*
- * Increment a [64 bit] statistic counter
- * Uses R2, R3
+ * arch/ppc/kernel/head.S
+ *
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ * Adapted for Power Macintosh by Paul Mackerras.
+ * Low-level exception handlers and MMU support
+ * rewritten by Paul Mackerras.
+ * Copyright (C) 1996 Paul Mackerras.
+ *
+ * This file contains the low-level support and setup for the
+ * PowerPC platform, including trap and interrupt dispatch.
+ * Also included here is low-level thread/task switch support.
+ *
+ * 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.
+ *
*/
-#define BUMP(ctr) \
- lis r2,ctr@h; \
- ori r2,r2,ctr@l; \
- lwz r3,4(r2); \
- addic r3,r3,1; \
- stw r3,4(r2); \
- lwz r3,0(r2); \
- addze r3,r3; \
- stw r3,0(r2)
-
-/* The same as 'BUMP' but running unmapped (TLB code) */
-#define BUMP_UNMAPPED(ctr) \
- mfspr r0,XER; \
- lis r2,ctr@h; \
- ori r2,r2,ctr@l; \
- lis r3,0xF000; \
- andc r2,r2,r3; \
- lwz r3,4(r2); \
- addic r3,r3,1; \
- stw r3,4(r2); \
- lwz r3,0(r2); \
- addze r3,r3; \
- mtspr XER,r0; \
- stw r3,0(r2)
-
-#define DO_RFI_TRACE_UNMAPPED(mark)
-#define DO_RFI_TRACE_MAPPED(mark)
-
-#define DEFAULT_TRAP(offset) \
- li r13,0; \
- ori r13,r13,HID0_ICE; \
- mtspr HID0,r13; \
- lis r13,0xFFF00000>>16; \
- ori r13,r13,offset; \
- mtlr r13; \
- blr
-#define TRACE_TRAP(offset)
-#define DATA_CACHE_OFF() \
- mfspr r2,HID0; \
- li r3,0; \
- ori r3,r3,HID0_DCE; \
- andc r2,r2,r3; \
- mtspr HID0,r2;
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ptrace.h>
+#include <linux/sys.h>
+#include <linux/errno.h>
+#include <linux/config.h>
-#define DATA_CACHE_ON() \
- mfspr r2,HID0; \
- ori r2,r2,HID0_DCE; \
- mtspr HID0,r2;
+#define SYNC() \
+ sync; \
+ isync
-/* This instruction is not implemented on the PPC 603 */
+/* This instruction is not implemented on the PPC 603 or 601 */
#define tlbia \
- li r4,64; \
- mtspr CTR,r4; \
- lis r4,0x9000; \
+ li r4,128; \
+ mtctr r4; \
+ lis r4,0xC000; \
0: tlbie r4; \
addi r4,r4,0x1000; \
bdnz 0b
-/* Validate kernel stack - check for overflow */
-/* all regs are considered scratch since the C function will stomp them */
-#define CHECK_STACK() \
- /*lis r3,current_set@ha; \
- lwz r3,current_set@l(r3); \
- bl _EXTERN(check_stack)*/
-#if 0
-#define _CHECK_STACK() \
- mtspr SPR0,r3; \
- mtspr SPR1,r4; /* use r3,4 as scratch */ \
- lis r2,current_set@ha; \
- lwz r2,current_set@l(r2); \
- lwz r2,KERNEL_STACK_PAGE(r2); \
- /* if kernel stack is sys_stack skip check */ \
- /*lis r3,sys_stack@h; \
- ori r3,r3,sys_stack@l; \
- cmpl 0,r1,r3;*/ \
- /* check for STACK_MAGIC on kernel stack page */ \
- lis r3, 0xdead; /* STACK_MAGIC */ \
- ori r3,r3,0xbeef; \
- lwz r4,0(r2); /* get *kernel_stack_page */ \
- cmpl 0,r4,r3; \
- bne 01f; \
- /* check that ksp is > kernel page */ \
- /*li r3,0x0FFF; \
- andc r2,r2,r3; \
- andc r3,r1,r3; \
- cmp 0,r3,r2; \
- beq 02f;*/ \
- /* check that ksp and kernel stack page are on same page */ \
- cmp 0,r1,r2; \
- bge 02f; \
-01: mr r6,r1; /* setup info for call to bad_stack() */ \
- mr r5,r2; \
- bl _EXTERN(bad_stack); \
-02: mfspr r4,SPR1; \
- mfspr r3,SPR0
-#endif
-
-/* save fp regs if fp is used */
-/* assumes that r1 contains ptr to regs of task and r2 is scratch
- -- Cort */
-#define SAVE_FP_REGS() \
- /* check if fp has been used by checking msr_fp bit */ \
- lwz r2,_MSR(r1); \
- andi. r2,r2,MSR_FP; \
- bne 00f; \
- /* floating point has been used -- save fp regs */ \
- lis r2,current_set@h; \
- ori r2,r2,current_set@l; \
- addi r2,r2,TSS; \
- /*mr r2,r1;*/ \
- stfd fr0,TSS_FPR0(r2); \
- stfd fr1,TSS_FPR1(r2); \
- stfd fr2,TSS_FPR2(r2); \
- stfd fr3,TSS_FPR3(r2); \
- stfd fr4,TSS_FPR4(r2); \
- stfd fr5,TSS_FPR5(r2); \
- stfd fr6,TSS_FPR6(r2); \
- stfd fr7,TSS_FPR7(r2); \
- stfd fr8,TSS_FPR8(r2); \
- stfd fr9,TSS_FPR9(r2); \
- stfd fr10,TSS_FPR10(r2); \
- stfd fr11,TSS_FPR11(r2); \
- stfd fr12,TSS_FPR12(r2); \
- stfd fr13,TSS_FPR13(r2); \
- stfd fr14,TSS_FPR14(r2); \
- stfd fr15,TSS_FPR15(r2); \
- stfd fr16,TSS_FPR16(r2); \
- stfd fr17,TSS_FPR17(r2); \
- stfd fr18,TSS_FPR18(r2); \
- stfd fr19,TSS_FPR19(r2); \
- stfd fr20,TSS_FPR20(r2); \
- stfd fr21,TSS_FPR21(r2); \
- stfd fr22,TSS_FPR22(r2); \
- stfd fr23,TSS_FPR23(r2); \
- stfd fr24,TSS_FPR24(r2); \
- stfd fr25,TSS_FPR25(r2); \
- stfd fr26,TSS_FPR26(r2); \
- stfd fr27,TSS_FPR27(r2); \
- stfd fr28,TSS_FPR28(r2); \
- stfd fr29,TSS_FPR29(r2); \
- stfd fr30,TSS_FPR30(r2); \
- stfd fr31,TSS_FPR31(r2); \
-00:
-
-
-/* restores fp regs if fp has been used -- always restores fpscr */
-/* assumes that r1 contains ptr to regs, r2 is scratch and srr1 holds
- what will become the msr when this process executes -- Cort*/
-#define RESTORE_FP_REGS(mark) \
- /* check if restoring from _switch() */ \
- li r2, mark; \
- cmpi 0,r2,0x0f0f; \
- bne 00f; /* only need to save if called from _switch() with 0x0f0f */\
- /* check if fp has been used by checking msr_fp bit */ \
- /* srr1 contains msr */ \
- mfspr r2,SRR1; \
- andi. r2,r2,MSR_FP; \
- bne 00f; \
- /* floating point has been used -- restore fp regs */ \
- /* Hey, Rocky! Watch me pull fp regs from my stack! */ \
- lis r2,current_set@h; \
- ori r2,r2,current_set@l; \
- addi r2,r2,TSS; \
- /*mr r2,r1;*/\
- lfd fr0,TSS_FPR0(r2); \
- lfd fr1,TSS_FPR1(r2); \
- lfd fr2,TSS_FPR2(r2); \
- lfd fr3,TSS_FPR3(r2); \
- lfd fr4,TSS_FPR4(r2); \
- lfd fr5,TSS_FPR5(r2); \
- lfd fr6,TSS_FPR6(r2); \
- lfd fr7,TSS_FPR7(r2); \
- lfd fr8,TSS_FPR8(r2); \
- lfd fr9,TSS_FPR9(r2); \
- lfd fr10,TSS_FPR10(r2); \
- lfd fr11,TSS_FPR11(r2); \
- lfd fr12,TSS_FPR12(r2); \
- lfd fr13,TSS_FPR13(r2); \
- lfd fr14,TSS_FPR14(r2); \
- lfd fr15,TSS_FPR15(r2); \
- lfd fr16,TSS_FPR16(r2); \
- lfd fr17,TSS_FPR17(r2); \
- lfd fr18,TSS_FPR18(r2); \
- lfd fr19,TSS_FPR19(r2); \
- lfd fr20,TSS_FPR20(r2); \
- lfd fr21,TSS_FPR21(r2); \
- lfd fr22,TSS_FPR22(r2); \
- lfd fr23,TSS_FPR23(r2); \
- lfd fr24,TSS_FPR24(r2); \
- lfd fr25,TSS_FPR25(r2); \
- lfd fr26,TSS_FPR26(r2); \
- lfd fr27,TSS_FPR27(r2); \
- lfd fr28,TSS_FPR28(r2); \
- lfd fr29,TSS_FPR29(r2); \
- lfd fr30,TSS_FPR30(r2); \
- lfd fr31,TSS_FPR31(r2); \
-00:
-
-/* save all registers */
-#define SAVE_ALL_REGS(mark) \
- subi r1,r1,INT_FRAME_SIZE; /* Make room for frame */ \
- stmw r3,GPR3(r1); /* Save R3..R31 */ \
- stw r3,ORIG_GPR3(r1); \
- stw r0,GPR0(r1); \
- mfspr r2,SPR0; \
- stw r2,GPR1(r1); \
- mfspr r2,SPR1; \
- stw r2,GPR2(r1); \
- mfspr r2,SPR2; \
- stw r2,_NIP(r1); \
- mfspr r2,SPR3; \
- stw r2,_MSR(r1); \
- mfctr r2; \
- stw r2,_CTR(r1); \
- mflr r2; \
- stw r2,_LINK(r1); \
- mfcr r2; \
- stw r2,_CCR(r1); \
- mfspr r2,XER; \
- stw r2,_XER(r1); \
- mffs fr0; \
- stfd fr0,FPCSR(r1); \
- lis r2,_break_lwarx@h; \
- ori r2,r2,_break_lwarx@l; \
- stwcx. r2,0,r2; \
- li r2,mark; \
- stw r2,TRAP(r1); \
- lis r2,0xDEAD; \
- ori r2,r2,0xDEAD; \
- stw r2,MARKER(r1); \
- li r2,0; \
- stw r2,RESULT(r1)
-
-
-/* save registers clobbered by a page fault handler */
-#define SAVE_PAGE_FAULT_REGS(offset) \
- mfspr r2,DAR; \
- stw r2,_DAR(r1); \
- mfspr r2,DSISR; \
- stw r2,_DSISR(r1); \
- mfspr r2,PVR; /* Check for 603/603e */ \
- srwi r2,r2,16; \
- cmpi 0,r2,3; /* 603 */ \
- beq 22f; \
- cmpi 0,r2,6; /* 603e */ \
- bne 24f; \
-22: mfspr r2,HASH1; /* Note: these registers exist only on 603 */ \
- stw r2,_HASH1(r1); \
- mfspr r2,HASH2; \
- stw r2,_HASH2(r1); \
- mfspr r2,IMISS; \
- stw r2,_IMISS(r1); \
- mfspr r2,DMISS; \
- stw r2,_DMISS(r1); \
- mfspr r2,ICMP; \
- stw r2,_ICMP(r1); \
- mfspr r2,DCMP; \
- stw r2,_DCMP(r1); \
-24:
-
-#define SAVE_INT_REGS(mark) \
- mtspr SPR0,r1; /* Save current stack pointer */ \
- mtspr SPR1,r2; /* Scratch */ \
- mfcr r2; \
- mtspr SPR2,r2; \
- mfspr r2,SRR1; /* Interrupt from user/system mode */ \
- andi. r2,r2,MSR_PR; \
- beq+ 10f; /* Jump if system - already have stack */ \
- mfspr r2,SPR2; /* Restore CCR */ \
- mtcrf 0xFF,r2; \
- mfspr r2,SRR0; /* Preserve interrupt registers */ \
- mtspr SPR2,r2; \
- mfspr r2,SRR1; \
- mtspr SPR3,r2; \
- lis r2,05f@h; \
- ori r2,r2,05f@l; \
- mtspr SRR0,r2; \
- mfmsr r2; \
- ori r2,r2,MSR_|MSR_DR|MSR_IR; \
- mtspr SRR1,r2; \
- rfi; \
-05: lis r2,current_set@ha; \
- lwz r2,current_set@l(r2); \
- mfspr r1,SPR2; \
- stw r1,TSS+LAST_PC(r2); \
- mfspr r1,SPR0; \
- stw r1,TSS+USER_STACK(r2); \
- lwz r1,TSS+KSP(r2); \
- subi r1,r1,INT_FRAME_SIZE; /* Make room for frame */ \
- stw r1,TSS+PT_REGS(r2); /* Save regs pointer for 'ptrace' */ \
- lwz r1,TSS+KSP(r2); \
- b 20f; \
-10: mfspr r2,SPR2; /* Restore CCR */ \
- mtcrf 0xFF,r2; \
- mfspr r2,SRR0; /* Preserve interrupt registers */ \
- mtspr SPR2,r2; \
- mfspr r2,SRR1; \
- mtspr SPR3,r2; \
- lis r2,20f@h; \
- ori r2,r2,20f@l; \
- mtspr SRR0,r2; \
- mfmsr r2; \
- ori r2,r2,MSR_|MSR_DR|MSR_IR; \
- mtspr SRR1,r2; \
- SYNC(); \
- rfi; \
-20: SAVE_ALL_REGS(mark); \
- CHECK_STACK()
-
-#define RETURN_FROM_INT(mark) \
-90: mfmsr r0; /* Disable interrupts */ \
- li r4,0; \
- ori r4,r4,MSR_EE; \
- andc r0,r0,r4; \
- sync; /* Some chip revs need this... */ \
- mtmsr r0; \
- lis r2,intr_count@ha; /* Need to run 'bottom half' */ \
- lwz r3,intr_count@l(r2); \
- cmpi 0,r3,0; \
- bne 00f; \
- lis r4,bh_mask@ha; \
- lwz r4,bh_mask@l(r4); \
- lis r5,bh_active@ha; \
- lwz r5,bh_active@l(r5); \
- and. r4,r4,r5; \
- beq 00f; \
- addi r3,r3,1; \
- stw r3,intr_count@l(r2); \
- bl _EXTERN(_do_bottom_half); \
- lis r2,intr_count@ha; \
- lwz r3,intr_count@l(r2); \
- subi r3,r3,1; \
- stw r3,intr_count@l(r2); \
-00: lwz r2,_MSR(r1); /* Returning to user mode? */ \
- andi. r2,r2,MSR_PR; \
- beq+ 10f; /* no - no need to mess with stack */ \
-/* lis r2,kernel_pages_are_copyback@ha; \
- lwz r2,kernel_pages_are_copyback@l(r2); \
- cmpi 0,r2,0; \
- beq 05f; \
- bl _EXTERN(flush_instruction_cache); */ \
-05: lis r3,current_set@ha; /* need to save kernel stack pointer */ \
- lwz r3,current_set@l(r3); \
- /*addi r4,r1,INT_FRAME_SIZE*/; /* size of frame */ \
- lwz r4, KERNEL_STACK_PAGE(r3); \
- addi r4,r4,KERNEL_STACK_SIZE; /* reset stack pointer to top of stack page */ \
- /* stack isn't 0'd so show_task():sched.c shows highwater of stack */ \
- stw r4,TSS+KSP(r3); \
- lwz r4,STATE(r3); /* If state != 0, can't run */ \
- cmpi 0,r4,0; \
- beq 06f; \
- bl _EXTERN(schedule); \
- b 90b; \
-06: lwz r4,COUNTER(r3); /* Time quantum expired? */ \
- cmpi 0,r4,0; \
- bne 07f; \
- bl _EXTERN(schedule); \
- b 90b; \
-07: lwz r4,BLOCKED(r3); /* Check for pending unblocked signals */ \
- lwz r5,SIGNAL(r3); \
- andc. r0,r5,r4; /* Lets thru any unblocked */ \
- beq 10f; \
- mr r3,r4; \
- mr r4,r1; \
- bl _EXTERN(do_signal); \
-10: lwz r2,_NIP(r1); /* Restore environment */ \
- mtspr SRR0,r2; \
- lwz r2,_MSR(r1); \
- mtspr SRR1,r2; \
- lmw r3,GPR3(r1); \
- lwz r2,_CTR(r1); \
- mtctr r2; \
- lwz r2,_LINK(r1); \
- mtlr r2; \
- lwz r2,_XER(r1); \
- mtspr XER,r2; \
- lfd fr0,FPCSR(r1); \
- mtfsf 0xFF,fr0; \
- RESTORE_FP_REGS(mark) ; \
- lwz r2,_CCR(r1); \
- mtcrf 0xFF,r2; \
- lwz r0,GPR0(r1); \
- lwz r2,GPR2(r1); \
- lwz r1,GPR1(r1); \
- SYNC(); \
- rfi
-
-
-_TEXT()
-/*
- * This code may be executed by a bootstrap process. If so, the
- * purpose is to relocate the loaded image to it's final location
- * in memory.
- * R3: End of image
- * R4: Start of image - 0x400
- * R11: Start of command line string
- * R12: End of command line string
- * R30: 'BeBx' if this is a BeBox
- *
- */
- .globl _start
- .globl _stext
-_stext:
-_start:
- addi r4,r4,0x400 /* Point at start of image */
- li r5,0 /* Load address */
- subi r4,r4,4 /* Adjust for auto-increment */
- subi r5,r5,4
- subi r3,r3,4
-00: lwzu r0,4(r4) /* Fast move */
- stwu r0,4(r5)
- cmp 0,r3,r4
- bne 00b
- li r5,0x100 /* Actual code starts here */
- mtlr r5
- blr
+#define TOPHYS(x) (x - KERNELBASE)
-hang:
- ori r0,r0,0
- b hang
-/*
- * BeBox CPU #1 vector & code
+/* this is a very kludgey way of loading up the BATs on the
+ prep system. I'll kill this horrible macro and write
+ something clean when I have a chance -- Cort
*/
-_ORG(0x0080)
- .globl BeBox_CPU1_vector
-BeBox_CPU1_vector:
- .long 0
-BeBox_CPU1_reset:
- li r1,BeBox_CPU1_vector@l
- li r2,0
- stw r2,0(r1)
-00: lwz r2,0(r1)
- cmpi 0,r2,0
- bne 10f
- li r2,10000
- mtctr r2
-02: nop
- bdnz 02b
- b 00b
-10: mtlr r1
- blr
+#define LOAD_BATS(RA,RB) \
+ mfspr RA,PVR ; \
+ srwi r5,r5,16 ; \
+ cmpi 0,RA,1 ; \
+ beq 199f ; \
+ /* load bats for 60x */ ; \
+ lis RA,BAT0@h ; \
+ ori RA,RA,BAT0@l ; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT0U,RB ; \
+ mtspr DBAT0U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT0L,RB ; \
+ mtspr DBAT0L,RB ; \
+ lis RA,BAT1@h ; \
+ ori RA,RA,BAT1@l ; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT1U,RB ; \
+ mtspr DBAT1U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT1L,RB ; \
+ mtspr DBAT1L,RB ; \
+ lis RA,BAT2@h ; \
+ ori RA,RA,BAT2@l ; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT2U,RB ; \
+ mtspr DBAT2U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT2L,RB ; \
+ mtspr DBAT2L,RB ; \
+ lis RA,BAT3@h ; \
+ ori RA,RA,BAT3@l ; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT3U,RB ; \
+ mtspr DBAT3U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT3L,RB ; \
+ mtspr DBAT3L,RB ; \
+ b 200f ; \
+199: /*load bats for 601 */ ; \
+ lis RA,BAT0_601@h ; \
+ ori RA,RA,BAT0_601@l; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT0U,RB ; \
+ mtspr DBAT0U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT0L,RB ; \
+ mtspr DBAT0L,RB ; \
+ lis RA,BAT1_601@h ; \
+ ori RA,RA,BAT1_601@l; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT1U,RB ; \
+ mtspr DBAT1U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT1L,RB ; \
+ mtspr DBAT1L,RB ; \
+ lis RA,BAT2_601@h ; \
+ ori RA,RA,BAT2_601@l; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT2U,RB ; \
+ mtspr DBAT2U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT2L,RB ; \
+ mtspr DBAT2L,RB ; \
+ lis RA,BAT3_601@h ; \
+ ori RA,RA,BAT3_601@l; \
+ addis RA,RA,-KERNELBASE@h;\
+ lwz RB,0(RA) ; \
+ mtspr IBAT3U,RB ; \
+ mtspr DBAT3U,RB ; \
+ lwz RB,4(RA) ; \
+ mtspr IBAT3L,RB ; \
+ mtspr DBAT3L,RB ; \
+200:
-_ORG(0x0100)
-/* Hard Reset */
- .globl HardReset
-HardReset:
- b Reset
-_ORG(0x0200)
- b MachineCheck
-
-_ORG(0x0300)
- b DataAccess
-
-_ORG(0x0400)
- b InstructionAccess
-
-_ORG(0x0500)
- b HardwareInterrupt
-
-_ORG(0x0600)
- b Alignment
-
-_ORG(0x0700)
- b ProgramCheck
-
-_ORG(0x0800)
- b FloatingPointCheck
-
-/* Decrementer register - ignored for now... */
-_ORG(0x0900)
-/* TRACE_TRAP(0x900) */
- mtspr SPR0,r1
- lis r1,0x7FFF
- ori r1,r1,0xFFFF
- mtspr DEC,r1
- mfspr r1,SPR0
-#if 0
- SYNC
-#endif
- rfi
-_ORG(0x0A00)
-DEFAULT_TRAP(0x0A00)
-_ORG(0x0B00)
-DEFAULT_TRAP(0x0B00)
-
-/*
- * System call
- */
-_ORG(0x0C00)
- b SystemCall
+ .text
+ .globl _stext
+_stext:
-_ORG(0x0D00)
- b SingleStep
+#ifdef CONFIG_PREP
+ . = 0x100
+_GLOBAL(HardReset)
+ b _start
-_ORG(0x0E00)
-DEFAULT_TRAP(0x0E00)
-_ORG(0x0F00)
-DEFAULT_TRAP(0x0F00)
+#endif /* CONFIG_PREP */
+#ifdef CONFIG_PMAC
/*
- * Handle TLB Miss on an instruction load
+ * _start is defined this way because the XCOFF loader in the OpenFirmware
+ * on the powermac expects the entry point to be a procedure descriptor.
*/
-_ORG(0x1000)
-/* Note: It is *unsafe* to use the TRACE TRAP macro here since there */
-/* could be a 'trace' in progress when the TLB miss occurs. */
-/* TRACE_TRAP(0x1000) */
- b InstructionTLBMiss
+ .text
+ .globl _start
+_start:
+ .long TOPHYS(__start),0,0
/*
- * Handle TLB Miss on a data item load
+ * Enter here with the kernel text, data and bss loaded starting at
+ * 0, running with virtual == physical mapping.
+ * r5 points to the prom entry point (the client interface handler
+ * address). Address translation is turned on, with the prom
+ * managing the hash table. Interrupts are disabled. The stack
+ * pointer (r1) points to just below the end of the half-meg region
+ * from 0x380000 - 0x400000, which is mapped in already.
*/
-_ORG(0x1100)
-/* TRACE_TRAP(0x1100) */
- b DataLoadTLBMiss
+ .globl __start
+__start:
/*
- * Handle TLB Miss on a store operation
+ * Use the first pair of BAT registers to map the 1st 8MB
+ * of RAM to KERNELBASE.
*/
-_ORG(0x1200)
-/* TRACE_TRAP(0x1200) */
- b DataStoreTLBMiss
-
-_ORG(0x1300)
-InstructionAddressBreakpoint:
- DEFAULT_TRAP(0x1300)
-
-_ORG(0x1400)
-SystemManagementInterrupt:
- DEFAULT_TRAP(0x1400)
-
-_ORG(0x1500)
+ mfspr r9,PVR
+ rlwinm r9,r9,16,16,31 /* r9 = 1 for 601, 4 for 604 */
+ cmpi 0,r9,1
+ lis r7,KERNELBASE@h
+ bne 4f
+ ori r7,r7,4 /* set up BAT registers for 601 */
+ li r8,0x7f
+ b 5f
+4: ori r7,r7,0xff /* set up BAT registers for 604 */
+ li r8,2
+ mtspr DBAT0U,r7
+ mtspr DBAT0L,r8
+5: mtspr IBAT0U,r7
+ mtspr IBAT0L,r8
+ isync
/*
- * This space [buffer] is used to forceably flush the data cache when
- * running in copyback mode. This is necessary IFF the data cache could
- * contain instructions for which the instruction cache has stale data.
- * Since the instruction cache NEVER snoops the data cache, memory must
- * be made coherent with the data cache to insure that the instruction
- * cache gets a valid instruction stream. Note that this flushing is
- * only performed when switching from system to user mode since this is
- * the only juncture [as far as the OS goes] where the data cache may
- * contain instructions, e.g. after a disk read.
+ * Now we have the 1st 8M of RAM mapped at KERNELBASE, so we can
+ * refer to addresses of data items, procedures, etc. normally.
*/
-#define NUM_CACHE_LINES 128*4
-#define CACHE_LINE_SIZE 32
-cache_flush_buffer:
- .space NUM_CACHE_LINES*CACHE_LINE_SIZE /* CAUTION! these need to match hardware */
-
-#if NUM_CACHE_LINES < 512
-_ORG(0x4000)
-#endif
+ lis r7,start_here@ha /* jump up to our copy at KERNELBASE */
+ addi r7,r7,start_here@l
+ mtlr r7
+ blr
+#endif /* CONFIG_PMAC */
-/* changed to use r3 as residual pointer (as firmware does), that's all -- Cort */
-/*
- * Hardware reset [actually from bootstrap]
- * Initialize memory management & call secondary init
- * Registers initialized by bootstrap:
- * R11: Start of command line string
- * R12: End of command line string
- * R28: Residual data
- * R29: Total Memory Size
- * R30: 'BeBx' if this is a BeBox
- */
-Reset:
- lis r7,0xF000 /* To mask upper 4 bits */
-/* set pointer to residual data */
- lis r1,resptr@h
- ori r1,r1,resptr@l
- andc r1,r1,r7
-/* changed to use r3 as residual pointer (as firmware does) -- Cort */
-/* this is only a ptr, the actual data is copied in mmu_init */
- stw r3,0(r1)
-
-/* Copy argument string */
- li r0,0 /* Null terminate string */
- stb r0,0(r12)
- lis r1,cmd_line@h
- ori r1,r1,cmd_line@l
- andc r1,r1,r7 /* No MMU yet - need unmapped address */
- subi r1,r1,1
- subi r11,r11,1
-00: lbzu r0,1(r11)
- cmpi 0,r0,0
- stbu r0,1(r1)
- bne 00b
-#define IS_BE_BOX 0x42654278 /* 'BeBx' */
- lis r1,isBeBox@h
- ori r1,r1,isBeBox@l
- andc r1,r1,r7
-/* See if this is a CPU other than CPU#1 */
-/* This [currently] happens on the BeBox */
- lwz r2,0(r1)
- cmpi 0,r2,0
- bne Reset_BeBox_CPU1
-/* Save machine type indicator */
- li r2,0
- lis r3,IS_BE_BOX>>16
- ori r3,r3,IS_BE_BOX&0xFFFF
- cmp 0,r30,r3
- bne 00f
- li r2,1
- mr r11,r28
- mr r12,r29
- lis r5,BeBox_CPU1_vector@h
- ori r5,r5,BeBox_CPU1_vector@l
- andc r5,r5,r7 /* Tell CPU #1 where to go */
-00: stw r2,0(r1)
- stw r30,4(r1)
-
-#if 0
- lis r1,sys_stack@h
- ori r1,r1,sys_stack@l
-#else
- lis r1,init_kernel_stack@h
- ori r1,r1,init_kernel_stack@l
-#endif
- addi r1,r1,0x1000 /* top of stack */
-#if 0
- li r2,0x0FFF /* Mask stack address down to page boundary */
-#endif
- andc r1,r1,r2
- subi r1,r1,INT_FRAME_SIZE /* Padding for first frame */
- li r2,0 /* TOC pointer for nanokernel */
- li r0,MSR_ /* Make sure FPU enabled */
- mtmsr r0
- lis r3,_edata@h /* Clear BSS */
- ori r3,r3,_edata@l
- andc r3,r3,r7 /* make unmapped address */
- lis r4,_end@h
- ori r4,r4,_end@l
- andc r4,r4,r7 /* make unmapped address */
- subi r3,r3,4
- li r0,0
-00: stwu r0,4(r3)
- cmp 0,r3,r4
- blt 00b
-#if 0
-/* Save total memory size (passed from bootstrap) */
- lis r3,_TotalMemory@h
- ori r3,r3,_TotalMemory@l
- andc r3,r3,r7 /* make unmapped address */
- stw r29,0(r3)
-#endif
-/* Initialize BAT registers */
- lis r3,BAT0@h
- ori r3,r3,BAT0@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT0U,r0
- mtspr DBAT0U,r0
- lwz r0,4(r3)
- mtspr IBAT0L,r0
- mtspr DBAT0L,r0
- lis r3,BAT1@h
- ori r3,r3,BAT1@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT1U,r0
- mtspr DBAT1U,r0
- lwz r0,4(r3)
- mtspr IBAT1L,r0
- mtspr DBAT1L,r0
-/* this BAT mapping will cover all of kernel space */
-#ifdef NEWMM
- lis r3,BAT2@h
- ori r3,r3,BAT2@l
-#else
- lis r3,TMP_BAT2@h
- ori r3,r3,TMP_BAT2@l
-#endif
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT2U,r0
- mtspr DBAT2U,r0
- lwz r0,4(r3)
- mtspr IBAT2L,r0
- mtspr DBAT2L,r0
-#if 1
- lis r3,BAT3@h
- ori r3,r3,BAT3@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT3U,r0
- mtspr DBAT3U,r0
- lwz r0,4(r3)
- mtspr IBAT3L,r0
- mtspr DBAT3L,r0
-#endif
-/* Now we can turn on the MMU */
- mfmsr r3
- ori r3,r3,MSR_DR|MSR_IR
- mtspr SRR1,r3
- lis r3,10f@h
- ori r3,r3,10f@l
- mtspr SRR0,r3
-DO_RFI_TRACE_UNMAPPED(0xDEAD0000)
- SYNC
- rfi /* enables MMU */
-10: bl _EXTERN(MMU_init) /* initialize MMU environment */
-DO_RFI_TRACE_MAPPED(0xDEAD0100)
-/* Withdraw BAT2->RAM mapping */
- lis r7,0xF000 /* To mask upper 4 bits */
- lis r3,20f@h
- ori r3,r3,20f@l
- andc r3,r3,r7 /* make unmapped address */
- mtspr SRR0,r3
- mfmsr r3
- li r4,MSR_DR|MSR_IR
- andc r3,r3,r4
- mtspr SRR1,r3
- SYNC
-DO_RFI_TRACE_MAPPED(0xDEAD0200)
- SYNC
- rfi
-20:
-
-DO_RFI_TRACE_UNMAPPED(0xDEAD0400)
-20: lis r3,BAT2@h
- ori r3,r3,BAT2@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT2U,r0
- mtspr DBAT2U,r0
- lwz r0,4(r3)
- mtspr IBAT2L,r0
- mtspr DBAT2L,r0
-/* Load up the kernel context */
- lis r2,init_task@h
- ori r2,r2,init_task@l
- addi r2,r2,TSS
- andc r2,r2,r7 /* make unmapped address */
- SYNC /* Force all PTE updates to finish */
- tlbia /* Clear all TLB entries */
- lis r3,_SDR1@h
- ori r3,r3,_SDR1@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r3,0(r3)
- mtspr SDR1,r3
- lwz r0,MMU_SEG0(r2)
- mtsr SR0,r0
- lwz r0,MMU_SEG1(r2)
- mtsr SR1,r0
- lwz r0,MMU_SEG2(r2)
- mtsr SR2,r0
- lwz r0,MMU_SEG3(r2)
- mtsr SR3,r0
- lwz r0,MMU_SEG4(r2)
- mtsr SR4,r0
- lwz r0,MMU_SEG5(r2)
- mtsr SR5,r0
- lwz r0,MMU_SEG6(r2)
- mtsr SR6,r0
- lwz r0,MMU_SEG7(r2)
- mtsr SR7,r0
- lwz r0,MMU_SEG8(r2)
- mtsr SR8,r0
- lwz r0,MMU_SEG9(r2)
- mtsr SR9,r0
- lwz r0,MMU_SEG10(r2)
- mtsr SR10,r0
- lwz r0,MMU_SEG11(r2)
- mtsr SR11,r0
- lwz r0,MMU_SEG12(r2)
- mtsr SR12,r0
- lwz r0,MMU_SEG13(r2)
- mtsr SR13,r0
- lwz r0,MMU_SEG14(r2)
- mtsr SR14,r0
- lwz r0,MMU_SEG15(r2)
- mtsr SR15,r0
-/* Now turn on the MMU for real! */
- mfmsr r3
- ori r3,r3,MSR_DR|MSR_IR
- mtspr SRR1,r3
- lis r3,30f@h
- ori r3,r3,30f@l
- mtspr SRR0,r3
-DO_RFI_TRACE_UNMAPPED(0xDEAD0500)
- SYNC
- rfi /* enables MMU */
-30:
-/* Turn on L1 Data Cache */
- mfspr r3,HID0 /* Caches are controlled by this register */
- ori r4,r3,(HID0_ICE|HID0_ICFI)
- ori r3,r3,(HID0_ICE)
- ori r4,r4,(HID0_DCE|HID0_DCI)
- ori r3,r3,(HID0_DCE)
- sync
- mtspr HID0,r4
- mtspr HID0,r3
-/* L1 cache enable */
- mfspr r2,PVR /* Check for 603/603e */
- srwi r2,r2,16
- cmpi 0,r2,4 /* 604 */
- bne 40f
- mfspr r3,HID0 /* Turn on 604 specific features */
- ori r3,r3,(HID0_SIED|HID0_BHTE)
- mtspr HID0,r3
-40: b _EXTERN(start_kernel) /* call main code */
- .long 0 # Illegal!
-
/*
- * BeBox CPU #2 runs here
+ * Macros for storing registers into and loading registers from
+ * exception frames.
*/
-Reset_BeBox_CPU1:
- lis r1,CPU1_stack@h
- ori r1,r1,CPU1_stack@l
- li r2,0x0FFF /* Mask stack address down to page boundary */
- andc r1,r1,r2
- subi r1,r1,INT_FRAME_SIZE /* Padding for first frame */
- lis r30,CPU1_trace@h
- ori r30,r30,CPU1_trace@l
- andc r30,r30,r7
- li r5,1
- stw r5,0(r30)
- li r2,0 /* TOC pointer for nanokernel */
- li r0,MSR_ /* Make sure FPU enabled */
- mtmsr r0
-/* Initialize BAT registers */
- lis r3,BAT0@h
- ori r3,r3,BAT0@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT0U,r0
- mtspr DBAT0U,r0
- lwz r0,4(r3)
- mtspr IBAT0L,r0
- mtspr DBAT0L,r0
- lis r3,BAT1@h
- ori r3,r3,BAT1@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT1U,r0
- mtspr DBAT1U,r0
- lwz r0,4(r3)
- mtspr IBAT1L,r0
- mtspr DBAT1L,r0
- lis r3,TMP_BAT2@h
- ori r3,r3,TMP_BAT2@l
- andc r3,r3,r7 /* make unmapped address */
- lwz r0,0(r3)
- mtspr IBAT2U,r0
- mtspr DBAT2U,r0
- lwz r0,4(r3)
- mtspr IBAT2L,r0
- mtspr DBAT2L,r0
-/* Now we can turn on the MMU */
- mfmsr r3
- ori r3,r3,MSR_DR|MSR_IR
- mtspr SRR1,r3
- lis r3,10f@h
- ori r3,r3,10f@l
- mtspr SRR0,r3
- li r5,2
- stw r5,0(r30)
- SYNC
- rfi /* enables MMU */
-10:
- lis r30,CPU1_trace@h
- ori r30,r30,CPU1_trace@l
- li r5,3
- stw r5,0(r30)
- bl _EXTERN(BeBox_CPU1)
-
-/*
- * Machine Check (Bus Errors, etc)
- */
-MachineCheck:
- TRACE_TRAP(0x0200)
- SAVE_INT_REGS(0x0200)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(MachineCheckException)
- RETURN_FROM_INT(0x0200)
-
-/*
- * Data Access exception
- */
-DataAccess:
- SAVE_INT_REGS(0x0300)
-#if 1
- mfspr r3, DAR
- mfspr r4, DSISR
- li r5, 0 /* not a text fault */
- mr r6, r1
- bl _EXTERN(new_page_fault)
-#else
- SAVE_PAGE_FAULT_REGS(0x0D00)
- mr r3,r1
- bl _EXTERN(DataAccessException)
-#endif
- RETURN_FROM_INT(0x0300)
+#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+#define SAVE_FPR(n, base) stfd n,TSS_FPR0+8*(n)(base)
+#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
+#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
+#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
+#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
+#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
+#define REST_FPR(n, base) lfd n,TSS_FPR0+8*(n)(base)
+#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
+#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
+#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
+#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
+#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
/*
- * Instruction Access Exception
+ * Exception entry code. This code runs with address translation
+ * turned off, i.e. using physical addresses.
+ * We assume sprg3 has the physical address of the current
+ * task's thread_struct.
*/
-InstructionAccess:
- SAVE_INT_REGS(0x0400)
-#if 1
- mfspr r3, SPR2 /* srr0 was saved here */
- mfspr r4, SPR3 /* srr1 was saved here */
- li r5, 1 /* a text fault */
- mr r6, r1
- bl _EXTERN(new_page_fault)
-#else
- SAVE_PAGE_FAULT_REGS(0x0D00)
- mr r3,r1
- bl _EXTERN(InstructionAccessException)
-#endif
- RETURN_FROM_INT(0x0400)
-
+#define EXCEPTION_PROLOG \
+0: mtspr SPRG0,r20; \
+ mtspr SPRG1,r21; \
+ mfcr r20; \
+ mfspr r21,SRR1; /* test whether from user or kernel */\
+ andi. r21,r21,MSR_PR; \
+ mr r21,r1; /* from kernel - use current sp */\
+ beq 1f; \
+ mfspr r21,SPRG3; /* from user - load kernel sp */\
+ lwz r21,KSP(r21); \
+1: addis r21,r21,-KERNELBASE@h; /* convert sp to physical */ \
+ subi r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
+ stw r1,GPR1(r21); \
+ stw r1,0(r21); \
+ addis r1,r21,KERNELBASE@h; /* set new kernel sp */ \
+ stw r20,_CCR(r21); /* save registers */ \
+ stw r22,GPR22(r21); \
+ stw r23,GPR23(r21); \
+ mfspr r20,SPRG0; \
+ stw r20,GPR20(r21); \
+ mfspr r22,SPRG1; \
+ stw r22,GPR21(r21); \
+ mflr r20; \
+ stw r20,_LINK(r21); \
+ mfctr r22; \
+ stw r22,_CTR(r21); \
+ mfspr r20,XER; \
+ stw r20,_XER(r21); \
+ mfspr r22,SRR0; \
+ mfspr r23,SRR1; /* we can now take exceptions */\
+ stw r0,GPR0(r21); \
+ stw r2,GPR2(r21); \
+ SAVE_4GPRS(3, r21);
/*
- * Hardware Interrupt
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR0), and r23 (SRR1).
*/
-HardwareInterrupt:
- SAVE_INT_REGS(0x0500)
- BUMP(__Hardware_Interrupts)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(handle_IRQ)
- RETURN_FROM_INT(0x0500)
/*
- * Alignment
- */
-Alignment:
- TRACE_TRAP(0x0600)
- SAVE_INT_REGS(0x0600)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(AlignmentException)
- RETURN_FROM_INT(0x0600)
-
-/*
- * Illegal instruction
+ * Exception vectors.
*/
+#define STD_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ EXCEPTION_PROLOG; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,MSR_KERNEL; \
+ bl transfer_to_handler; \
+ .long hdlr; \
+ .long int_return
+
+#ifndef CONFIG_PREP
+/* System reset */
+ STD_EXCEPTION(0x100, Reset, UnknownException)
+#endif /* ndef CONFIG_PREP */
+
+/* Machine check */
+ STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
+
+/* Data access exception */
+ . = 0x300
+DataAccess:
+ EXCEPTION_PROLOG
+ mfspr r20,DSISR
+ andis. r0,r20,0x8470 /* weird error? */
+ bne 1f /* if not, try to put a PTE */
+ mfspr r3,DAR /* into the hash table */
+ rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */
+ rlwimi r4,r20,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ mfspr r5,SPRG3 /* phys addr of TSS */
+ bl hash_page
+1: stw r20,_DSISR(r21)
+ mr r5,r20
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ bl transfer_to_handler
+ .long do_page_fault
+ .long int_return
+
+/* Instruction access exception */
+ . = 0x400
+InstructionAccess:
+ EXCEPTION_PROLOG
+ andis. r0,r23,0x4000 /* no pte found? */
+ beq 1f /* if so, try to put a PTE */
+ mr r3,r22 /* into the hash table */
+ rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */
+ mr r20,r23 /* SRR1 has reason bits */
+ mfspr r5,SPRG3 /* phys addr of TSS */
+ bl hash_page
+1: addi r3,r1,STACK_FRAME_OVERHEAD
+ mr r4,r22
+ mr r5,r23
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ bl transfer_to_handler
+ .long do_page_fault
+ .long int_return
+
+/* External interrupt */
+ STD_EXCEPTION(0x500, HardwareInterrupt, handle_IRQ)
+
+/* Alignment exception */
+ . = 0x600
+Alignment:
+ EXCEPTION_PROLOG
+ mfspr r4,DAR
+ stw r4,_DAR(r21)
+ mfspr r5,DSISR
+ stw r5,_DSISR(r21)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ bl transfer_to_handler
+ .long AlignmentException
+ .long int_return
+
+/* Program check exception */
+ . = 0x700
ProgramCheck:
- TRACE_TRAP(0x0700)
- SAVE_INT_REGS(0x0700)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(ProgramCheckException)
- RETURN_FROM_INT(0x0700)
-
-/*
- * Single Step Exception
- */
-SingleStep:
- SAVE_INT_REGS(0x0D00)
- SAVE_PAGE_FAULT_REGS(0x0D00)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(SingleStepException)
-#if 0
- bl _EXTERN(flush_instruction_cache)
-#endif
- RETURN_FROM_INT(0x0D00)
+ EXCEPTION_PROLOG
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ bl transfer_to_handler
+ .long ProgramCheckException
+ .long int_return
+
+/* Floating-point unavailable */
+ . = 0x800
+FPUnavailable:
+ EXCEPTION_PROLOG
+ bne load_up_fpu /* if from user, just load it up */
+ li r20,MSR_KERNEL
+ bl transfer_to_handler /* if from kernel, take a trap */
+ .long KernelFP
+ .long int_return
+
+/* Decrementer */
+#ifdef CONFIG_PREP
+/* - ignored for now... */
+_ORG(0x0900)
+ mtspr SPRG0,r1
+ lis r1,0x7FFF
+ ori r1,r1,0xFFFF
+ mtspr DEC,r1
+ mfspr r1,SPRG0
+ rfi
+#endif /* CONFIG_PREP */
+#ifdef CONFIG_PMAC
+ STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
+#endif /* CONFIG_PMAC */
-/*
- * Floating point [not available, etc]
- */
-FloatingPointCheck:
- SAVE_INT_REGS(0x0800)
- mr r3,r1 /* Set pointer to saved regs */
- bl _EXTERN(FloatingPointCheckException)
- cmpi 0,r3,MSR_FP /* check if fp was turned on by handler */
- bne 00f
- RETURN_FROM_INT(0x0f0f) /* 0xf0f tells to restore fp regs */
-00: RETURN_FROM_INT(0x0200)
+ STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
+ STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
-/*
- * System Call exception
- */
+/* System call */
+ . = 0xc00
SystemCall:
- SAVE_INT_REGS(0x0C00)
- lwz r2,_CCR(r1) /* Clear SO bit in CR */
- lis r9,0x1000
- andc r2,r2,r9
- stw r2,_CCR(r1)
- cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
- bne+ 10f
- mr r3,r1
- bl _EXTERN(sys_sigreturn)
- cmpi 0,r3,0 /* Check for restarted system call */
- bge 99f
- b 20f
-10: lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- lwz r2,TASK_FLAGS(r2)
- andi. r2,r2,PF_TRACESYS
- bne 50f
-
- lis r2,sys_call_table@h
- ori r2,r2,sys_call_table@l
- slwi r0,r0,2
- lwzx r2,r2,r0 /* Fetch system call handler [ptr] */
-#if 1
- cmpi 0,r2,0 /* make sure syscall handler not 0 */
- beq 99f
- cmpi 0,r0,NR_syscalls<<2 /* make sure syscallnum in bounds */
- bgt 99f
-#endif
- mtlr r2
- mr r9,r1
- blrl /* Call handler */
-
-20: stw r3,RESULT(r1) /* Save result */
- cmpi 0,r3,0
- bge 30f
- neg r3,r3
- cmpi 0,r3,ERESTARTNOHAND
- bne 22f
- li r3,EINTR
-22: lwz r2,_CCR(r1) /* Set SO bit in CR */
- oris r2,r2,0x1000
- stw r2,_CCR(r1)
-30: stw r3,GPR3(r1) /* Update return value */
- b 99f
-/* Traced system call support */
-50: bl _EXTERN(syscall_trace)
- lwz r0,GPR0(r1) /* Restore original registers */
- lwz r3,GPR3(r1)
- lwz r4,GPR4(r1)
- lwz r5,GPR5(r1)
- lwz r6,GPR6(r1)
- lwz r7,GPR7(r1)
- lwz r8,GPR8(r1)
- lwz r9,GPR9(r1)
- lis r2,sys_call_table@h
- ori r2,r2,sys_call_table@l
- slwi r0,r0,2
- lwzx r2,r2,r0 /* Fetch system call handler [ptr] */
- mtlr r2
- mr r9,r1
- blrl /* Call handler */
- stw r3,RESULT(r1) /* Save result */
- cmpi 0,r3,0
- bge 60f
- neg r3,r3
- cmpi 0,r3,ERESTARTNOHAND
- bne 52f
- li r3,EINTR
-52: lwz r2,_CCR(r1) /* Set SO bit in CR */
- oris r2,r2,0x1000
- stw r2,_CCR(r1)
-60: stw r3,GPR3(r1) /* Update return value */
- bl _EXTERN(syscall_trace)
-99:
- RETURN_FROM_INT(0x0C00)
+ EXCEPTION_PROLOG
+ stw r3,ORIG_GPR3(r21)
+ li r20,MSR_KERNEL
+ rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
+ bl transfer_to_handler
+ .long DoSyscall
+ .long int_return
+
+/* Single step - not used on 601 */
+ STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
+
+ STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
+ STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
/*
- * Handle TLB miss for instruction
+ * Handle TLB miss for instruction on 603/603e.
+ * Note: we get an alternate set of r0 - r3 to use automatically.
*/
+ . = 0x1000
InstructionTLBMiss:
- BUMP_UNMAPPED(__Instruction_TLB_Misses)
mfctr r0 /* Need to save this - CTR can't be touched! */
mfspr r2,HASH1 /* Get PTE pointer */
mfspr r3,ICMP /* Partial item compare value */
@@ -1080,37 +425,47 @@ InstructionTLBMiss:
subi r2,r2,8 /* Preset pointer */
10: lwzu r1,8(r2) /* Get next PTE */
cmp 0,r1,r3 /* Found entry yet? */
- bdne 10b /* Jump back if not, until CTR==0 */
+ bdnzf 2,10b /* Jump back if not, until CTR==0 */
bne 30f /* Try secondary hash if CTR==0 */
lwz r1,4(r2) /* Get second word of entry */
-#if 0
- andi. r3,r1,0x08 /* Check guard bit - invalid access if set */
- bne InstructionFetchError
-#endif
- andi. r3,r1,0x100 /* Check R bit (referenced) */
- bne 20f /* If set, all done */
- ori r1,r1,0x100 /* Set bit */
- stw r1,4(r2) /* Update memory image */
20: mtctr r0 /* Restore CTR */
mfspr r3,SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
mfspr r0,IMISS /* Set to update TLB */
mtspr RPA,r1
tlbli r0
-#if 0
- SYNC
-#endif
rfi /* All done */
/* Secondary hash */
30: andi. r1,r3,0x40 /* Already doing secondary hash? */
bne InstructionAddressInvalid /* Yes - item not in hash table */
mfspr r2,HASH2 /* Get hash table pointer */
ori r3,r3,0x40 /* Set secondary hash */
- b 00b /* Try lookup again */
+ b 00b /* Try lookup again */
+InstructionAddressInvalid:
+ mfspr r3,SRR1
+ rlwinm r1,r3,9,6,6 /* Get load/store bit */
+ addis r1,r1,0x4000 /* Set bit 1 -> PTE not found */
+ mtspr DSISR,r1
+ mtctr r0 /* Restore CTR */
+ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
+ or r2,r2,r1
+ mtspr SRR1,r2
+ mfspr r1,IMISS /* Get failing address */
+ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
+ beq 20f /* Jump if big endian */
+ xori r1,r1,3
+20: mtspr DAR,r1 /* Set fault address */
+ mfmsr r0 /* Restore "normal" registers */
+ xoris r0,r0,MSR_TGPR>>16
+ mtcrf 0x80,r3 /* Restore CR0 */
+ sync /* Some chip revs have problems here... */
+ mtmsr r0
+ b InstructionAccess
/*
- * Handle TLB miss for DATA Load operation
- */
+ * Handle TLB miss for DATA Load operation on 603/603e
+ */
+ . = 0x1100
DataLoadTLBMiss:
mfctr r0 /* Need to save this - CTR can't be touched! */
mfspr r2,HASH1 /* Get PTE pointer */
@@ -1120,36 +475,47 @@ DataLoadTLBMiss:
subi r2,r2,8 /* Preset pointer */
10: lwzu r1,8(r2) /* Get next PTE */
cmp 0,r1,r3 /* Found entry yet? */
- bdne 10b /* Jump back if not, until CTR==0 */
+ bdnzf 2,10b /* Jump back if not, until CTR==0 */
bne 30f /* Try secondary hash if CTR==0 */
lwz r1,4(r2) /* Get second word of entry */
- andi. r3,r1,0x100 /* Check R bit (referenced) */
- ori r1,r1,0x100 /* Set bit */
- bne 20f /* If set, all done */
- stw r1,4(r2) /* Update memory image */
20: mtctr r0 /* Restore CTR */
mfspr r3,SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
mfspr r0,DMISS /* Set to update TLB */
mtspr RPA,r1
-/* SYNC() */
tlbld r0
-#if 0
- SYNC
-#endif
rfi /* All done */
/* Secondary hash */
30: andi. r1,r3,0x40 /* Already doing secondary hash? */
bne DataAddressInvalid /* Yes - item not in hash table */
mfspr r2,HASH2 /* Get hash table pointer */
ori r3,r3,0x40 /* Set secondary hash */
- b 00b /* Try lookup again */
+ b 00b /* Try lookup again */
+DataAddressInvalid:
+ mfspr r3,SRR1
+ rlwinm r1,r3,9,6,6 /* Get load/store bit */
+ addis r1,r1,0x4000 /* Set bit 1 -> PTE not found */
+ mtspr DSISR,r1
+ mtctr r0 /* Restore CTR */
+ andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
+ mtspr SRR1,r2
+ mfspr r1,DMISS /* Get failing address */
+ rlwinm. r2,r2,0,31,31 /* Check for little endian access */
+ beq 20f /* Jump if big endian */
+ xori r1,r1,3
+20: mtspr DAR,r1 /* Set fault address */
+ mfmsr r0 /* Restore "normal" registers */
+ xoris r0,r0,MSR_TGPR>>16
+ mtcrf 0x80,r3 /* Restore CR0 */
+ sync /* Some chip revs have problems here... */
+ mtmsr r0
+ b DataAccess
/*
- * Handle TLB miss for DATA STORE
+ * Handle TLB miss for DATA Store on 603/603e
*/
+ . = 0x1200
DataStoreTLBMiss:
- BUMP_UNMAPPED(__DataStore_TLB_Misses)
mfctr r0 /* Need to save this - CTR can't be touched! */
mfspr r2,HASH1 /* Get PTE pointer */
mfspr r3,DCMP /* Partial item compare value */
@@ -1158,26 +524,15 @@ DataStoreTLBMiss:
subi r2,r2,8 /* Preset pointer */
10: lwzu r1,8(r2) /* Get next PTE */
cmp 0,r1,r3 /* Found entry yet? */
- bdne 10b /* Jump back if not, until CTR==0 */
+ bdnzf 2,10b /* Jump back if not, until CTR==0 */
bne 30f /* Try secondary hash if CTR==0 */
lwz r1,4(r2) /* Get second word of entry */
- andi. r3,r1,0x80 /* Check C bit (changed) */
-#if 0 /* Note: no validation */
- beq 40f /* If not set (first time) validate access */
-#else
- ori r1,r1,0x180 /* Set changed, accessed */
- bne 20f
- stw r1,4(r2)
-#endif
20: mtctr r0 /* Restore CTR */
mfspr r3,SRR1 /* Need to restore CR0 */
mtcrf 0x80,r3
mfspr r0,DMISS /* Set to update TLB */
mtspr RPA,r1
tlbld r0
-#if 0
- SYNC
-#endif
rfi /* All done */
/* Secondary hash */
30: andi. r1,r3,0x40 /* Already doing secondary hash? */
@@ -1185,229 +540,980 @@ DataStoreTLBMiss:
mfspr r2,HASH2 /* Get hash table pointer */
ori r3,r3,0x40 /* Set secondary hash */
b 00b /* Try lookup again */
-/* PTE found - validate access */
-40: rlwinm. r3,r1,30,0,1 /* Extract PP bits */
- bge- 50f /* Jump if PP=0,1 */
- andi. r3,r1,1
- beq+ 70f /* Access OK */
- b WriteProtectError /* Not OK - fail! */
-50: mfspr r3,SRR1 /* Check privilege */
- andi. r3,r3,MSR_PR
- beq+ 60f /* Jump if supervisor mode */
- mfspr r3,DMISS /* Get address */
- mfsrin r3,r3 /* Get segment register */
- andis. r3,r3,0x2000 /* If Kp==0, OK */
- beq+ 70f
- b WriteProtectError /* Bad access */
-60: mfspr r3,DMISS /* Get address */
- mfsrin r3,r3 /* Get segment register */
- andis. r3,r3,0x4000 /* If Ks==0, OK */
- beq+ 70f
- b WriteProtectError /* Bad access */
-70: ori r1,r1,0x180 /* Set changed, accessed */
- stw r1,4(r2) /* Update PTE in memory */
- b 20b
-
+
+/* Instruction address breakpoint exception (on 603/604) */
+ STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
+
+/* System management exception (603?) */
+ STD_EXCEPTION(0x1400, Trap_14, UnknownException)
+
+ STD_EXCEPTION(0x1500, Trap_15, UnknownException)
+ STD_EXCEPTION(0x1600, Trap_16, UnknownException)
+ STD_EXCEPTION(0x1700, Trap_17, UnknownException)
+ STD_EXCEPTION(0x1800, Trap_18, UnknownException)
+ STD_EXCEPTION(0x1900, Trap_19, UnknownException)
+ STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
+ STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
+ STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
+ STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
+ STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
+ STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
+
+/* Run mode exception */
+ STD_EXCEPTION(0x2000, RunMode, RunModeException)
+
+ STD_EXCEPTION(0x2100, Trap_21, UnknownException)
+ STD_EXCEPTION(0x2200, Trap_22, UnknownException)
+ STD_EXCEPTION(0x2300, Trap_23, UnknownException)
+ STD_EXCEPTION(0x2400, Trap_24, UnknownException)
+ STD_EXCEPTION(0x2500, Trap_25, UnknownException)
+ STD_EXCEPTION(0x2600, Trap_26, UnknownException)
+ STD_EXCEPTION(0x2700, Trap_27, UnknownException)
+ STD_EXCEPTION(0x2800, Trap_28, UnknownException)
+ STD_EXCEPTION(0x2900, Trap_29, UnknownException)
+ STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
+ STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
+ STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
+ STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
+ STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
+ STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
+
+ . = 0x3000
+
/*
- * These routines are error paths/continuations of the exception
- * handlers above. They are placed here to avoid the problems
- * of only 0x100 bytes per exception handler.
+ * This code finishes saving the registers to the exception frame
+ * and jumps to the appropriate handler for the exception, turning
+ * on address translation.
*/
-
-/* Invalid address */
-InstructionAddressInvalid:
- mfspr r3,SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
- addis r1,r1,0x4000 /* Set bit 1 -> PTE not found */
- b 10f
+ .globl transfer_to_handler
+transfer_to_handler:
+ stw r22,_NIP(r21)
+ stw r23,_MSR(r21)
+ SAVE_GPR(7, r21)
+ SAVE_4GPRS(8, r21)
+ SAVE_8GPRS(12, r21)
+ SAVE_8GPRS(24, r21)
+ andi. r23,r23,MSR_PR
+ mfspr r23,SPRG3 /* if from user, fix up tss */
+ beq 2f
+#ifdef CONFIG_PMAC
+ lwz r24,GPR1(r21)
+ stw r22,LAST_PC(r23)
+ stw r24,USER_STACK(r23)
+#endif /* CONFIG_PMAC */
+ addi r24,r1,STACK_FRAME_OVERHEAD
+ stw r24,PT_REGS(r23)
+2: addi r2,r23,-TSS /* set r2 to current */
+ addis r2,r2,KERNELBASE@h
+ mflr r23
+ andi. r24,r23,0x3f00 /* get vector offset */
+ stw r24,TRAP(r21)
+ li r22,0
+ stw r22,RESULT(r21)
+ lwz r24,0(r23) /* virtual address of handler */
+ lwz r23,4(r23) /* where to go when done */
+ mtspr SRR0,r24
+ mtspr SRR1,r20
+ mtlr r23
+ SYNC
+ rfi /* jump to handler, enable MMU */
-/* Fetch from guarded or no-access page */
-InstructionFetchError:
- mfspr r3,SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
- addis r1,r1,0x0800 /* Set bit 4 -> protection error */
-10: mtspr DSISR,r1
- mtctr r0 /* Restore CTR */
- andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
- mtspr SRR1,r2
- mfspr r1,IMISS /* Get failing address */
- rlwinm. r2,r2,0,31,31 /* Check for little endian access */
- beq 20f /* Jump if big endian */
- xori r1,r1,3
-20: mtspr DAR,r1 /* Set fault address */
- mfmsr r0 /* Restore "normal" registers */
- xoris r0,r0,MSR_TGPR>>16
- mtcrf 0x80,r3 /* Restore CR0 */
- ori r0,r0,MSR_FP /* Need to keep FP enabled */
- sync /* Some chip revs have problems here... */
- mtmsr r0
- b InstructionAccess
+/*
+ * Continuation of the floating-point unavailable handler.
+ */
+load_up_fpu:
+ bl giveup_fpu_unmapped
+ ori r23,r23,MSR_FP /* 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)
+
+/* use last_task_used_math instead of fpu_tss */
+ lis r3,last_task_used_math@h/*a*/
+ addis r3,r3,-KERNELBASE@h
+ subi r4,r5,TSS
+ addis r4,r4,KERNELBASE@h
+ stw r4,last_task_used_math@l(r3)
+#if 0
+ lis r3,fpu_tss@ha
+ addis r4,r5,KERNELBASE@h
+ addis r3,r3,-KERNELBASE@h
+ stw r4,fpu_tss@l(r3)
+#endif
+ /* restore registers and return */
+ lwz r3,_CCR(r21)
+ lwz r4,_LINK(r21)
+ mtcrf 0xff,r3
+ mtlr r4
+ REST_GPR(1, r21)
+ REST_4GPRS(3, r21)
+ /* we haven't used ctr or xer */
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_GPR(20, r21)
+ REST_2GPRS(22, r21)
+ lwz r21,GPR21(r21)
+ SYNC
+ rfi
-/* Invalid address */
-DataAddressInvalid:
- mfspr r3,SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
- addis r1,r1,0x4000 /* Set bit 1 -> PTE not found */
- b 10f
+/*
+ * Load a PTE into the hash table, if possible.
+ * The address is in r3, and r4 contains access flags:
+ * _PAGE_USER (4) if a user-mode access, ored with
+ * _PAGE_RW (2) if a write. r20 contains DSISR or SRR1,
+ * so bit 1 (0x40000000) is set if the exception was due
+ * to no matching PTE being found in the hash table.
+ * r5 contains the physical address of the current task's tss.
+ *
+ * Returns to the caller if the access is illegal or there is no
+ * mapping for the address. Otherwise it places an appropriate PTE
+ * in the hash table and returns from the exception.
+ * Uses r0, r2 - r6, ctr, lr.
+ *
+ * For speed, 4 of the instructions get patched once the size and
+ * physical address of the hash table are known. These definitions
+ * of Hash_base and Hash_bits below are just an example.
+ */
+Hash_base = 0x180000
+Hash_bits = 12 /* e.g. 256kB hash table */
+Hash_msk = (((1 << Hash_bits) - 1) * 64)
+
+ .globl hash_page
+hash_page:
+ /* Get PTE (linux-style) and check access */
+ lwz r5,PG_TABLES(r5) /* task's page tables */
+ lis r2,-KERNELBASE@h
+ add r5,r5,r2 /* convert to phys addr */
+ rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */
+ lwz r5,0(r5) /* get pmd entry */
+ rlwinm. r5,r5,0,0,19 /* extract address of pte page */
+ beqlr- /* return if no mapping */
+ add r2,r5,r2
+ rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */
+ lwz r6,0(r2) /* get linux-style pte */
+ ori r4,r4,1 /* set _PAGE_PRESENT bit in access */
+ andc. r0,r4,r6 /* check access & ~permission */
+ bnelr- /* return if access not permitted */
+ ori r6,r6,0x100 /* set _PAGE_ACCESSED in pte */
+ rlwinm r5,r4,5,24,24 /* _PAGE_RW access -> _PAGE_DIRTY */
+ rlwimi r5,r4,7,22,22 /* _PAGE_RW -> _PAGE_HWWRITE */
+ or r6,r6,r5
+ stw r6,0(r2) /* update PTE (accessed/dirty bits) */
+
+ /* Convert linux-style PTE to low word of PPC-style PTE */
+ rlwinm r4,r6,32-9,31,31 /* _PAGE_HWWRITE -> PP lsb */
+ rlwimi r6,r6,32-1,31,31 /* _PAGE_USER -> PP (both bits now) */
+ ori r4,r4,0xe04 /* clear out reserved bits */
+ andc r6,r6,r4 /* PP=2 or 0, when _PAGE_HWWRITE */
+
+ /* Construct the high word of the PPC-style PTE */
+ mfsrin r5,r3 /* get segment reg for segment */
+ rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */
+ oris r5,r5,0x8000 /* set V (valid) bit */
+ rlwimi r5,r3,10,26,31 /* put in API (abbrev page index) */
+
+ /* Get the address of the primary PTE group in the hash table */
+ .globl hash_page_patch_A
+hash_page_patch_A:
+ lis r4,Hash_base@h /* base address of hash table */
+ rlwimi r4,r5,32-1,26-Hash_bits,25 /* (VSID & hash_mask) << 6 */
+ rlwinm r0,r3,32-6,26-Hash_bits,25 /* (PI & hash_mask) << 6 */
+ xor r4,r4,r0 /* make primary hash */
+
+ /* See whether it was a PTE not found exception or a
+ protection violation. */
+ andis. r0,r20,0x4000
+ li r2,8 /* PTEs/group */
+ bne 10f /* no PTE: go look for an empty slot */
+ tlbie r3 /* invalidate TLB entry */
+
+ /* Search the primary PTEG for a PTE whose 1st word matches r5 */
+ mtctr r2
+ addi r3,r4,-8
+1: lwzu r0,8(r3) /* get next PTE */
+ cmp 0,r0,r5
+ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
+ beq+ found_slot
+
+ /* Search the secondary PTEG for a matching PTE */
+ ori r5,r5,0x40 /* set H (secondary hash) bit */
+ .globl hash_page_patch_B
+hash_page_patch_B:
+ xoris r3,r4,Hash_msk>>16 /* compute secondary hash */
+ xori r3,r3,0xffc0
+ addi r3,r3,-8
+ mtctr r2
+2: lwzu r0,8(r3)
+ cmp 0,r0,r5
+ bdnzf 2,2b
+ beq+ found_slot
+ xori r5,r5,0x40 /* clear H bit again */
+
+ /* Search the primary PTEG for an empty slot */
+10: mtctr r2
+ addi r3,r4,-8 /* search primary PTEG */
+1: lwzu r0,8(r3) /* get next PTE */
+ cmpi 0,r0,0 /* empty? */
+ bdnzf 2,1b /* loop while ctr != 0 && !cr0.eq */
+ beq+ found_empty
+
+ /* Search the secondary PTEG for an empty slot */
+ ori r5,r5,0x40 /* set H (secondary hash) bit */
+ .globl hash_page_patch_C
+hash_page_patch_C:
+ xoris r3,r4,Hash_msk>>16 /* compute secondary hash */
+ xori r3,r3,0xffc0
+ addi r3,r3,-8
+ mtctr r2
+2: lwzu r0,8(r3)
+ cmpi 0,r0,0
+ bdnzf 2,2b
+ beq+ found_empty
+
+ /* Choose an arbitrary slot in the primary PTEG to overwrite */
+ xori r5,r5,0x40 /* clear H bit again */
+ lwz r2,next_slot@l(0)
+ addi r2,r2,8
+ andi. r2,r2,0x38
+ stw r2,next_slot@l(0)
+ add r3,r4,r2
+
+ /* Store PTE in PTEG */
+found_empty:
+ stw r5,0(r3)
+found_slot:
+ stw r6,4(r3)
+ SYNC
+ /* Return from the exception */
+ lwz r3,_CCR(r21)
+ lwz r4,_LINK(r21)
+ lwz r5,_CTR(r21)
+ mtcrf 0xff,r3
+ mtlr r4
+ mtctr r5
+ REST_GPR(0, r21)
+ REST_2GPRS(1, r21)
+ REST_4GPRS(3, r21)
+ /* we haven't used xer */
+ mtspr SRR1,r23
+ mtspr SRR0,r22
+ REST_GPR(20, r21)
+ REST_2GPRS(22, r21)
+ lwz r21,GPR21(r21)
+ SYNC
+ rfi
-/* Write to read-only space */
-WriteProtectError:
- mfspr r3,SRR1
- rlwinm r1,r3,9,6,6 /* Get load/store bit */
- addis r1,r1,0x0800 /* Set bit 4 -> protection error */
-10: mtspr DSISR,r1
- mtctr r0 /* Restore CTR */
- andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */
- mtspr SRR1,r2
- mfspr r1,DMISS /* Get failing address */
- rlwinm. r2,r2,0,31,31 /* Check for little endian access */
- beq 20f /* Jump if big endian */
- xori r1,r1,3
-20: mtspr DAR,r1 /* Set fault address */
- mfmsr r0 /* Restore "normal" registers */
- xoris r0,r0,MSR_TGPR>>16
- mtcrf 0x80,r3 /* Restore CR0 */
- ori r0,r0,MSR_FP /* Need to keep FP enabled */
- sync /* Some chip revs have problems here... */
- mtmsr r0
- b DataAccess
+next_slot:
+ .long 0
/*
- * Flush instruction cache
- * *** I'm really paranoid here!
+ * This is where the main kernel code starts.
*/
-_GLOBAL(flush_instruction_cache)
- mflr r5
- bl _EXTERN(flush_data_cache)
- mfspr r3,HID0 /* Caches are controlled by this register */
+
+start_here:
+ /*
+ * 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 r7,HID0
+ andi. r0,r7,HID0_DCE
+ ori r7,r7,HID0_ICE|HID0_DCE
+ ori r8,r7,HID0_ICFI
+ bne 3f /* don't invalidate the D-cache */
+ ori r8,r8,HID0_DCI /* unless it wasn't enabled */
+3: sync
+ mtspr HID0,r8 /* enable and invalidate caches */
+ sync
+ mtspr HID0,r7 /* enable caches */
+ sync
+ isync
+ cmpi 0,r9,4 /* check for 604 */
+ cmpi 1,r9,9 /* or 604e */
+ cror 2,2,6
+ bne 4f
+ ori r7,r7,HID0_SIED|HID0_BHTE /* for 604[e], enable */
+ mtspr HID0,r7 /* superscalar exec & br history tbl */
+4:
+ /* ptr to current */
+ lis r2,init_task_union@h
+ ori r2,r2,init_task_union@l
+ /* ptr to phys current tss */
+ addis r3,r2,-KERNELBASE@h
+ addi r3,r3,TSS /* init task's TSS */
+ mtspr SPRG3,r3
+ /* stack */
+ addi r1,r2,TASK_UNION_SIZE
+ li r0,0
+ stwu r0,-STACK_FRAME_OVERHEAD(r1)
+
+ /* Clear out the BSS */
+ lis r7,_end@ha
+ addi r7,r7,_end@l
+ lis r8,__bss_start@ha
+ addi r8,r8,__bss_start@l
+ subf r7,r8,r7
+ addi r7,r7,3
+ rlwinm. r7,r7,30,2,31
+ beq 2f
+ addi r8,r8,-4
+ mtctr r7
+ li r0,0
+3: stwu r0,4(r8)
+ bdnz 3b
+2:
+/*
+ * Initialize the prom stuff (powermacs only) and the MMU.
+ */
+#ifdef CONFIG_PMAC
+ bl prom_init
+#endif /* CONFIG_PMAC */
+ bl MMU_init
+
+/*
+ * 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)
+ li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
+ lis r4,2f@h
+ addis r4,r4,-KERNELBASE@h
+ ori r4,r4,2f@l
+ mtspr SRR0,r4
+ mtspr SRR1,r3
+ rfi
+/* Load up the kernel context */
+2:
+#ifdef CONFIG_PREP
+ /* reload the bats now that MMU_init() has setup them up -- Cort */
+ LOAD_BATS(r3,r0)
+#endif
+
+ 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
- ori r4,r4,(HID0_ICE|HID0_ICFI)
- or r3,r3,r4 /* Need to enable+invalidate to clear */
- mtspr HID0,r3
- andc r3,r3,r4
- ori r3,r3,HID0_ICE /* Enable cache */
- mtspr HID0,r3
- mtlr r5
- blr
+3: mtsrin r3,r4
+ addi r3,r3,1 /* increment VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+#ifdef CONFIG_PMAC
+ li r0,0 /* zot the BATs */
+#if 1
+ mtspr IBAT0U,r0
+ mtspr IBAT0L,r0
+ mtspr DBAT0U,r0
+ mtspr DBAT0L,r0
+#endif
+ mtspr IBAT1U,r0
+ mtspr IBAT1L,r0
+ mtspr DBAT1U,r0
+ mtspr DBAT1L,r0
+ mtspr IBAT2U,r0
+ mtspr IBAT2L,r0
+ mtspr DBAT2U,r0
+ mtspr DBAT2L,r0
+ mtspr IBAT3U,r0
+ mtspr IBAT3L,r0
+ mtspr DBAT3U,r0
+ mtspr DBAT3L,r0
+#endif
+/* Now turn on the MMU for real! */
+ li r4,MSR_KERNEL
+ lis r3,start_kernel@h
+ ori r3,r3,start_kernel@l
+ mtspr SRR0,r3
+ mtspr SRR1,r4
+ rfi /* enable MMU and jump to start_kernel */
+#ifdef CONFIG_PREP
/*
- * Flush data cache
- * *** I'm really paranoid here!
+ * 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
+ * of the regs is:
+ * R3: End of image
+ * R4: Start of image - 0x400
+ * R11: Start of command line string
+ * R12: End of command line string
+ *
+ * This just gets a minimal mmu environment setup so we can call
+ * start_here() to do the real work.
+ * -- Cort
*/
-_GLOBAL(flush_data_cache)
- BUMP(__Cache_Flushes)
- lis r3,cache_is_copyback@ha
- lwz r3,cache_is_copyback@l(r3)
- cmpi 0,r3,0
- beq 10f
-/* When DATA CACHE is copy-back */
- lis r3,cache_flush_buffer@h
- ori r3,r3,cache_flush_buffer@l
- li r4,NUM_CACHE_LINES
- mtctr r4
-00: dcbz 0,r3 /* Flush cache line with minimal BUS traffic */
- addi r3,r3,CACHE_LINE_SIZE /* Next line, please */
- bdnz 00b
-10: blr
+ .globl __start
+__start:
+ .globl _start
+_start:
+ lis r7,0xF000 /* To mask upper 4 bits */
+/* save pointer to residual data */
+ lis r1,resptr@h
+ ori r1,r1,resptr@l
+ addis r1,r1,-KERNELBASE@h
+ stw r3,0(r1)
+/* save argument string */
+ li r0,0 /* Null terminate string */
+ stb r0,0(r12)
+ lis r1,cmd_line@h
+ ori r1,r1,cmd_line@l
+ addis r1,r1,-KERNELBASE@h
+ subi r1,r1,1
+ subi r11,r11,1
+00: lbzu r0,1(r11)
+ cmpi 0,r0,0
+ stbu r0,1(r1)
+ bne 00b
+/* setup the msr with sane values */
+ li r0,MSR_
+ mtmsr r0
+/* turn on the mmu with bats covering kernel enough to get started */
+ LOAD_BATS(r3,r0)
+ mfmsr r3
+ ori r3,r3,MSR_DR|MSR_IR
+ mtspr SRR1,r3
+ lis r3,10f@h
+ ori r3,r3,10f@l
+ mtspr SRR0,r3
+ SYNC
+ rfi /* enables MMU */
+10: lis r7,start_here@ha /* jump up to our copy at KERNELBASE */
+ addi r7,r7,start_here@l
+ mtlr r7
+ blr
+#endif /* CONFIG_PREP */
+
+/*
+ * FP unavailable trap from kernel - print a message, but let
+ * the task use FP in the kernel until it returns to user mode.
+ */
+KernelFP:
+ lwz r3,_MSR(r1)
+ ori r3,r3,MSR_FP
+ stw r3,_MSR(r1) /* enable use of FP after return */
+ lis r3,86f@h
+ ori r3,r3,86f@l
+ mr r4,r2 /* current */
+ lwz r5,_NIP(r1)
+ bl printk
+ b int_return
+86: .string "floating point used in kernel (task=%p, pc=%x)\n"
+ .align 4
/*
- * Flush a particular page from the DATA cache
- * Note: this is necessary because the instruction cache does *not*
- * snoop from the data cache.
- * void flush_page(void *page)
+ * 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.
+ * (If giveup_fpu_unmapped uses any integer registers other than
+ * r3 - r6, the return code at load_up_fpu above will have
+ * to be adjusted.)
*/
-_GLOBAL(flush_page)
- li r4,0x0FFF
- andc r3,r3,r4 /* Get page base address */
- li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
- mtctr r4
-00: dcbf 0,r3 /* Clear line */
- icbi 0,r3
- addi r3,r3,CACHE_LINE_SIZE
- bdnz 00b
+giveup_fpu_unmapped:
+ lis r6,-KERNELBASE@h
+ b 1f
+
+ .globl giveup_fpu
+giveup_fpu:
+ li r6,0
+1:
+ addis r3,r6,last_task_used_math@h/*a*/
+ lwz r4,last_task_used_math@l(r3)
+#if 0
+ addis r3,r6,fpu_tss@ha
+ lwz r4,fpu_tss@l(r3)
+#endif
+ mfmsr r5
+ ori r5,r5,MSR_FP
+ SYNC
+ mtmsr r5 /* enable use of fpu now */
+ SYNC
+ cmpi 0,r4,0
+ add r4,r4,r6
+ beqlr /* if no previous owner, done */
+ addi r4,r4,TSS /* want TSS of last_task_used_math */
+ li r5,0
+ stw r5,last_task_used_math@l(r3)
+#if 0
+ stw r5,fpu_tss@l(r3)
+#endif
+ SAVE_32FPRS(0, r4)
+ mffs fr0
+ stfd fr0,TSS_FPSCR-4(r4)
+ lwz r5,PT_REGS(r4)
+ lwz r5,PT_REGS(r4)
+ add r5,r5,r6
+ lwz r3,_MSR-STACK_FRAME_OVERHEAD(r5)
+ li r4,MSR_FP
+ andc r3,r3,r4 /* disable FP for previous task */
+ stw r3,_MSR-STACK_FRAME_OVERHEAD(r5)
blr
/*
+ * Handle a system call.
+ */
+DoSyscall:
+ stw r0,TSS+LAST_SYSCALL(r2)
+ lwz r11,_CCR(r1) /* Clear SO bit in CR */
+ lis r10,0x1000
+ andc r11,r11,r10
+ stw r11,_CCR(r1)
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+ lis r31,show_syscalls_task@ha
+ lwz r31,show_syscalls_task@l(r31)
+ cmp 0,r2,r31
+ bne 1f
+#endif
+ lis r3,7f@ha
+ addi r3,r3,7f@l
+ lwz r4,GPR0(r1)
+ lwz r5,GPR3(r1)
+ lwz r6,GPR4(r1)
+ lwz r7,GPR5(r1)
+ lwz r8,GPR6(r1)
+ mr r9,r2
+ bl printk
+ lwz r0,GPR0(r1)
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+1:
+#endif /* SHOW_SYSCALLS */
+ cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
+ beq- 10f
+ lwz r10,TASK_FLAGS(r2)
+ andi. r10,r10,PF_TRACESYS
+ bne- 50f
+ cmpli 0,r0,NR_syscalls
+ bge- 66f
+ lis r10,sys_call_table@h
+ ori r10,r10,sys_call_table@l
+ slwi r0,r0,2
+ lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
+ cmpi 0,r10,0
+ beq- 66f
+ mtlr r10
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ blrl /* Call handler */
+ .globl syscall_ret_1
+syscall_ret_1:
+20: stw r3,RESULT(r1) /* Save result */
+#ifdef SHOW_SYSCALLS
+#ifdef SHOW_SYSCALLS_TASK
+ cmp 0,r2,r31
+ bne 91f
+#endif
+ mr r4,r3
+ lis r3,79f@ha
+ addi r3,r3,79f@l
+ bl printk
+ lwz r3,RESULT(r1)
+91:
+#endif
+ li r10,-_LAST_ERRNO
+ cmpl 0,r3,r10
+ blt 30f
+ neg r3,r3
+ cmpi 0,r3,ERESTARTNOHAND
+ bne 22f
+ li r3,EINTR
+22: lwz r10,_CCR(r1) /* Set SO bit in CR */
+ oris r10,r10,0x1000
+ stw r10,_CCR(r1)
+30: stw r3,GPR3(r1) /* Update return value */
+ b int_return
+66: li r3,ENOSYS
+ b 22b
+/* sys_sigreturn */
+10: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl _EXTERN(sys_sigreturn)
+ cmpi 0,r3,0 /* Check for restarted system call */
+ bge int_return
+ b 20b
+/* Traced system call support */
+50: bl _EXTERN(syscall_trace)
+ lwz r0,GPR0(r1) /* Restore original registers */
+ lwz r3,GPR3(r1)
+ lwz r4,GPR4(r1)
+ lwz r5,GPR5(r1)
+ lwz r6,GPR6(r1)
+ lwz r7,GPR7(r1)
+ lwz r8,GPR8(r1)
+ lwz r9,GPR9(r1)
+ cmpli 0,r0,NR_syscalls
+ bge- 66f
+ lis r10,sys_call_table@h
+ ori r10,r10,sys_call_table@l
+ slwi r0,r0,2
+ lwzx r10,r10,r0 /* Fetch system call handler [ptr] */
+ cmpi 0,r10,0
+ beq- 66f
+ mtlr r10
+ addi r9,r1,STACK_FRAME_OVERHEAD
+ blrl /* Call handler */
+ .globl syscall_ret_2
+syscall_ret_2:
+ stw r3,RESULT(r1) /* Save result */
+ stw r3,GPR0(r1) /* temporary gross hack to make strace work */
+ li r10,-_LAST_ERRNO
+ cmpl 0,r3,r10
+ blt 60f
+ neg r3,r3
+ cmpi 0,r3,ERESTARTNOHAND
+ bne 52f
+ li r3,EINTR
+52: lwz r10,_CCR(r1) /* Set SO bit in CR */
+ oris r10,r10,0x1000
+ stw r10,_CCR(r1)
+60: stw r3,GPR3(r1) /* Update return value */
+ bl _EXTERN(syscall_trace)
+ b int_return
+66: li r3,ENOSYS
+ b 52b
+#ifdef SHOW_SYSCALLS
+7: .string "syscall %d(%x, %x, %x, %x), current=%p\n"
+79: .string " -> %x\n"
+ .align 2
+#endif
+
+/*
* This routine switches between two different tasks. The process
* state of one is saved on its kernel stack. Then the state
* of the other is restored from its kernel stack. The memory
* management hardware is updated to the second process's state.
- * Finally, we can return to the second process, via the 'return'.
+ * Finally, we can return to the second process, via int_return.
+ * On entry, r3 points to the TSS for the current task, r4
+ * points to the TSS for the new task, and r5 contains the
+ * MMU context number for the new task.
*
* Note: there are two ways to get to the "going out" portion
* of this code; either by coming in via the entry (_switch)
* or via "fork" which must set up an environment equivalent
* to the "_switch" path. If you change this (or in particular, the
- * SAVE_ALL_REGS macro), you'll have to change the fork code also.
+ * SAVE_REGS macro), you'll have to change the fork code also.
*
* The code which creates the new task context is in 'copy_thread'
* in arch/ppc/kernel/process.c
*/
_GLOBAL(_switch)
- mtspr SPR0,r1 /* SAVE_ALL_REGS prologue */
- mtspr SPR1,r2
- mflr r2 /* Return to switch caller */
- mtspr SPR2,r2
- mfmsr r2
- mtspr SPR3,r2
- SAVE_ALL_REGS(0x0FF0)
- SAVE_FP_REGS()
- CHECK_STACK()
- SYNC()
+ stwu r1,-INT_FRAME_SIZE-STACK_UNDERHEAD(r1)
+ stw r0,GPR0(r1)
+ lwz r0,0(r1)
+ stw r0,GPR1(r1)
+ SAVE_10GPRS(2, r1)
+ SAVE_10GPRS(12, r1)
+ SAVE_10GPRS(22, r1)
+ mflr r20 /* Return to switch caller */
+ mfmsr r22
+ li r0,MSR_FP /* Disable floating-point */
+ andc r22,r22,r0
+ stw r20,_NIP(r1)
+ stw r22,_MSR(r1)
+ stw r20,_LINK(r1)
+ mfcr r20
+ mfctr r22
+ mfspr r23,XER
+ stw r20,_CCR(r1)
+ stw r22,_CTR(r1)
+ stw r23,_XER(r1)
+ li r0,0x0ff0
+ stw r0,TRAP(r1)
stw r1,KSP(r3) /* Set old stack pointer */
- BUMP(__Context_Switches)
+ sync
+ addis r0,r4,-KERNELBASE@h
+ mtspr SPRG3,r0 /* Update current TSS phys addr */
+ SYNC
lwz r1,KSP(r4) /* Load new stack pointer */
- lwz r0,MMU_SEG0(r4)
- mtsr SR0,r0
- lwz r0,MMU_SEG1(r4)
- mtsr SR1,r0
- lwz r0,MMU_SEG2(r4)
- mtsr SR2,r0
- lwz r0,MMU_SEG3(r4)
- mtsr SR3,r0
- lwz r0,MMU_SEG4(r4)
- mtsr SR4,r0
- lwz r0,MMU_SEG5(r4)
- mtsr SR5,r0
- lwz r0,MMU_SEG6(r4)
- mtsr SR6,r0
- lwz r0,MMU_SEG7(r4)
- mtsr SR7,r0
-#if 0
- /* segs 8-15 are shared by everyone -- don't need to be changed */
- lwz r0,MMU_SEG8(r4)
- mtsr SR8,r0
- lwz r0,MMU_SEG9(r4)
- mtsr SR9,r0
- lwz r0,MMU_SEG10(r4)
- mtsr SR10,r0
- lwz r0,MMU_SEG11(r4)
- mtsr SR11,r0
- lwz r0,MMU_SEG12(r4)
- mtsr SR12,r0
- lwz r0,MMU_SEG13(r4)
- mtsr SR13,r0
- lwz r0,MMU_SEG14(r4)
- mtsr SR14,r0
- lwz r0,MMU_SEG15(r4)
- mtsr SR15,r0
-#endif
- /* no need to invalidate tlb since each process has a distinct
- set of vsid's. -- Cort */
-#if 0
- tlbia /* Invalidate entire TLB */
- BUMP(__TLBIAs)
-#endif
- /* p5.2 603 users manual - with addr transl. enabled,
- the memory access is performed under the control of
- the page table entry. I interpret this to mean that
- it is tagged with the vsid -- so no need to flush here
- since each process has a distinct set of vsid's.
- Of course, my intepretation may be wrong.
- -- Cort */
- /*bl _EXTERN(flush_instruction_cache)*/
- RETURN_FROM_INT(0x0f0f)
-
+ addi r2,r4,-TSS /* Update current */
+ /* Set up segment registers for new task */
+ rlwinm r5,r5,4,8,27 /* VSID = context << 4 */
+ addis r5,r5,0x6000 /* Set Ks, Ku bits */
+ li r0,8 /* TASK_SIZE / SEGMENT_SIZE */
+ mtctr r0
+ li r3,0
+3: mtsrin r5,r3
+ addi r5,r5,1 /* next VSID */
+ addis r3,r3,0x1000 /* address of next segment */
+ bdnz 3b
+ SYNC
+
+/* FALL THROUGH into int_return */
+
+/*
+ * Trap exit.
+ */
+ .globl int_return
+int_return:
+0: mfmsr r30 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r30,r30,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r30
+ SYNC
+ lwz r5,_MSR(r1)
+ and. r5,r5,r4
+ beq 2f
+3: lis r4,lost_interrupts@ha
+ lwz r4,lost_interrupts@l(r4)
+ cmpi 0,r4,0
+ beq+ 1f
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl handle_IRQ
+ b 3b
+1: lis r4,bh_mask@ha
+ lwz r4,bh_mask@l(r4)
+ lis r5,bh_active@ha
+ lwz r5,bh_active@l(r5)
+ and. r4,r4,r5
+ beq+ 2f
+ ori r31,r30,MSR_EE /* re-enable interrupts */
+ SYNC
+ mtmsr r31
+ SYNC
+ bl _EXTERN(do_bottom_half)
+ SYNC
+ mtmsr r30 /* disable interrupts again */
+ SYNC
+2: lwz r3,_MSR(r1) /* Returning to user mode? */
+ andi. r3,r3,MSR_PR
+ beq+ 10f /* no - no need to mess with stack */
+ lis r3,need_resched@ha
+ lwz r3,need_resched@l(r3)
+ cmpi 0,r3,0 /* check need_resched flag */
+ beq+ 7f
+ bl _EXTERN(schedule)
+ b 0b
+7: lwz r3,BLOCKED(r2) /* Check for pending unblocked signals */
+ lwz r5,SIGNAL(r2)
+ andc. r0,r5,r3 /* Lets thru any unblocked */
+ beq+ 8f
+ addi r4,r1,STACK_FRAME_OVERHEAD
+ bl _EXTERN(do_signal)
+ b 0b
+8: addi r4,r1,INT_FRAME_SIZE+STACK_UNDERHEAD /* size of frame */
+ stw r4,TSS+KSP(r2) /* save kernel stack pointer */
+10:
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr SRR0,r2
+ mtspr SRR1,r0
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfi
+
+/*
+ * Fake an interrupt from kernel mode.
+ * This is used when enable_irq loses an interrupt.
+ * We only fill in the stack frame minimally.
+ */
+_GLOBAL(fake_interrupt)
+ mflr r0
+ stw r0,4(r1)
+ stwu r1,-INT_FRAME_SIZE-STACK_UNDERHEAD(r1)
+ stw r0,_NIP(r1)
+ stw r0,_LINK(r1)
+ mfmsr r3
+ stw r3,_MSR(r1)
+ li r0,0x0fac
+ stw r0,TRAP(r1)
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl handle_IRQ
+ addi r1,r1,INT_FRAME_SIZE+STACK_UNDERHEAD
+ lwz r0,4(r1)
+ mtlr r0
+ blr
+
+/*
+ * Set up the segment registers for a new context.
+ */
+_GLOBAL(set_context)
+ rlwinm r3,r3,4,8,27 /* VSID = context << 4 */
+ addis r3,r3,0x6000 /* Set Ks, Ku bits */
+ li r0,8 /* TASK_SIZE / SEGMENT_SIZE */
+ mtctr r0
+ li r4,0
+3: mtsrin r3,r4
+ addi r3,r3,1 /* next VSID */
+ addis r4,r4,0x1000 /* address of next segment */
+ bdnz 3b
+ SYNC
+ blr
+
+/*
+ * Flush instruction cache.
+ * This is a no-op on the 601.
+ */
+_GLOBAL(flush_instruction_cache)
+ mfspr r3,PVR
+ rlwinm r3,r3,16,16,31
+ cmpi 0,r3,1
+ beqlr /* for 601, do nothing */
+ /* 603/604 processor - use invalidate-all bit in HID0 */
+ mfspr r3,HID0
+ ori r3,r3,HID0_ICFI
+ mtspr HID0,r3
+ SYNC
+ blr
+
+/*
+ * Write any modified data cache blocks out to memory
+ * and invalidate the corresponding instruction cache blocks.
+ * This is a no-op on the 601.
+ *
+ * store_cache_range(unsigned long start, unsigned long stop)
+ */
+CACHE_LINE_SIZE = 32
+LG_CACHE_LINE_SIZE = 5
+_GLOBAL(store_cache_range)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ li r5,CACHE_LINE_SIZE-1
+ andc r3,r3,r5
+ subf r4,r3,r4
+ add r4,r4,r5
+ srwi. r4,r4,LG_CACHE_LINE_SIZE
+ beqlr
+ mtctr r4
+ mr r6,r3
+1: dcbst 0,r3
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 1b
+ sync /* wait for dcbst's to get to ram */
+ mtctr r4
+2: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 2b
+ sync
+ isync
+ blr
+
+/*
+ * Flush a particular page from the DATA cache
+ * Note: this is necessary because the instruction cache does *not*
+ * snoop from the data cache.
+ * This is a no-op on the 601 which has a unified cache.
+ *
+ * void flush_page_to_ram(void *page)
+ */
+_GLOBAL(flush_page_to_ram)
+ mfspr r5,PVR
+ rlwinm r5,r5,16,16,31
+ cmpi 0,r5,1
+ beqlr /* for 601, do nothing */
+ li r4,0x0FFF
+ andc r3,r3,r4 /* Get page base address */
+ li r4,4096/CACHE_LINE_SIZE /* Number of lines in a page */
+ mtctr r4
+ mr r6,r3
+0: dcbst 0,r3 /* Write line to ram */
+ addi r3,r3,CACHE_LINE_SIZE
+ bdnz 0b
+ sync
+ mtctr r4
+1: icbi 0,r6
+ addi r6,r6,CACHE_LINE_SIZE
+ bdnz 1b
+ sync
+ isync
+ blr
+
+/*
+ * Flush entries from the hash table with VSIDs in the range
+ * given.
+ */
+_GLOBAL(flush_hash_segments)
+ rlwinm r3,r3,7,1,24 /* put VSID lower limit in position */
+ oris r3,r3,0x8000 /* set V bit */
+ rlwinm r4,r4,7,1,24 /* put VSID upper limit in position */
+ oris r4,r4,0x8000
+ ori r4,r4,0x7f
+ lis r5,Hash@ha
+ lwz r5,Hash@l(r5) /* base of hash table */
+ lis r6,Hash_size@ha
+ lwz r6,Hash_size@l(r6) /* size in bytes */
+ srwi r6,r6,3 /* # PTEs */
+ mtctr r6
+ addi r5,r5,-8
+ li r0,0
+1: lwzu r6,8(r5) /* get next tag word */
+ cmplw 0,r6,r3
+ cmplw 1,r6,r4
+ cror 0,0,5 /* set cr0.lt if out of range */
+ blt 2f /* branch if out of range */
+ stw r0,0(r5) /* invalidate entry */
+2: bdnz 1b /* continue with loop */
+ sync
+ tlbia
+ isync
+ blr
+
+/*
+ * Flush the entry for a particular page from the hash table.
+ *
+ * flush_hash_page(unsigned context, unsigned long va)
+ */
+_GLOBAL(flush_hash_page)
+ rlwinm r3,r3,11,1,20 /* put context into vsid */
+ rlwimi r3,r4,11,21,24 /* put top 4 bits of va into vsid */
+ oris r3,r3,0x8000 /* set V (valid) bit */
+ rlwimi r3,r4,10,26,31 /* put in API (abbrev page index) */
+ rlwinm r7,r4,32-6,10,25 /* get page index << 6 */
+ rlwinm r5,r3,32-1,7,25 /* vsid << 6 */
+ xor r7,r7,r5 /* primary hash << 6 */
+ lis r5,Hash_mask@ha
+ lwz r5,Hash_mask@l(r5) /* hash mask */
+ slwi r5,r5,6 /* << 6 */
+ and r7,r7,r5
+ lis r6,Hash@ha
+ lwz r6,Hash@l(r6) /* hash table base */
+ add r6,r6,r7 /* address of primary PTEG */
+ li r8,8
+ mtctr r8
+ addi r7,r6,-8
+1: lwzu r0,8(r7) /* get next PTE */
+ cmpw 0,r0,r3 /* see if tag matches */
+ bdnzf 2,1b /* while --ctr != 0 && !cr0.eq */
+ beq 3f /* if we found it */
+ ori r3,r3,0x40 /* set H (alt. hash) bit */
+ xor r6,r6,r5 /* address of secondary PTEG */
+ mtctr r8
+ addi r7,r6,-8
+2: lwzu r0,8(r7) /* get next PTE */
+ cmpw 0,r0,r3 /* see if tag matches */
+ bdnzf 2,2b /* while --ctr != 0 && !cr0.eq */
+ bne 4f /* if we didn't find it */
+3: li r0,0
+ stw r0,0(r7) /* invalidate entry */
+4: sync
+ tlbie r4 /* in hw tlb too */
+ isync
+ blr
/*
* This routine is just here to keep GCC happy - sigh...
@@ -1415,18 +1521,212 @@ _GLOBAL(_switch)
_GLOBAL(__main)
blr
+#ifdef CONFIG_PMAC
+/*
+ * These exception handlers are used when we have called a prom
+ * routine after we have taken over the exception vectors and MMU.
+ */
+ .globl prom_exc_table
+prom_exc_table:
+ .long TOPHYS(prom_exception) /* 0 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 400 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 800 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* c00 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1000 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1400 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1800 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1c00 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1000 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1400 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1800 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception) /* 1c00 */
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+ .long TOPHYS(prom_exception)
+
+/*
+ * When we come in to these prom exceptions, r1 and lr have been
+ * saved in sprg1 and sprg2, and lr points to a word containing
+ * the vector offset.
+ */
+prom_exception:
+ mr r1,r21 /* save r21 */
+ lis r21,prom_sp@ha /* get a stack to use */
+ addis r21,r21,-KERNELBASE@h
+ lwz r21,prom_sp@l(r21)
+ addis r21,r21,-KERNELBASE@h /* convert to physical addr */
+ subi r21,r21,INT_FRAME_SIZE+STACK_UNDERHEAD
+ stw r0,GPR0(r21)
+ stw r2,GPR2(r21)
+ stw r3,GPR3(r21)
+ stw r4,GPR4(r21)
+ stw r5,GPR5(r21)
+ stw r6,GPR6(r21)
+ stw r20,GPR20(r21)
+ stw r1,GPR21(r21)
+ stw r22,GPR22(r21)
+ stw r23,GPR23(r21)
+ mfspr r1,SPRG1
+ stw r1,GPR1(r21)
+ mfcr r3
+ mfspr r4,SPRG2
+ stw r3,_CCR(r21)
+ stw r4,_LINK(r21)
+ mfctr r3
+ mfspr r4,XER
+ stw r3,_CTR(r21)
+ stw r4,_XER(r21)
+ mfspr r22,SRR0
+ mfspr r23,SRR1
+
+ /* at this point we have set things up pretty much exactly
+ how EXCEPTION_PROLOG does */
+ mflr r3
+ lwz r3,0(r3) /* get exception vector */
+ stw r3,TRAP(r21)
+ cmpi 0,r3,0x300 /* was it a dsi? */
+ bne 1f
+
+ mfspr r20,DSISR /* here on data access exc. */
+ andis. r0,r20,0x8470 /* weird error? */
+ bne 3f /* if not, try to put a PTE */
+ mfspr r3,DAR /* into the hash table */
+ rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */
+ rlwimi r4,r20,32-23,29,29 /* DSISR_STORE -> _PAGE_RW */
+ b 2f
+
+1: cmpi 0,r3,0x400 /* was it an isi? */
+ bne 3f
+ andis. r0,r23,0x4000 /* if so, check if no pte found */
+ beq 3f /* if so, try to put a PTE */
+ mr r3,r22 /* into the hash table */
+ rlwinm r4,r23,32-13,30,30 /* MSR_PR -> _PAGE_USER */
+ mr r20,r23 /* SRR1 has reason bits */
+2: lis r5,prom_tss@ha /* phys addr of TSS */
+ addis r5,r5,-KERNELBASE@h
+ lwz r5,prom_tss@l(r5)
+ bl hash_page
+
+3: addis r1,r21,KERNELBASE@h /* restore kernel stack ptr */
+ addi r3,r1,INT_FRAME_SIZE+STACK_UNDERHEAD
+ stw r3,0(r21) /* set stack chain pointer */
+ lis r5,prom_tss@ha
+ addis r5,r5,-KERNELBASE@h
+ lwz r5,prom_tss@l(r5)
+ mtspr SPRG3,r5 /* reset phys TSS pointer */
+ lwz r4,TRAP(r21) /* the real exception vector */
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ li r20,MSR_KERNEL
+ bl transfer_to_handler
+ .long PromException
+ .long prom_int_return
+
+ .comm prom_sp,4
+ .comm prom_tss,4
+
+ .globl prom_int_return
+prom_int_return:
+ lis r3,prom_exc_table@ha /* restore sprg3 for prom vectors */
+ addi r3,r3,prom_exc_table@l
+ addis r3,r3,-KERNELBASE@h
+ mtspr SPRG3,r3
+ b int_return
+
+/*
+ * When entering the prom, we have to change to using a different
+ * set of exception vectors.
+ */
+ .globl enter_prom
+enter_prom:
+ stwu r1,-32(r1)
+ mflr r0
+ stw r0,36(r1)
+ stw r29,20(r1)
+ stw r30,24(r1)
+ stw r31,28(r1)
+ lis r8,prom_entry@ha
+ lwz r8,prom_entry@l(r8)
+ mfmsr r31
+ andi. r0,r31,MSR_IP /* using our own vectors yet? */
+ beq 1f /* if so, have to switch */
+ mtlr r8
+ blrl /* if not, can just charge ahead */
+ b 2f
+1: lis r9,prom_sp@ha /* save sp for exception handler */
+ stw r1,prom_sp@l(r9)
+ mfspr r29,SPRG3 /* save physical tss pointer */
+ lis r9,prom_tss@ha
+ stw r29,prom_tss@l(r9)
+ li r9,0
+ ori r9,r9,MSR_EE
+ andc r30,r31,r9
+ lis r9,prom_exc_table@ha /* set pointer to exception table */
+ addi r9,r9,prom_exc_table@l
+ addis r9,r9,-KERNELBASE@h
+ ori r0,r31,MSR_IP
+ sync
+ mtmsr r30 /* disable interrupts */
+ mtspr SPRG3,r9 /* while we update MSR_IP and sprg3 */
+ sync
+ mtmsr r0 /* start using exc. vectors in prom */
+ mtlr r8
+ blrl /* call prom */
+ sync
+ mtmsr r30 /* disable interrupts again */
+ mtspr SPRG3,r29 /* while we restore MSR_IP and sprg3 */
+ sync
+ mtmsr r31 /* reenable interrupts */
+2: lwz r0,36(r1)
+ mtlr r0
+ lwz r29,20(r1)
+ lwz r30,24(r1)
+ lwz r31,28(r1)
+ lwz r1,0(r1)
+ blr
+#endif
+
+/*
+ * We put a few things here that have to be page-aligned.
+ * This stuff goes at the beginning of the data segment,
+ * which is page-aligned.
+ */
.data
.globl sdata
sdata:
.space 2*4096
-
-#if 0
-_GLOBAL(sys_stack)
-sys_stack:
- .space 4096
-#endif
-CPU1_stack:
-
.globl empty_zero_page
empty_zero_page:
.space 4096
@@ -1435,6 +1735,7 @@ empty_zero_page:
swapper_pg_dir:
.space 4096
+#ifdef CONFIG_PREP
/*
* This space gets a copy of optional info passed to us by the bootstrap
* Used to pass parameters into the kernel like root=/dev/sda1, etc.
@@ -1442,54 +1743,5 @@ swapper_pg_dir:
.globl cmd_line
cmd_line:
.space 512
-
-#ifdef STATS
-/*
- * Miscellaneous statistics - gathered just for performance info
- */
- .globl _INTR_stats
-_INTR_stats:
- .globl __Instruction_TLB_Misses
-__Instruction_TLB_Misses:
- .long 0,0 /* Instruction TLB misses */
- .globl __DataLoad_TLB_Misses
-__DataLoad_TLB_Misses:
- .long 0,0 /* Data [load] TLB misses */
- .globl __DataStore_TLB_Misses
-__DataStore_TLB_Misses:
- .long 0,0 /* Data [store] TLB misses */
- .globl __Instruction_Page_Faults
-__Instruction_Page_Faults:
- .long 0,0 /* Instruction page faults */
- .globl __Data_Page_Faults
-__Data_Page_Faults:
- .long 0,0 /* Data page faults */
- .globl __Cache_Flushes
-__Cache_Flushes:
- .long 0,0 /* Explicit cache flushes */
- .globl __Context_Switches
-__Context_Switches:
- .long 0,0 /* Context switches */
- .globl __Hardware_Interrupts
-__Hardware_Interrupts:
- .long 0,0 /* I/O interrupts (disk, timer, etc) */
- .globl __TLBIAs
- .globl __TLBIAs
-__TLBIAs:
- .long 0,0 /* TLB cache forceably flushed */
- .globl __TLBIEs
-__TLBIEs:
- .long 0,0 /* Specific TLB entry flushed */
-#endif
-
- .globl _TotalMemory
-_TotalMemory:
- .long 0,0
-
-/*
- * This location is used to break any outstanding "lock"s when
- * changing contexts.
- */
-_break_lwarx: .long 0
-
+#endif /* CONFIG_PREP */
diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
index 41d453186..171bfaa5c 100644
--- a/arch/ppc/kernel/irq.c
+++ b/arch/ppc/kernel/irq.c
@@ -1,9 +1,13 @@
/*
- * linux/arch/ppc/kernel/irq.c
+ * arch/ppc/kernel/irq.c
*
- * Copyright (C) 1992 Linus Torvalds
- * Adapted from arch/i386 by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Power Macintosh version
+ * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * Derived from arch/i386/kernel/irq.c
+ * Copyright (C) 1992 Linus Torvalds
+ * Adapted from arch/i386 by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
*
* This file contains the code used by various IRQ handling routines:
* asking for different IRQ's should be done through these routines
@@ -11,7 +15,7 @@
* shouldn't result in any weird surprises, and installing new handlers
* should be easier.
*/
-
+
/*
* IRQ's are in fact implemented a bit like signal handlers for the kernel.
* Naturally it's not a 1:1 relation, but there are similarities.
@@ -25,323 +29,300 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/timex.h>
+#include <linux/config.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
-inline int get_irq_list(char *);
-void check_irq(void);
-void BeBox_CPU1(void);
-void BeBox_state(void);
-int BeBox_irq(void);
-void show_BeBox_state(void);
-void BeBox_enable_irq(int );
-void BeBox_disable_irq(int );
-void BeBox_init_IRQ(void);
-void _do_bottom_half(void);
-static _NOP(void);
-static _delay(void);
-void hard_disk_LED(int state);
+#define IRQ_FLAG ((unsigned *)0xf3000020)
+#define IRQ_ENABLE ((unsigned *)0xf3000024)
+#define IRQ_ACK ((unsigned *)0xf3000028)
+#define IRQ_LEVEL ((unsigned *)0xf300002c)
+
+#define KEYBOARD_IRQ 20 /* irq number for command-power interrupt */
+#undef SHOW_IRQ 1
-#define SHOW_IRQ
-#undef SHOW_IRQ
+unsigned lost_interrupts = 0;
+
+unsigned int local_irq_count[NR_CPUS];
+static struct irqaction irq_action[32];
/*
- * For the BeBox, interrupt numbers are 0..15 for 8259 PIC interrupts
- * and 16..31 for other BeBox motherboard type interrupts.
+ * This contains the irq mask for both irq controllers
*/
-
-unsigned long isBeBox[];
-unsigned char *BeBox_IO_page;
+static unsigned int cached_irq_mask = 0xffff;
+
+#define cached_21 (((char *)(&cached_irq_mask))[0])
+#define cached_A1 (((char *)(&cached_irq_mask))[1])
+
-static unsigned char cache_21 = 0xff;
-static unsigned char cache_A1 = 0xff;
+int __ppc_bh_counter;
-void disable_irq(unsigned int irq_nr)
+void *null_handler(int,void *,struct pt_regs *);
+
+/*
+ * disable and enable intrs in software. This is used
+ * from the non-realtime parts of Linux to disable interrupts.
+ * The realtime part disables/enables intrs in the hardware.
+ * -- Cort
+ */
+unsigned long soft_intr_enable = 1;
+void _soft_cli(void)
{
- unsigned char mask;
- int s = _disable_interrupts();
+ soft_intr_enable = 0;
+}
- if (isBeBox[0] && (irq_nr >= 16))
- {
- BeBox_disable_irq(irq_nr);
- } else
+void _soft_sti(void)
+{
+ soft_intr_enable = 1;
+ if ( lost_interrupts )
{
- mask = 1 << (irq_nr & 7);
- if (irq_nr < 8)
- {
- cache_21 |= mask;
- outb(cache_21,0x21);
- } else
- {
- cache_A1 |= mask;
- outb(cache_A1,0xA1);
- }
+ printk("lost_interrupts from _soft_sti() %x\n",lost_interrupts);
+ fake_interrupt();
}
- _enable_interrupts(s);
}
-void enable_irq(unsigned int irq_nr)
+void *
+null_handler(int a, void *b, struct pt_regs *regs)
+{
+ /*printk("irq.c: null_handler() called. Should not have happened.\n");*/
+}
+
+void
+disable_irq(unsigned int irq_nr)
{
- unsigned char mask;
int s = _disable_interrupts();
+ unsigned char mask;
- if (isBeBox[0] && (irq_nr >= 16))
+#ifdef CONFIG_PMAC
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr));
+#else /* CONFIG_PMAC */
+ mask = 1 << (irq_nr & 7);
+ if (irq_nr < 8)
{
- BeBox_enable_irq(irq_nr);
- _enable_interrupts(s);
- return;
+ cached_21 |= mask;
+ outb(cached_21,0x21);
} else
{
- mask = ~(1 << (irq_nr & 7));
- if (irq_nr < 8) {
- cache_21 &= mask;
- outb(cache_21,0x21);
- } else
- {
- cache_A1 &= mask;
- outb(cache_A1,0xA1);
- }
- }
+ cached_A1 |= mask;
+ outb(cached_A1,0xA1);
+ }
+#endif /* CONFIG_PMAC */
_enable_interrupts(s);
}
-/*
- * Irq handlers.
- */
-struct irq_action {
- void (*handler)(int, void *dev, struct pt_regs *);
- unsigned long flags;
- unsigned long mask;
- const char *name;
- int notified;
- void *dev_id;
-};
-
-static struct irq_action irq_action[32] = {
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL },
- { NULL, 0, 0, NULL }, { NULL, 0, 0, NULL }
-};
-
-
-inline int get_irq_list(char *buf)
+void
+enable_irq(unsigned int irq_nr)
{
- int i, len = 0;
- struct irq_action * action = irq_action;
-
- for (i = 0; i < 32; i++, action++) {
- if (!action->handler)
- continue;
- len += sprintf(buf+len, "%2d: %8d %c %s\n",
- i, kstat.interrupts[i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
- }
- return len;
-}
+ int s = _disable_interrupts();
+#ifdef CONFIG_PMAC
+ unsigned bit = 1U << irq_nr;
+
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) & ~(1 << irq_nr));
+ out_le32(IRQ_ENABLE, ld_le32(IRQ_ENABLE) | bit);
+
+ /*
+ * Unfortunately, setting the bit in the enable register
+ * when the device interrupt is already on *doesn't* set
+ * the bit in the flag register or request another interrupt.
+ */
+ if ((ld_le32(IRQ_LEVEL) & bit) && !(ld_le32(IRQ_FLAG) & bit))
+ lost_interrupts |= bit;
+#else /* CONFIG_PMAC */
+ if (irq_nr < 8) {
+ cached_21 &= ~(1 << (irq_nr & 7));
+ outb(cached_21,0x21);
+ } else
+ {
+ cached_A1 &= ~(1 << (irq_nr-8 & 7));
+ outb(cached_A1,0xA1);
+ }
+#endif /* CONFIG_PMAC */
-inline void
-process_IRQ(int irq, int _irq, struct pt_regs *regs)
-{
- struct irq_action *action;
- atomic_inc(&intr_count);
- if (irq < 16)
- {
- /* Mask interrupt */
- if (irq > 7)
- {
- cache_A1 |= (1<<(irq-8));
- outb(cache_A1, 0xA1);
- } else
- {
- cache_21 |= (1<<irq);
- outb(cache_21, 0x21);
- }
- }
- action = irq + irq_action;
- kstat.interrupts[irq]++;
- /* TEMP */
- /* On the Nobis, the keyboard interrupt "edge" gets lost - why? */
- if (irq == 0)
- {
- static int count;
- if (++count == 500)
- {
- if (inb(0x64) & 0x01)
- {
- struct irq_action *action;
- action = irq_action + 1; /* Keyboard */
- printk("Reset KBD, KBSTAT = %x, ELCR = %x/%x, MASK = %x/%x\n",
- inb(0x64), inb(0x4D0), inb(0x4D1), cache_21, cache_A1);
- action->handler(1, action->dev_id, regs);
- }
- count = 0;
- }
- }
- if (action->handler)
- {
- action->handler(irq, action->dev_id, regs);
- } else
- {
- printk("Bogus interrupt %d/%x, pc %x regs %x\n",
- irq, _irq,regs->nip,regs);
-#if 0
- printk("BeBox[] = %x/%x\n", isBeBox[0], isBeBox[1]);
- show_BeBox_state();
- cnpause();
-#endif
- }
- if (_disable_interrupts() && !action->notified)
- {
- action->notified = 1;
- printk("*** WARNING! %s handler [IRQ %d] turned interrupts on!\n",
- action->name, irq);
- }
- if (irq < 16)
- {
- /* Issue EOI to interrupt controller */
- if (irq > 7)
- {
- outb(0xE0|(irq-8), 0xA0);
- outb(0xE2, 0x20);
- } else
- {
- outb(0xE0|irq, 0x20);
- }
- if (!(action->flags & SA_ONESHOT))
- {
- /* Re-enable interrupt */
- if (irq > 7)
- {
- cache_A1 &= ~(1<<(irq-8));
- outb(cache_A1, 0xA1);
- } else
- {
- cache_21 &= ~(1<<irq);
- outb(cache_21, 0x21);
- }
- }
- } else
- {
- BeBox_enable_irq(irq);
- }
- atomic_dec(&intr_count);
+ _enable_interrupts(s);
}
-asmlinkage inline void handle_IRQ(struct pt_regs *regs)
+
+int get_irq_list(char *buf)
{
- int irq, _irq, s;
- struct irq_action *action;
- static int _ints;
-
- if (!isBeBox[0] || ((irq = BeBox_irq()) < 16))
- {
- /* Figure out IRQ#, etc. */
- outb(0x0C, 0x20); /* Poll interrupt controller */
- irq = _irq = inb(0x20);
- irq &= 0x07; /* Caution! */
- if (irq == 2)
- { /* Cascaded interrupt -> IRQ8..IRQ15 */
- outb(0x0C, 0xA0);
- irq = (_irq = inb(0xA0)) & 0x07;
- irq += 8;
- }
- }
- process_IRQ(irq, _irq, regs);
-
- /* Sometimes, the cascaded IRQ controller get's "stuck" */
- if ((irq == 0) && (_ints++ == 100))
- {
- _ints = 0;
- outb(0x0A, 0xA0); _irq = inb(0xA0);
- if (_irq & ~cache_A1)
- { /* Figure out which IRQs are present */
- _irq &= ~cache_A1;
- for (irq = 0; irq < 7; irq++)
- {
- if (_irq & (1<<irq))
- {
-#if 0
- printk("Dropped IRQ #%d\n", irq+8);
-#endif
- process_IRQ(irq+8, _irq, regs);
+ int i, len = 0;
+ struct irqaction * action;
+
+ for (i = 0 ; i < NR_IRQS ; i++) {
+ action = irq_action + i;
+ if (!action || !action->handler)
+ continue;
+ len += sprintf(buf+len, "%2d: %10u %s",
+ i, kstat.interrupts[i], action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s", action->name);
+ }
+ len += sprintf(buf+len, "\n");
}
- }
- }
- }
-}
-
/*
- * Display current IRQ state
+ * Linus - should you add NMI counts here ?????
*/
-
-void
-show_irq_state(void)
-{
- unsigned char state_21, state_A1;
- outb(0x0A, 0x20); state_21 = inb(0x20);
- outb(0x0A, 0xA0); state_A1 = inb(0xA0);
- printk("IRQ State = %x/%x, Edge = %x/%x, Processor = %d\n", state_21, state_A1, inb(0x4D0), inb(0x4D1), _Processor);
+#ifdef __SMP_PROF__
+ len+=sprintf(buf+len, "IPI: %8lu received\n",
+ ipi_count);
+#endif
+ return len;
}
-/*
- * Initialize interrupt controllers to a well-known state.
- */
-
-static void
-reset_int_controllers(void)
+asmlinkage void handle_IRQ(struct pt_regs *regs)
{
- /* Initialize interrupt controllers */
- outb(0x11, 0x20); /* Start init sequence */
- outb(0x40, 0x21); /* Vector base */
- outb(0x04, 0x21); /* Cascade (slave) on IRQ2 */
- outb(0x01, 0x21); /* Select 8086 mode */
- outb(0xFF, 0x21); /* Mask all */
- outb(0x11, 0xA0); /* Start init sequence */
- outb(0x48, 0xA1); /* Vector base */
- outb(0x02, 0xA1); /* Cascade (slave) on IRQ2 */
- outb(0x01, 0xA1); /* Select 8086 mode */
- outb(0xFF, 0xA1); /* Mask all */
-#if 0
- outb(0x00, 0x4D0); /* All edge triggered */
- outb(0xCF, 0x4D1); /* Trigger mode */
+ int irq;
+ unsigned bits;
+ struct irqaction *action;
+ int cpu = smp_processor_id();
+
+ hardirq_enter(cpu);
+
+#ifdef CONFIG_PMAC
+ bits = ld_le32(IRQ_FLAG) | lost_interrupts;
+ lost_interrupts = 0;
+
+ for (irq = NR_IRQS; irq >= 0; --irq)
+ if (bits & (1U << irq))
+ break;
+#else /* CONFIG_PMAC */
+#if 1
+ if ( lost_interrupts )
+ {
+ irq = ffz(~lost_interrupts);
+ lost_interrupts &= ~irq;
+ goto retry;
+ }
+ outb(0x0C, 0x20);
+ irq = inb(0x20) & 7;
+ if (irq == 2)
+ {
+retry_cascade:
+ outb(0x0C, 0xA0);
+ irq = inb(0xA0);
+ /* if no intr left */
+ if ( !(irq & 128 ) )
+ goto out;
+ irq = (irq&7) + 8;
+ }
+retry:
+#else
+ /* get the irr from the intr controller */
+ outb(0x0A, 0x20);
+ bits = inb(0x20);
+ /* handle cascade */
+ if ( bits )
+ {
+ bits &= 4;
+ outb(0x0A, 0xA0);
+ bits = inb(0xA0)<<8;
+ }
+ /* get lost interrupts */
+ bits |= lost_interrupts;
+ /* save intrs that are masked out */
+ lost_interrupts = bits & cached_irq_mask;
+ /* get rid of intrs being masked */
+ bits &= ~cached_irq_mask;
+ /* non-specifc eoi */
+ outb(0x20,0x20);
+ if ( bits & 0xff00 )
+ outb(0x20,0xA0);
+
+ printk("bits %04X lost %04X mask %04x\n",
+ bits, lost_interrupts,cached_irq_mask);
+
+ for (irq = NR_IRQS; irq >= 0; --irq)
+ if (bits & (1U << irq))
+ break;
#endif
- outb(cache_A1, 0xA1);
- outb(cache_21, 0x21);
- enable_irq(2); /* Enable cascade interrupt */
+#endif /* CONFIG_PMAC */
+
+ if (irq < 0) {
+ printk("Bogus interrupt from PC = %lx, irq %d\n",regs->nip,irq);
+ goto out;
+ }
+
+#ifdef CONFIG_PMAC
+ out_le32(IRQ_ACK, 1U << irq);
+#else /* CONFIG_PMAC */
+ /* mask out the irq while handling it */
+ disable_irq(irq);
+ /*
+ * send eoi to interrupt controller right away or lower
+ * priority intrs would be ignored even if with intrs enabled
+ */
+ if (irq > 7)
+ {
+ outb(0xE0|(irq-8), 0xA0);
+ outb(0xE2, 0x20);
+ } else
+ {
+ outb(0xE0|irq, 0x20);
+ }
+#endif /* !CONFIG_PMAC */
+
+ /*
+ * now that we've acked the irq, if intrs are disabled in software
+ * we're in the real-time system and non-rt linux has disabled them
+ * so we just queue it up and return -- Cort
+ */
+ if ( ! soft_intr_enable )
+ {
+ lost_interrupts |= 1UL << irq;
+ /* can't printk - kernel expects intrs off! */
+ /*printk("irq %d while intrs soft disabled\n", irq);*/
+ goto out;
+ }
+
+ action = irq + irq_action;
+ kstat.interrupts[irq]++;
+ if (action->handler) {
+ action->handler(irq, action->dev_id, regs);
+ _disable_interrupts(); /* in case the handler turned them on */
+ } else {
+ disable_irq( irq );
+ }
+#ifdef CONFIG_PREP
+ /* re-enable if the interrupt was good and isn't one-shot */
+ if ( action->handler && !(action->flags & SA_ONESHOT) )
+ enable_irq(irq);
+ /* make sure we don't miss any cascade intrs due to eoi-ing irq 2 */
+ if ( irq > 7 )
+ goto retry_cascade;
+#endif
+
+ hardirq_exit(cpu);
+ /*
+ * This should be conditional: we should really get
+ * a return code from the irq handler to tell us
+ * whether the handler wants us to do software bottom
+ * half handling or not..
+ */
+ if (1)
+ if (bh_active & bh_mask)
+ do_bottom_half();
+ return;
+out:
+ hardirq_exit(cpu);
+
}
int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname, void *dev_id)
+ unsigned long irqflags, const char * devname, void *dev_id)
{
- struct irq_action * action;
+ struct irqaction * action;
unsigned long flags;
-
-#ifdef SHOW_IRQ
-if (irq) printk("Request IRQ #%d, Handler: %x\n", irq, handler);
-#endif
- if (irq > 15)
- {
- if (!isBeBox[0] || (irq > 31))
- return -EINVAL;
- }
+
+#ifdef SHOW_IRQ
+ printk("request_irq(): irq %d handler %08x name %s dev_id %04x\n",
+ irq,handler,devname,dev_id);
+#endif /* SHOW_IRQ */
+
+ if (irq > NR_IRQS)
+ return -EINVAL;
action = irq + irq_action;
if (action->handler)
return -EBUSY;
@@ -361,10 +342,14 @@ if (irq) printk("Request IRQ #%d, Handler: %x\n", irq, handler);
void free_irq(unsigned int irq, void *dev_id)
{
- struct irq_action * action = irq + irq_action;
+ struct irqaction * action = irq + irq_action;
unsigned long flags;
- if (irq > 31) {
+#ifdef SHOW_IRQ
+ printk("free_irq(): irq %d dev_id %04x\n", irq, dev_id);
+#endif /* SHOW_IRQ */
+
+ if (irq > NR_IRQS) {
printk("Trying to free IRQ%d\n",irq);
return;
}
@@ -383,15 +368,6 @@ void free_irq(unsigned int irq, void *dev_id)
restore_flags(flags);
}
-#define SA_PROBE SA_ONESHOT
-
-static void no_action(int irq, void *dev, struct pt_regs * regs)
-{
-#ifdef DEBUG
- printk("Probe got IRQ: %d\n", irq);
-#endif
-}
-
unsigned long probe_irq_on (void)
{
unsigned int i, irqs = 0, irqmask;
@@ -399,7 +375,7 @@ unsigned long probe_irq_on (void)
/* first, snaffle up any unassigned irqs */
for (i = 15; i > 0; i--) {
- if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
+ if (!request_irq(i, null_handler, SA_ONESHOT, "probe", NULL)) {
enable_irq(i);
irqs |= (1 << i);
}
@@ -409,7 +385,7 @@ unsigned long probe_irq_on (void)
for (delay = jiffies + 2; delay > jiffies; ); /* min 10ms delay */
/* now filter out any obviously spurious interrupts */
- irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+ irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i) & irqmask) {
irqs ^= (1 << i);
@@ -426,13 +402,13 @@ int probe_irq_off (unsigned long irqs)
{
unsigned int i, irqmask;
- irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+ irqmask = (((unsigned int)cached_A1)<<8) | (unsigned int)cached_21;
for (i = 15; i > 0; i--) {
if (irqs & (1 << i)) {
free_irq(i, NULL);
}
}
-#ifdef DEBUG
+#ifdef SHOW_IRQ
printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
#endif
irqs &= irqmask;
@@ -443,209 +419,65 @@ int probe_irq_off (unsigned long irqs)
i = -i;
return i;
}
-
-void init_IRQ(void)
-{
- int i;
-
- if ((_get_PVR()>>16) == 1) /* PPC 601 */
- { /* Nobis? */
- reset_int_controllers();
- }
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
- /* set the clock to 100 Hz */
- outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */
- outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
- outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
- if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
- printk("Unable to get IRQ2 for cascade\n");
- request_region(0x20,0x20,"pic1");
- request_region(0xa0,0x20,"pic2");
-
- /* Make sure IRQ2 (cascade) interrupt is "level" based */
- outb(inb(0x4D0)|0x04, 0x4D0); /* IRQ2 level based */
-
- /* Set up PCI interrupts */
- route_PCI_interrupts();
-
- if (isBeBox[0])
- {
- BeBox_init_IRQ();
- }
-}
-/*
- * Wrapper for "bottom 1/2" of interrupt processing. This routine
- * is called whenever an interrupt needs non-interrupt-time service.
- */
-
-void _do_bottom_half(void)
-{
- _enable_interrupts(1);
- do_bottom_half();
- _disable_interrupts();
-}
-
-void hard_disk_LED(int state)
-{
- if (_Processor == _PROC_IBM) {
- outb(state, IBM_HDD_LED);
- }
-}
-
-
-/*
- * Support for interrupts on the BeBox
- */
-
-#define CPU0_INT_MASK (volatile unsigned long *)(BeBox_IO_page+0x0F0)
-#define CPU1_INT_MASK (volatile unsigned long *)(BeBox_IO_page+0x1F0)
-#define INT_SOURCE (volatile unsigned long *)(BeBox_IO_page+0x2F0)
-#define CPU_RESET (volatile unsigned long *)(BeBox_IO_page+0x4F0)
-
-#define _CPU0_INT_MASK (volatile unsigned long *)(0xA0000000+0x0F0)
-#define _CPU1_INT_MASK (volatile unsigned long *)(0xA0000000+0x1F0)
-#define _INT_SOURCE (volatile unsigned long *)(0xA0000000+0x2F0)
-#define _CPU_RESET (volatile unsigned long *)(0xA0000000+0x4F0)
-
-#define CPU_HRESET 0x20000000
-#define CPU_SRESET 0x40000000
-
-#define SCSI_IRQ 16
-
-#define INT_SCSI (1<<21)
-#define INT_8259 (1<<5)
-
-/*
- * Map of pseudo IRQs to actual bits
- * Note: We give out IRQ #16..31 for all interrupt sources which are
- * not found in the 8259 PIC.
- */
-
-unsigned long BeBox_IRQ_map[] =
- {
- INT_SCSI, /* 16 - SCSI */
- 0x00000000, /* 17 - Unused */
- 0x00000000, /* 18 - Unused */
- 0x00000000, /* 19 - Unused */
- 0x00000000, /* 20 - Unused */
- 0x00000000, /* 21 - Unused */
- 0x00000000, /* 22 - Unused */
- 0x00000000, /* 23 - Unused */
- 0x00000000, /* 24 - Unused */
- 0x00000000, /* 25 - Unused */
- 0x00000000, /* 26 - Unused */
- 0x00000000, /* 27 - Unused */
- 0x00000000, /* 28 - Unused */
- 0x00000000, /* 29 - Unused */
- 0x00000000, /* 30 - Unused */
- 0x00000000, /* 31 - Unused */
- };
-
-volatile int CPU1_alive;
-volatile int CPU1_trace;
-
-static
-_NOP(void)
-{
-}
-
-static
-_delay(void)
+void init_IRQ(void)
{
- int i;
- for (i = 0; i < 100; i++) _NOP();
-}
+#ifdef CONFIG_PMAC
+ extern void xmon_irq(int, void *, struct pt_regs *);
-void
-BeBox_init_IRQ(void)
-{
- int tmr;
- volatile extern long BeBox_CPU1_vector;
- *CPU0_INT_MASK = 0x0FFFFFFC; /* Clear all bits? */
- *CPU0_INT_MASK = 0x80000003 | INT_8259;
- *CPU1_INT_MASK = 0x0FFFFFFC;
-printk("Start CPU #1 - CPU Status: %x\n", *CPU_RESET);
- BeBox_CPU1_vector = 0x0100; /* Reset */
- tmr = 0;
- while (CPU1_alive == 0)
- {
- if (++tmr == 1000)
- {
-printk("CPU #1 not there? - CPU Status: %x, Trace: %x\n", *CPU_RESET, CPU1_trace);
- break;
- }
- _delay();
- }
-printk("CPU #1 running!\n");
-}
+ *IRQ_ENABLE = 0;
+ request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0);
+#else /* CONFIG_PMAC */
+ /* Initialize interrupt controllers */
+ outb(0x11, 0x20); /* Start init sequence */
+ outb(0x40, 0x21); /* Vector base */
+#if 1
+ outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+#else
+ outb(0x0C, 0x21); /* level triggered, Cascade (slave) on IRQ2 */
+#endif
+
+ outb(0x01, 0x21); /* Select 8086 mode */
+ outb(0xFF, 0x21); /* Mask all */
-void
-BeBox_disable_irq(int irq)
-{
- /* Note: this clears the particular bit */
- *CPU0_INT_MASK = BeBox_IRQ_map[irq-16];
-}
+ outb(0x11, 0xA0); /* Start init sequence */
+ outb(0x48, 0xA1); /* Vector base */
+#if 1
+ outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
+#else
+ outb(0x0A, 0x21); /* level triggered, Cascade (slave) on IRQ2 */
+#endif
+ outb(0x01, 0xA1); /* Select 8086 mode */
+ outb(0xFF, 0xA1); /* Mask all */
-void
-BeBox_enable_irq(int irq)
-{
- int s = _disable_interrupts();
- /* Sets a single bit */
+ /*
+ * Program level mode for irq's that 'can' be level triggered.
+ * This does not effect irq's 0,1,2 and 8 since they must be
+ * edge triggered. This is not the PIC controller. The default
+ * here is for edge trigger mode. -- Cort
+ */
#if 0
-printk("BeBox IRQ Mask = %x", *CPU0_INT_MASK);
+ outb(0xf8, 0x4d0); /* level triggered */
+ outb(0xff, 0x4d1);
#endif
- *CPU0_INT_MASK = 0x80000000 | BeBox_IRQ_map[irq-16];
-#if 0
-printk("/%x\n", *CPU0_INT_MASK);
-#endif
- _enable_interrupts(s);
-}
-
-void
-show_BeBox_state(void)
-{
- unsigned long cpu0_int_mask;
- unsigned long int_state;
- cpu0_int_mask = (*CPU0_INT_MASK & 0x0FFFFFFC) & ~INT_8259;
- int_state = cpu0_int_mask & *INT_SOURCE;
- printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-}
-
-int
-BeBox_irq(void)
-{
- int i;
- unsigned long cpu0_int_mask;
- unsigned long int_state;
- cpu0_int_mask = (*CPU0_INT_MASK & 0x0FFFFFFC) & ~INT_8259;
- int_state = cpu0_int_mask & *INT_SOURCE;
- if (int_state)
- { /* Determine the pseudo-interrupt # */
#if 0
- printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-#endif
- for (i = 0; i < 16; i++)
- {
- if (BeBox_IRQ_map[i] & int_state)
- {
- return (i+16);
- }
- }
-printk("Ints[%x] = %x, Mask[%x] = %x/%x, State = %x\n", INT_SOURCE, *INT_SOURCE, CPU0_INT_MASK, *CPU0_INT_MASK, cpu0_int_mask, int_state);
-printk("Can't find BeBox IRQ!\n");
- }
- return (0);
-}
-
-void BeBox_state(void)
-{
- printk("Int state = %x, CPU0 mask = %x, CPU1 mask = %x\n", *INT_SOURCE, *CPU0_INT_MASK, *CPU1_INT_MASK);
-}
-
-void BeBox_CPU1(void)
-{
- CPU1_alive++;
- while (1) ;
+ outb(0x00, 0x4D0); /* All edge triggered */
+ outb(0xCF, 0x4D1); /* Trigger mode */
+#endif
+ outb(cached_A1, 0xA1);
+ outb(cached_21, 0x21);
+ if (request_irq(2, null_handler, SA_INTERRUPT, "cascade", NULL))
+ printk("Unable to get IRQ2 for cascade\n");
+ enable_irq(2); /* Enable cascade interrupt */
+
+#define TIMER0_COUNT 0x40
+#define TIMER_CONTROL 0x43
+ /* set timer to periodic mode */
+ outb_p(0x34,TIMER_CONTROL); /* binary, mode 2, LSB/MSB, ch 0 */
+ /* set the clock to ~100 Hz */
+ outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */
+ outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */
+
+ route_pci_interrupts();
+#endif /* CONFIG_PMAC */
}
diff --git a/arch/ppc/kernel/ksyms.c b/arch/ppc/kernel/ksyms.c
index b59b8964e..b246fa6df 100644
--- a/arch/ppc/kernel/ksyms.c
+++ b/arch/ppc/kernel/ksyms.c
@@ -1,4 +1,40 @@
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/smp.h>
+#include <linux/elfcore.h>
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+void transfer_to_handler();
+void int_return();
+void syscall_trace();
+void handle_IRQ();
+void MachineCheckException();
+void AlignmentException();
+void ProgramCheckException();
+void SingleStepException();
+void FloatingPointCheckException();
+void sys_sigreturn();
+unsigned long sys_call_table[];
+
+extern struct task_struct *current_set[1];
/* platform dependent support */
+EXPORT_SYMBOL(current_set);
+EXPORT_SYMBOL(do_signal);
+EXPORT_SYMBOL(syscall_trace);
+EXPORT_SYMBOL(transfer_to_handler);
+EXPORT_SYMBOL(int_return);
+EXPORT_SYMBOL(handle_IRQ);
+EXPORT_SYMBOL(init_task_union);
+EXPORT_SYMBOL(MachineCheckException);
+EXPORT_SYMBOL(AlignmentException);
+EXPORT_SYMBOL(ProgramCheckException);
+EXPORT_SYMBOL(SingleStepException);
+EXPORT_SYMBOL(FloatingPointCheckException);
+EXPORT_SYMBOL(sys_sigreturn);
+EXPORT_SYMBOL(sys_call_table);
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index c2a2989ec..430cd7a5d 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -1,234 +1,40 @@
/*
- * This module contains the PowerPC interrupt fielders
- * set of code at specific locations, based on function
+ * This file contains miscellaneous low-level functions.
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * 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 "ppc_asm.tmpl"
+#include <linux/config.h>
#include <linux/sys.h>
+#include <asm/unistd.h>
#include <asm/errno.h>
-#include "ppc_defs.h"
#include <asm/processor.h>
-
-/* Keep track of low-level exceptions - rather crude, but informative */
-#define STATS
-
-/*
- * Increment a [64 bit] statistic counter
- * Uses R2, R3
- */
-#define BUMP(ctr) \
- lis r2,ctr@h; \
- ori r2,r2,ctr@l; \
- lwz r3,4(r2); \
- addic r3,r3,1; \
- stw r3,4(r2); \
- lwz r3,0(r2); \
- addze r3,r3; \
- stw r3,0(r2)
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
-/*#ifdef CONFIG_603*/
-/* This instruction is not implemented on the PPC 603 */
+/* This instruction is not implemented on the PPC 601 or 603 */
#define tlbia \
- li r4,64; \
+ li r4,128; \
mtspr CTR,r4; \
li r4,0; \
0: tlbie r4; \
addi r4,r4,0x1000; \
bdnz 0b
-/*#endif*/ /* CONFIG_603*/
_TEXT()
-#define CPU_CTL 0x80000092
-_GLOBAL(hard_reset_now)
- mfmsr r3 /* Disable interrupts */
- li r4,0
- ori r4,r4,MSR_EE
- andc r3,r3,r4
- ori r3,r3,MSR_IP /* Set FLASH/ROM interrupt handlers */
- sync
- mtmsr r3
- lis r3,CPU_CTL>>16
- ori r3,r3,(CPU_CTL&0xFFFF)
- lbz r4,0(r3) /* Turn on SRESET */
- li r5,1
- andc r4,r4,r5 /* Make sure we go from 0->1 */
- stb r4,0(r3)
- ori r4,r4,1
- stb r4,0(r3) /* This should do it! */
-99: nop
- b 99b
-
-#if 0
-/*
- unsigned short
- le16_to_cpu(unsigned short val)
-*/
-_GLOBAL(le16_to_cpu)
- lis r4,_le_scratch@h
- ori r4,r4,_le_scratch@l
- sth r3,0(r4)
- li r5,0
- lhbrx r3,r4,r5
- blr
-
-_GLOBAL(le32_to_cpu)
- lis r4,_le_scratch@h
- ori r4,r4,_le_scratch@l
- stw r3,0(r4)
- li r5,0
- lwbrx r3,r4,r5
- blr
-_GLOBAL(_le_scratch)
- .space 4
-#endif
-#if 1
-/*
-extern int __put_user_8(char, char *);
-extern int __put_user_16(short, short *);
-extern int __put_user_32(long, long *);
-*/
-_GLOBAL(__put_user_8)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
-
- stb r3,0(r4)
- li r3,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r3,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-
-_GLOBAL(__put_user_16)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
-
- sth r3,0(r4)
- li r3,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r3,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-_GLOBAL(__put_user_32)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
-
- stw r3,0(r4)
- li r3,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r3,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-
-_GLOBAL(__get_user_8)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
-
- lbz r3,0(r4)
- li r4,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r4,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-
-_GLOBAL(__get_user_16)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
-
- lhz r3,0(r4)
- li r4,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r4,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-
-_GLOBAL(__get_user_32)
- /* setup exception stuff */
- lis r2,current_set@ha
- lwz r2,current_set@l(r2)
- /* increment excount */
- lwz r6,TSS+TSS_EXCOUNT(r2)
- addi r6,r6,1
- stw r6,TSS+TSS_EXCOUNT(r2)
- /* set expc */
- lis r6,1f@h
- ori r6,r6,1f@l
- stw r6,TSS+TSS_EXPC(r2)
- lwz r3,0(r4)
- li r4,0 /* successful return */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-1: li r4,-EFAULT /* bad access */
- li r6,0
- stw r6,TSS+TSS_EXCOUNT(r2)
- blr
-#endif
/*
* Disable interrupts
* rc = _disable_interrupts()
*/
_GLOBAL(_disable_interrupts)
+_GLOBAL(__cli)
+_GLOBAL(_hard_cli)
mfmsr r0 /* Get current interrupt state */
rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
li r4,0 /* Need [unsigned] value of MSR_EE */
@@ -244,20 +50,18 @@ _GLOBAL(_disable_interrupts)
* turns on interrupts if state = 1.
*/
_GLOBAL(_enable_interrupts)
- mfmsr r0 /* Get current state */
- rlwimi r0,r3,16-1,32-16,32-16 /* Insert bit */
+ cmpi 0,r3,0 /* turning them on? */
+ beqlr /* nothing to do if state == 0 */
+_GLOBAL(__sti)
+_GLOBAL(_hard_sti)
+ lis r4,lost_interrupts@ha
+ lwz r4,lost_interrupts@l(r4)
+ mfmsr r3 /* Get current state */
+ ori r3,r3,MSR_EE /* Turn on 'EE' bit */
+ cmpi 0,r4,0 /* lost interrupts to process first? */
+ bne- do_lost_interrupts
sync /* Some chip revs have problems here... */
- mtmsr r0 /* Update machine state */
- blr
-
-/*
- * Get 'flags' (aka machine status register)
- * __save_flags(long *ptr)
- */
-_GLOBAL(__save_flags)
- mfmsr r0 /* Get current state */
- stw r0,0(r3)
- mr r3,r0
+ mtmsr r3 /* Update machine state */
blr
/*
@@ -265,34 +69,37 @@ _GLOBAL(__save_flags)
* __restore_flags(long val)
*/
_GLOBAL(__restore_flags)
- sync /* Some chip revs have problems here... */
+ andi. r0,r3,MSR_EE /* enabling interrupts? */
+ beq 2f
+ lis r4,lost_interrupts@ha
+ lwz r4,lost_interrupts@l(r4)
+ cmpi 0,r4,0
+ bne do_lost_interrupts
+2: sync /* Some chip revs have problems here... */
mtmsr r3
isync
blr
/*
- * Disable interrupts - like an 80x86
- * cli()
- */
-_GLOBAL(cli)
- mfmsr r0 /* Get current interrupt state */
- rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
- li r4,0 /* Need [unsigned] value of MSR_EE */
- ori r4,r4,MSR_EE /* Set to turn off bit */
- andc r0,r0,r4 /* Clears bit in (r4) */
- sync /* Some chip revs have problems here... */
- mtmsr r0 /* Update machine state */
- blr /* Done */
-
-/*
- * Enable interrupts - like an 80x86
- * sti()
+ * We were about to enable interrupts but we have to simulate
+ * some interrupts that were lost by enable_irq first.
*/
-_GLOBAL(sti)
- mfmsr r0 /* Get current state */
- ori r0,r0,MSR_EE /* Turn on 'EE' bit */
- sync /* Some chip revs have problems here... */
- mtmsr r0 /* Update machine state */
+do_lost_interrupts:
+ stwu r1,-16(r1)
+ mflr r0
+ stw r0,20(r1)
+ stw r3,8(r1)
+1: bl fake_interrupt
+ lis r4,lost_interrupts@ha
+ lwz r4,lost_interrupts@l(r4)
+ cmpi 0,r4,0
+ bne- 1b
+ lwz r3,8(r1)
+ sync
+ mtmsr r3
+ lwz r0,20(r1)
+ mtlr r0
+ addi r1,r1,16
blr
/*
@@ -300,7 +107,6 @@ _GLOBAL(sti)
*/
_GLOBAL(_tlbia)
tlbia
- BUMP(__TLBIAs)
blr
/*
@@ -308,17 +114,7 @@ _GLOBAL(_tlbia)
*/
_GLOBAL(_tlbie)
tlbie r3
- BUMP(__TLBIEs)
blr
-
-/*
- * Fetch the current SR register
- * get_SR(int index)
- */
-_GLOBAL(get_SR)
- mfsrin r3,r3
- blr
-
/*
* Atomic [test&set] exchange
*
@@ -340,7 +136,11 @@ _GLOBAL(xchg_u32)
* void atomic_sub(int c, int *v)
* void atomic_inc(int *v)
* void atomic_dec(int *v)
- * void atomic_dec_and_test(int *v)
+ * int atomic_dec_and_test(int *v)
+ * int atomic_inc_return(int *v)
+ * int atomic_dec_return(int *v)
+ * void atomic_clear_mask(atomic_t mask, atomic_t *addr)
+ * void atomic_set_mask(atomic_t mask, atomic_t *addr);
*/
_GLOBAL(atomic_add)
10: lwarx r5,0,r4 /* Fetch old value & reserve */
@@ -360,69 +160,46 @@ _GLOBAL(atomic_inc)
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
blr
+_GLOBAL(atomic_inc_return)
+10: lwarx r5,0,r3 /* Fetch old value & reserve */
+ addi r5,r5,1 /* Perform 'add' operation */
+ stwcx. r5,0,r3 /* Update with new value */
+ bne- 10b /* Retry if "reservation" (i.e. lock) lost */
+ mr r3,r5 /* Return new value */
+ blr
_GLOBAL(atomic_dec)
10: lwarx r5,0,r3 /* Fetch old value & reserve */
subi r5,r5,1 /* Perform 'add' operation */
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
blr
+_GLOBAL(atomic_dec_return)
+10: lwarx r5,0,r3 /* Fetch old value & reserve */
+ subi r5,r5,1 /* Perform 'add' operation */
+ stwcx. r5,0,r3 /* Update with new value */
+ bne- 10b /* Retry if "reservation" (i.e. lock) lost */
+ mr r3,r5 /* Return new value */
+ blr
_GLOBAL(atomic_dec_and_test)
10: lwarx r5,0,r3 /* Fetch old value & reserve */
subi r5,r5,1 /* Perform 'add' operation */
stwcx. r5,0,r3 /* Update with new value */
bne- 10b /* Retry if "reservation" (i.e. lock) lost */
cmpi 0,r5,0 /* Return 'true' IFF 0 */
- bne 15f
li r3,1
+ beqlr
+ li r3,0
blr
-15: li r3,0
- blr
-
-
-/*
- * Delay for a specific # of "loops"
- * __delay(int loops)
- */
-_GLOBAL(__delay)
- mtctr r3
-00: addi r3,r3,0 /* NOP */
- bdnz 00b
- blr
-
-/*
- * Delay for a number of microseconds
- * udelay(int usecs)
- */
-_GLOBAL(udelay)
-00: li r0,86 /* Instructions / microsecond? */
- mtctr r0
-10: addi r0,r0,0 /* NOP */
- bdnz 10b
- subic. r3,r3,1
- bne 00b
- blr
-
-/*
- * Atomically increment [intr_count]
- */
-_GLOBAL(start_bh_atomic)
- lis r3,intr_count@h
- ori r3,r3,intr_count@l
-10: lwarx r4,0,r3
- addi r4,r4,1
- stwcx. r4,0,r3
+_GLOBAL(atomic_clear_mask)
+10: lwarx r5,0,r4
+ andc r5,r5,r3
+ stwcx. r5,0,r4
bne- 10b
blr
-
-/*
- * Atomically decrement [intr_count]
- */
-_GLOBAL(end_bh_atomic)
- lis r3,intr_count@h
- ori r3,r3,intr_count@l
-10: lwarx r4,0,r3
- subic r4,r4,1
- stwcx. r4,0,r3
+_GLOBAL(atomic_set_mask)
+10: lwarx r5,0,r4
+ or r5,r5,r3
+ stwcx. r5,0,r4
bne- 10b
blr
@@ -431,6 +208,8 @@ _GLOBAL(end_bh_atomic)
*
* insw(port, buf, len)
* outsw(port, buf, len)
+ * insl(port, buf, len)
+ * outsl(port, buf, len)
*/
_GLOBAL(_insw)
mtctr r5
@@ -448,135 +227,39 @@ _GLOBAL(_outsw)
bdnz 00b
blr
-#if 0
-/*
- *extern inline int find_first_zero_bit(void * vaddr, unsigned size)
- *{
- * unsigned long res;
- * unsigned long *p;
- * unsigned long *addr = vaddr;
- *
- * if (!size)
- * return 0;
- * __asm__ __volatile__ (" moveq #-1,d0\n\t"
- * "1:"
- * " cmpl %1@+,d0\n\t"
- * " bne 2f\n\t"
- * " subql #1,%0\n\t"
- * " bne 1b\n\t"
- * " bra 5f\n\t"
- * "2:"
- * " movel %1@-,d0\n\t"
- * " notl d0\n\t"
- * " bfffo d0{#0,#0},%0\n\t"
- * "5:"
- * : "=d" (res), "=a" (p)
- * : "0" ((size + 31) >> 5), "1" (addr)
- * : "d0");
- * return ((p - addr) << 5) + res;
- *}
- */
-_GLOBAL(find_first_zero_bit)
- li r5,0 /* bit # */
- subi r3,r3,4 /* Adjust pointer for auto-increment */
-00: lwzu r0,4(r3) /* Get next word */
- not. r7,r0 /* Complement to find ones */
- beq 10f /* Jump if all ones */
-02: andi. r7,r0,1 /* Check low-order bit */
- beq 20f /* All done when zero found */
- srawi r0,r0,1
- addi r5,r5,1
- b 02b
-10: addi r5,r5,32 /* Update bit # */
- subic. r4,r4,32 /* Any more? */
- bgt 00b
-20: mr r3,r5 /* Compute result */
+_GLOBAL(_insl)
+ mtctr r5
+ subi r4,r4,4
+00: lwbrx r5,0,r3
+ stwu r5,4(r4)
+ bdnz 00b
blr
-
-/*
- *static inline int find_next_zero_bit (void *vaddr, int size,
- * int offset)
- *{
- * unsigned long *addr = vaddr;
- * unsigned long *p = addr + (offset >> 5);
- * int set = 0, bit = offset & 31, res;
- *
- * if (bit) {
- * // Look for zero in first longword
- * __asm__("bfffo %1{#0,#0},%0"
- * : "=d" (set)
- * : "d" (~*p << bit));
- * if (set < (32 - bit))
- * return set + offset;
- * set = 32 - bit;
- * p++;
- * }
- * // No zero yet, search remaining full bytes for a zero
- * res = find_first_zero_bit (p, size - 32 * (p - addr));
- * return (offset + set + res);
- *}
- */
-_GLOBAL(find_next_zero_bit)
- addi r5,r5,1 /* bump offset to start */
- srawi r6,r5,5 /* word offset */
- add r6,r6,r6 /* byte offset */
- add r6,r6,r6 /* byte offset */
- add r3,r3,r6 /* compute byte position */
- sub r4,r4,r5 /* adjust size by starting index */
- andi. r0,r5,0x1F /* offset in current word? */
- beq 10f /* at start of word */
- lwz r0,0(r3) /* get word */
- sraw r0,r0,r5 /* shift right */
- not. r7,r0
- beq 07f /* jump if only ones remain */
-05: andi. r7,r0,1 /* found zero? */
- beq 90f /* yes - all done */
- srawi r0,r0,1
- addi r5,r5,1
- b 05b
-07: andi. r6,r5,0x1F
- subfic r0,r6,32
- add r5,r5,r0
- sub r4,r4,r0
- b 20f
-10: subi r3,r3,4 /* Adjust pointer for auto-increment */
-20: lwzu r0,4(r3) /* Get next word */
- not. r7,r0 /* Complement to find ones */
- beq 40f /* Jump if all ones */
-30: andi. r7,r0,1 /* Check low-order bit */
- beq 90f /* All done when zero found */
- srawi r0,r0,1
- addi r5,r5,1
- b 30b
-40: addi r5,r5,32 /* Update bit # */
- subic. r4,r4,32 /* Any more? */
- bgt 20b
-90: mr r3,r5 /* Compute result */
+
+_GLOBAL(_outsl)
+ mtctr r5
+ subi r4,r4,4
+00: lwzu r5,4(r4)
+ stwbrx r5,0,r3
+ bdnz 00b
+ blr
+
+#ifdef CONFIG_PMAC
+_GLOBAL(ide_insw)
+ mtctr r5
+ subi r4,r4,2
+00: lhzx r5,0,r3
+ sthu r5,2(r4)
+ bdnz 00b
blr
+
+_GLOBAL(ide_outsw)
+ mtctr r5
+ subi r4,r4,2
+00: lhzu r5,2(r4)
+ sthx r5,0,r3
+ bdnz 00b
+ blr
#endif
-
-/*
- *
- * ffz = Find First Zero in word. Undefined if no zero exists,
- * so code should check against ~0UL first..
- *
- *extern inline unsigned long ffz(unsigned long word)
- *{
- * __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
- * : "=d" (word)
- * : "d" (~(word)));
- * return word;
- *}
- */
-_GLOBAL(ffz)
- mr r4,r3
- li r3,0
-10: andi. r0,r4,1 /* Find the zero we know is there */
- srawi r4,r4,1
- beq 90f
- addi r3,r3,1
- b 10b
-90: blr
/*
* Extended precision shifts
@@ -605,43 +288,7 @@ _GLOBAL(__ashldi3)
slw r3,r3,r5 /* YYY--- */
or r3,r3,r7 /* YYYZZZ */
blr
-
-_GLOBAL(abort)
- .long 0
-
-/* in include/asm/string.h now -- Cort */
-#if 0
-_GLOBAL(bzero)
-#define bufp r3
-#define len r4
-#define pat r5
-/* R3 has buffer */
-/* R4 has length */
-/* R5 has pattern */
- cmpi 0,len,0 /* Exit if len <= 0 */
- ble 99f
- andi. r0,bufp,3 /* Must be on longword boundary */
- bne 10f /* Use byte loop if not aligned */
- andi. r0,len,3 /* Check for overrage */
- subi bufp,bufp,4 /* Adjust pointer */
- srawi len,len,2 /* Divide by 4 */
- blt 99f /* If negative - bug out! */
- mtspr CTR,len /* Set up counter */
- li pat,0
-00: stwu pat,4(bufp) /* Store value */
- bdnz 00b /* Loop [based on counter] */
- mr len,r0 /* Get remainder (bytes) */
-10: cmpi 0,len,0 /* Any bytes left */
- ble 99f /* No - all done */
- mtspr CTR,len /* Set up counter */
- subi bufp,bufp,1 /* Adjust pointer */
- li pat,0
-20: stbu pat,1(bufp) /* Store value */
- bdnz 20b /* Loop [based on counter] */
-99: blr
-#endif
-
_GLOBAL(abs)
cmpi 0,r3,0
bge 10f
@@ -651,39 +298,72 @@ _GLOBAL(abs)
_GLOBAL(_get_SP)
mr r3,r1 /* Close enough */
blr
-
-_GLOBAL(_get_SDR1)
- mfspr r3,SDR1
+
+_GLOBAL(_get_PVR)
+ mfspr r3,PVR
blr
-_GLOBAL(_get_SRx)
- mfsrin r3,r3
+_GLOBAL(cvt_fd)
+cvt_fd:
+ lfs 0,0(r3)
+ stfd 0,0(r4)
+ blr
+/*
+ * Fetch the current SR register
+ * get_SR(int index)
+ */
+_GLOBAL(get_SR)
+ mfsrin r4,r3
+ mr r3,r4
blr
-_GLOBAL(_get_PVR)
- mfspr r3,PVR
+
+_GLOBAL(cvt_df)
+cvt_df:
+ lfd 0,0(r3)
+ stfs 0,0(r4)
blr
/*
* Create a kernel thread
* __kernel_thread(flags, fn, arg)
*/
-#if 1
-#define SYS_CLONE 120
_GLOBAL(__kernel_thread)
-__kernel_thread:
- li r0,SYS_CLONE
+ li r0,__NR_clone
sc
cmpi 0,r3,0 /* parent or child? */
bnelr /* return if parent */
mtlr r4 /* fn addr in lr */
mr r3,r5 /* load arg and call fn */
- blr
- li 0, 1 /* exit after child exits */
- li 3, 0
+ blrl
+ li r0,__NR_exit /* exit after child exits */
+ li r3,0
sc
-#endif
-
+
+#define SYSCALL(name) \
+_GLOBAL(name) \
+ li r0,__NR_##name; \
+ sc; \
+ bnslr; \
+ lis r4,errno@ha; \
+ stw r3,errno@l(r4); \
+ li r3,-1; \
+ blr
+
+#define __NR__exit __NR_exit
+
+SYSCALL(idle)
+SYSCALL(setup)
+SYSCALL(sync)
+SYSCALL(setsid)
+SYSCALL(write)
+SYSCALL(dup)
+SYSCALL(execve)
+SYSCALL(open)
+SYSCALL(close)
+SYSCALL(waitpid)
+
+
/* Why isn't this a) automatic, b) written in 'C'? */
.data
.align 4
@@ -694,12 +374,12 @@ sys_call_table:
.long sys_fork
.long sys_read
.long sys_write
- .long sys_open /* 5 */
+ .long sys_open /* 5 */
.long sys_close
.long sys_waitpid
.long sys_creat
.long sys_link
- .long sys_unlink /* 10 */
+ .long sys_unlink /* 10 */
.long sys_execve
.long sys_chdir
.long sys_time
@@ -709,7 +389,7 @@ sys_call_table:
.long sys_break
.long sys_stat
.long sys_lseek
- .long sys_getpid /* 20 */
+ .long sys_getpid /* 20 */
.long sys_mount
.long sys_umount
.long sys_setuid
@@ -734,12 +414,12 @@ sys_call_table:
.long sys_pipe
.long sys_times
.long sys_prof
- .long sys_brk /* 45 */
+ .long sys_brk /* 45 */
.long sys_setgid
.long sys_getgid
.long sys_signal
.long sys_geteuid
- .long sys_getegid /* 50 */
+ .long sys_getegid /* 50 */
.long sys_acct
.long sys_phys
.long sys_lock
@@ -754,57 +434,57 @@ sys_call_table:
.long sys_ustat
.long sys_dup2
.long sys_getppid
- .long sys_getpgrp /* 65 */
+ .long sys_getpgrp /* 65 */
.long sys_setsid
.long sys_sigaction
.long sys_sgetmask
.long sys_ssetmask
- .long sys_setreuid /* 70 */
+ .long sys_setreuid /* 70 */
.long sys_setregid
.long sys_sigsuspend
.long sys_sigpending
.long sys_sethostname
- .long sys_setrlimit /* 75 */
+ .long sys_setrlimit /* 75 */
.long sys_getrlimit
.long sys_getrusage
.long sys_gettimeofday
.long sys_settimeofday
- .long sys_getgroups /* 80 */
+ .long sys_getgroups /* 80 */
.long sys_setgroups
- .long sys_select
+ .long ppc_select
.long sys_symlink
.long sys_lstat
- .long sys_readlink /* 85 */
+ .long sys_readlink /* 85 */
.long sys_uselib
.long sys_swapon
.long sys_reboot
.long old_readdir /* was sys_readdir */
- .long sys_mmap /* 90 */
+ .long sys_mmap /* 90 */
.long sys_munmap
.long sys_truncate
.long sys_ftruncate
.long sys_fchmod
- .long sys_fchown /* 95 */
+ .long sys_fchown /* 95 */
.long sys_getpriority
.long sys_setpriority
.long sys_profil
.long sys_statfs
- .long sys_fstatfs /* 100 */
+ .long sys_fstatfs /* 100 */
.long sys_ioperm
.long sys_socketcall
.long sys_syslog
.long sys_setitimer
- .long sys_getitimer /* 105 */
+ .long sys_getitimer /* 105 */
.long sys_newstat
.long sys_newlstat
.long sys_newfstat
.long sys_uname
- .long sys_iopl /* 110 */
+ .long sys_iopl /* 110 */
.long sys_vhangup
.long sys_idle
.long sys_vm86
.long sys_wait4
- .long sys_swapoff /* 115 */
+ .long sys_swapoff /* 115 */
.long sys_sysinfo
.long sys_ipc
.long sys_fsync
@@ -814,7 +494,7 @@ sys_call_table:
.long sys_newuname
.long sys_modify_ldt
.long sys_adjtimex
- .long sys_mprotect /* 125 */
+ .long sys_mprotect /* 125 */
.long sys_sigprocmask
.long sys_create_module
.long sys_init_module
@@ -829,9 +509,9 @@ sys_call_table:
.long 0 /* for afs_syscall */
.long sys_setfsuid
.long sys_setfsgid
- .long sys_llseek /* 140 */
+ .long sys_llseek /* 140 */
.long sys_getdents
- .long sys_newselect
+ .long ppc_select
.long sys_flock
.long sys_msync
.long sys_readv /* 145 */
@@ -844,7 +524,7 @@ sys_call_table:
.long sys_mlockall
.long sys_munlockall
.long sys_sched_setparam
- .long sys_sched_getparam /* 155 */
+ .long sys_sched_getparam /* 155 */
.long sys_sched_setscheduler
.long sys_sched_getscheduler
.long sys_sched_yield
@@ -853,8 +533,11 @@ sys_call_table:
.long sys_sched_rr_get_interval
.long sys_nanosleep
.long sys_mremap
- .long SYMBOL_NAME(sys_setresuid)
- .long SYMBOL_NAME(sys_getresuid)
- .long SYMBOL_NAME(sys_nfsservctl)
- .space (NR_syscalls-166)*4
+ .long sys_setresuid
+ .long sys_getresuid /* 165 */
+ .long sys_query_module
+ .long sys_poll
+ .long sys_nfsservctl
+ .long sys_debug
+ .space (NR_syscalls-170)*4
diff --git a/arch/ppc/kernel/mk_defs.c b/arch/ppc/kernel/mk_defs.c
index 5e6789a1d..3f404a37a 100644
--- a/arch/ppc/kernel/mk_defs.c
+++ b/arch/ppc/kernel/mk_defs.c
@@ -1,11 +1,14 @@
/*
* This program is used to generate definitions needed by
* assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
*/
-#define MK_DEFS
-#include <stdio.h>
-#include <linux/config.h>
+#include <stddef.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/head.h>
@@ -16,156 +19,114 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/processor.h>
-extern int errno;
+#define DEFINE(sym, val) \
+ asm volatile("\n#define\t" #sym "\t%0" : : "i" (val))
-main(int argc, char *argv[])
+void
+main(void)
{
- FILE *out;
- struct task_struct task;
- struct thread_struct tss;
- int i;
- char s[256];
- struct pt_regs regs;
- if (!(out = fopen(argv[1], "w")))
- {
- fprintf(stderr, "Can't create output file: %s\n", strerror(errno));
- exit(1);
- }
- fprintf(out, "/*\n");
- fprintf(out, " * WARNING! This file is automatically generated - DO NOT EDIT!\n");
- fprintf(out, " */\n");
- put_line(out, "STATE", (int)&task.state-(int)&task);
- put_line(out, "COUNTER", (int)&task.counter-(int)&task);
- put_line(out, "BLOCKED", (int)&task.blocked-(int)&task);
- put_line(out, "SIGNAL", (int)&task.signal-(int)&task);
- put_line(out, "KERNEL_STACK_PAGE", (int)&task.kernel_stack_page-(int)&task);
- put_line(out, "TSS", (int)&task.tss-(int)&task);
- put_line(out, "KSP", (int)&tss.ksp-(int)&tss);
- put_line(out, "LAST_PC", (int)&tss.last_pc-(int)&tss);
- put_line(out, "USER_STACK", (int)&tss.user_stack-(int)&tss);
- put_line(out, "PT_REGS", (int)&tss.regs-(int)&tss);
- put_line(out, "PF_TRACESYS", PF_TRACESYS);
- put_line(out, "TASK_FLAGS", (int)&task.flags-(int)&task);
- put_line(out, "MMU_SEG0", (int)&tss.segs[0]-(int)&tss);
- put_line(out, "MMU_SEG1", (int)&tss.segs[1]-(int)&tss);
- put_line(out, "MMU_SEG2", (int)&tss.segs[2]-(int)&tss);
- put_line(out, "MMU_SEG3", (int)&tss.segs[3]-(int)&tss);
- put_line(out, "MMU_SEG4", (int)&tss.segs[4]-(int)&tss);
- put_line(out, "MMU_SEG5", (int)&tss.segs[5]-(int)&tss);
- put_line(out, "MMU_SEG6", (int)&tss.segs[6]-(int)&tss);
- put_line(out, "MMU_SEG7", (int)&tss.segs[7]-(int)&tss);
- put_line(out, "MMU_SEG8", (int)&tss.segs[8]-(int)&tss);
- put_line(out, "MMU_SEG9", (int)&tss.segs[9]-(int)&tss);
- put_line(out, "MMU_SEG10", (int)&tss.segs[10]-(int)&tss);
- put_line(out, "MMU_SEG11", (int)&tss.segs[11]-(int)&tss);
- put_line(out, "MMU_SEG12", (int)&tss.segs[12]-(int)&tss);
- put_line(out, "MMU_SEG13", (int)&tss.segs[13]-(int)&tss);
- put_line(out, "MMU_SEG14", (int)&tss.segs[14]-(int)&tss);
- put_line(out, "MMU_SEG15", (int)&tss.segs[15]-(int)&tss);
- put_line(out, "TSS_EXPC", (int)&tss.expc-(int)&tss);
- put_line(out, "TSS_EXCOUNT", (int)&tss.excount-(int)&tss);
- put_line(out, "TSS_FPR0", (int)&tss.fpr[0]-(int)&tss);
- put_line(out, "TSS_FPR1", (int)&tss.fpr[1]-(int)&tss);
- put_line(out, "TSS_FPR2", (int)&tss.fpr[2]-(int)&tss);
- put_line(out, "TSS_FPR3", (int)&tss.fpr[3]-(int)&tss);
- put_line(out, "TSS_FPR4", (int)&tss.fpr[4]-(int)&tss);
- put_line(out, "TSS_FPR5", (int)&tss.fpr[5]-(int)&tss);
- put_line(out, "TSS_FPR6", (int)&tss.fpr[6]-(int)&tss);
- put_line(out, "TSS_FPR7", (int)&tss.fpr[7]-(int)&tss);
- put_line(out, "TSS_FPR8", (int)&tss.fpr[8]-(int)&tss);
- put_line(out, "TSS_FPR9", (int)&tss.fpr[9]-(int)&tss);
- put_line(out, "TSS_FPR10", (int)&tss.fpr[10]-(int)&tss);
- put_line(out, "TSS_FPR11", (int)&tss.fpr[11]-(int)&tss);
- put_line(out, "TSS_FPR12", (int)&tss.fpr[12]-(int)&tss);
- put_line(out, "TSS_FPR13", (int)&tss.fpr[13]-(int)&tss);
- put_line(out, "TSS_FPR14", (int)&tss.fpr[14]-(int)&tss);
- put_line(out, "TSS_FPR15", (int)&tss.fpr[15]-(int)&tss);
- put_line(out, "TSS_FPR16", (int)&tss.fpr[16]-(int)&tss);
- put_line(out, "TSS_FPR17", (int)&tss.fpr[17]-(int)&tss);
- put_line(out, "TSS_FPR18", (int)&tss.fpr[18]-(int)&tss);
- put_line(out, "TSS_FPR19", (int)&tss.fpr[19]-(int)&tss);
- put_line(out, "TSS_FPR20", (int)&tss.fpr[20]-(int)&tss);
- put_line(out, "TSS_FPR21", (int)&tss.fpr[21]-(int)&tss);
- put_line(out, "TSS_FPR22", (int)&tss.fpr[22]-(int)&tss);
- put_line(out, "TSS_FPR23", (int)&tss.fpr[23]-(int)&tss);
- put_line(out, "TSS_FPR24", (int)&tss.fpr[24]-(int)&tss);
- put_line(out, "TSS_FPR25", (int)&tss.fpr[25]-(int)&tss);
- put_line(out, "TSS_FPR26", (int)&tss.fpr[26]-(int)&tss);
- put_line(out, "TSS_FPR27", (int)&tss.fpr[27]-(int)&tss);
- put_line(out, "TSS_FPR28", (int)&tss.fpr[28]-(int)&tss);
- put_line(out, "TSS_FPR29", (int)&tss.fpr[29]-(int)&tss);
- put_line(out, "TSS_FPR30", (int)&tss.fpr[30]-(int)&tss);
- put_line(out, "TSS_FPR31", (int)&tss.fpr[31]-(int)&tss);
- put_line(out, "TSS_FP_USED", (int)&tss.fp_used-(int)&tss);
- /* Interrupt register frame */
- put_line(out, "INT_FRAME_SIZE", sizeof(regs));
- put_line(out, "GPR0", (int)&regs.gpr[0]-(int)&regs);
- put_line(out, "GPR1", (int)&regs.gpr[1]-(int)&regs);
- put_line(out, "GPR2", (int)&regs.gpr[2]-(int)&regs);
- put_line(out, "GPR3", (int)&regs.gpr[3]-(int)&regs);
- put_line(out, "GPR4", (int)&regs.gpr[4]-(int)&regs);
- put_line(out, "GPR5", (int)&regs.gpr[5]-(int)&regs);
- put_line(out, "GPR6", (int)&regs.gpr[6]-(int)&regs);
- put_line(out, "GPR7", (int)&regs.gpr[7]-(int)&regs);
- put_line(out, "GPR8", (int)&regs.gpr[8]-(int)&regs);
- put_line(out, "GPR9", (int)&regs.gpr[9]-(int)&regs);
- put_line(out, "GPR10", (int)&regs.gpr[10]-(int)&regs);
- put_line(out, "GPR11", (int)&regs.gpr[11]-(int)&regs);
- put_line(out, "GPR12", (int)&regs.gpr[12]-(int)&regs);
- put_line(out, "GPR13", (int)&regs.gpr[13]-(int)&regs);
- put_line(out, "GPR14", (int)&regs.gpr[14]-(int)&regs);
- put_line(out, "GPR15", (int)&regs.gpr[15]-(int)&regs);
- put_line(out, "GPR16", (int)&regs.gpr[16]-(int)&regs);
- put_line(out, "GPR17", (int)&regs.gpr[17]-(int)&regs);
- put_line(out, "GPR18", (int)&regs.gpr[18]-(int)&regs);
- put_line(out, "GPR19", (int)&regs.gpr[19]-(int)&regs);
- put_line(out, "GPR20", (int)&regs.gpr[20]-(int)&regs);
- put_line(out, "GPR21", (int)&regs.gpr[21]-(int)&regs);
- put_line(out, "GPR22", (int)&regs.gpr[22]-(int)&regs);
- put_line(out, "GPR23", (int)&regs.gpr[23]-(int)&regs);
- put_line(out, "GPR24", (int)&regs.gpr[24]-(int)&regs);
- put_line(out, "GPR25", (int)&regs.gpr[25]-(int)&regs);
- put_line(out, "GPR26", (int)&regs.gpr[26]-(int)&regs);
- put_line(out, "GPR27", (int)&regs.gpr[27]-(int)&regs);
- put_line(out, "GPR28", (int)&regs.gpr[28]-(int)&regs);
- put_line(out, "GPR29", (int)&regs.gpr[29]-(int)&regs);
- put_line(out, "GPR30", (int)&regs.gpr[30]-(int)&regs);
- put_line(out, "GPR31", (int)&regs.gpr[31]-(int)&regs);
-#if 0
- for ( i = 0 ; i <= 31 ; i++)
- {
- sprintf(s,"FPR%d",i);
- put_line(out, s, (int)&regs.fpr[i]-(int)&regs);
- }
+ /*DEFINE(KERNELBASE, KERNELBASE);*/
+ DEFINE(STATE, offsetof(struct task_struct, state));
+ DEFINE(NEXT_TASK, offsetof(struct task_struct, next_task));
+ DEFINE(COUNTER, offsetof(struct task_struct, counter));
+ DEFINE(BLOCKED, offsetof(struct task_struct, blocked));
+ DEFINE(SIGNAL, offsetof(struct task_struct, signal));
+ DEFINE(TSS, offsetof(struct task_struct, tss));
+ DEFINE(KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(PG_TABLES, offsetof(struct thread_struct, pg_tables));
+#ifdef CONFIG_PMAC
+ DEFINE(LAST_PC, offsetof(struct thread_struct, last_pc));
+ DEFINE(USER_STACK, offsetof(struct thread_struct, user_stack));
+#endif
+ DEFINE(LAST_SYSCALL, offsetof(struct thread_struct, last_syscall));
+ DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
+ DEFINE(PF_TRACESYS, PF_TRACESYS);
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TSS_FPR0, offsetof(struct thread_struct, fpr[0]));
+#if 0
+ DEFINE(TSS_FPR1, offsetof(struct thread_struct, fpr[1]));
+ DEFINE(TSS_FPR2, offsetof(struct thread_struct, fpr[2]));
+ DEFINE(TSS_FPR3, offsetof(struct thread_struct, fpr[3]));
+ DEFINE(TSS_FPR4, offsetof(struct thread_struct, fpr[4]));
+ DEFINE(TSS_FPR5, offsetof(struct thread_struct, fpr[5]));
+ DEFINE(TSS_FPR6, offsetof(struct thread_struct, fpr[6]));
+ DEFINE(TSS_FPR7, offsetof(struct thread_struct, fpr[7]));
+ DEFINE(TSS_FPR8, offsetof(struct thread_struct, fpr[8]));
+ DEFINE(TSS_FPR9, offsetof(struct thread_struct, fpr[9]));
+ DEFINE(TSS_FPR10, offsetof(struct thread_struct, fpr[10]));
+ DEFINE(TSS_FPR11, offsetof(struct thread_struct, fpr[11]));
+ DEFINE(TSS_FPR12, offsetof(struct thread_struct, fpr[12]));
+ DEFINE(TSS_FPR13, offsetof(struct thread_struct, fpr[13]));
+ DEFINE(TSS_FPR14, offsetof(struct thread_struct, fpr[14]));
+ DEFINE(TSS_FPR15, offsetof(struct thread_struct, fpr[15]));
+ DEFINE(TSS_FPR16, offsetof(struct thread_struct, fpr[16]));
+ DEFINE(TSS_FPR17, offsetof(struct thread_struct, fpr[17]));
+ DEFINE(TSS_FPR18, offsetof(struct thread_struct, fpr[18]));
+ DEFINE(TSS_FPR19, offsetof(struct thread_struct, fpr[19]));
+ DEFINE(TSS_FPR20, offsetof(struct thread_struct, fpr[20]));
+ DEFINE(TSS_FPR21, offsetof(struct thread_struct, fpr[21]));
+ DEFINE(TSS_FPR22, offsetof(struct thread_struct, fpr[22]));
+ DEFINE(TSS_FPR23, offsetof(struct thread_struct, fpr[23]));
+ DEFINE(TSS_FPR24, offsetof(struct thread_struct, fpr[24]));
+ DEFINE(TSS_FPR25, offsetof(struct thread_struct, fpr[25]));
+ DEFINE(TSS_FPR26, offsetof(struct thread_struct, fpr[26]));
+ DEFINE(TSS_FPR27, offsetof(struct thread_struct, fpr[27]));
+ DEFINE(TSS_FPR28, offsetof(struct thread_struct, fpr[28]));
+ DEFINE(TSS_FPR29, offsetof(struct thread_struct, fpr[29]));
+ DEFINE(TSS_FPR30, offsetof(struct thread_struct, fpr[30]));
+ DEFINE(TSS_FPR31, offsetof(struct thread_struct, fpr[31]));
#endif
- put_line(out, "FPCSR", (int)&regs.fpcsr-(int)&regs);
- /* Note: these symbols include "_" because they overlap with special register names */
- put_line(out, "_NIP", (int)&regs.nip-(int)&regs);
- put_line(out, "_MSR", (int)&regs.msr-(int)&regs);
- /* put_line(out, "_SRR1", (int)&regs.srr1-(int)&regs);
- put_line(out, "_SRR0", (int)&regs.srr0-(int)&regs); */
- put_line(out, "_CTR", (int)&regs.ctr-(int)&regs);
- put_line(out, "_LINK", (int)&regs.link-(int)&regs);
- put_line(out, "_CCR", (int)&regs.ccr-(int)&regs);
- put_line(out, "_XER", (int)&regs.xer-(int)&regs);
- put_line(out, "_DAR", (int)&regs.dar-(int)&regs);
- put_line(out, "_DSISR", (int)&regs.dsisr-(int)&regs);
- put_line(out, "_HASH1", (int)&regs.hash1-(int)&regs);
- put_line(out, "_HASH2", (int)&regs.hash2-(int)&regs);
- put_line(out, "_IMISS", (int)&regs.imiss-(int)&regs);
- put_line(out, "_DMISS", (int)&regs.dmiss-(int)&regs);
- put_line(out, "_ICMP", (int)&regs.icmp-(int)&regs);
- put_line(out, "_DCMP", (int)&regs.dcmp-(int)&regs);
- put_line(out, "ORIG_GPR3", (int)&regs.orig_gpr3-(int)&regs);
- put_line(out, "RESULT", (int)&regs.result-(int)&regs);
- put_line(out, "TRAP", (int)&regs.trap-(int)&regs);
- put_line(out, "MARKER", (int)&regs.marker-(int)&regs);
- exit(0);
-}
-
-put_line(FILE *out, char *name, int offset)
-{
- fprintf(out, "#define %s %d\n", name, offset);
+ DEFINE(TSS_FPSCR, offsetof(struct thread_struct, fpscr));
+ /* Interrupt register frame */
+ DEFINE(TASK_UNION_SIZE, sizeof(union task_union));
+ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD);
+ DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs));
+ DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
+ DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
+ DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2]));
+ DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3]));
+ DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4]));
+ DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5]));
+ DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6]));
+ DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7]));
+ DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8]));
+ DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9]));
+ DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10]));
+ DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11]));
+ DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12]));
+ DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13]));
+ DEFINE(GPR14, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[14]));
+ DEFINE(GPR15, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[15]));
+ DEFINE(GPR16, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[16]));
+ DEFINE(GPR17, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[17]));
+ DEFINE(GPR18, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[18]));
+ DEFINE(GPR19, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[19]));
+ DEFINE(GPR20, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[20]));
+ DEFINE(GPR21, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[21]));
+ DEFINE(GPR22, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[22]));
+ DEFINE(GPR23, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[23]));
+ DEFINE(GPR24, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[24]));
+ DEFINE(GPR25, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[25]));
+ DEFINE(GPR26, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[26]));
+ DEFINE(GPR27, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[27]));
+ DEFINE(GPR28, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[28]));
+ DEFINE(GPR29, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[29]));
+ DEFINE(GPR30, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[30]));
+ DEFINE(GPR31, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[31]));
+ /* Note: these symbols include _ because they overlap with special register names */
+ DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip));
+ DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr));
+ DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr));
+ DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link));
+ DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr));
+ DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer));
+ DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar));
+ DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr));
+ DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3));
+ DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
+ DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
}
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 74f796792..612a24bff 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -11,14 +11,18 @@
#include <linux/bios32.h>
#include <linux/pci.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+
/*
* PCI interrupt configuration. This is motherboard specific.
*/
-
-
/* Which PCI interrupt line does a given device [slot] use? */
/* Note: This really should be two dimensional based in slot/pin used */
unsigned char *Motherboard_map;
+unsigned char *Motherboard_map_name;
/* How is the 82378 PIRQ mapping setup? */
unsigned char *Motherboard_routes;
@@ -27,7 +31,7 @@ unsigned char *Motherboard_routes;
/* Motorola PowerStack */
static char Blackhawk_pci_IRQ_map[16] =
- {
+{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
0, /* Slot 2 - unused */
@@ -44,20 +48,20 @@ static char Blackhawk_pci_IRQ_map[16] =
0, /* Slot 13 - unused */
1, /* Slot 14 - Ethernet */
0, /* Slot 15 - unused */
- };
+};
static char Blackhawk_pci_IRQ_routes[] =
- {
+{
0, /* Line 0 - Unused */
9, /* Line 1 */
11, /* Line 2 */
14, /* Line 3 */
15 /* Line 4 */
- };
+};
/* Motorola MVME16xx */
static char Genesis_pci_IRQ_map[16] =
- {
+{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
0, /* Slot 2 - unused */
@@ -74,20 +78,20 @@ static char Genesis_pci_IRQ_map[16] =
0, /* Slot 13 - unused */
1, /* Slot 14 - Ethernet */
0, /* Slot 15 - unused */
- };
+};
static char Genesis_pci_IRQ_routes[] =
- {
+{
0, /* Line 0 - Unused */
10, /* Line 1 */
11, /* Line 2 */
14, /* Line 3 */
15 /* Line 4 */
- };
+};
/* Motorola Series-E */
static char Comet_pci_IRQ_map[16] =
- {
+{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
0, /* Slot 2 - unused */
@@ -104,20 +108,20 @@ static char Comet_pci_IRQ_map[16] =
0, /* Slot 13 - unused */
1, /* Slot 14 - Ethernet */
0, /* Slot 15 - unused */
- };
+};
static char Comet_pci_IRQ_routes[] =
- {
+{
0, /* Line 0 - Unused */
10, /* Line 1 */
11, /* Line 2 */
14, /* Line 3 */
15 /* Line 4 */
- };
+};
/* BeBox */
static char BeBox_pci_IRQ_map[16] =
- {
+{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
0, /* Slot 2 - unused */
@@ -134,20 +138,20 @@ static char BeBox_pci_IRQ_map[16] =
0, /* Slot 13 - unused */
0, /* Slot 14 - unused */
0, /* Slot 15 - unused */
- };
+};
static char BeBox_pci_IRQ_routes[] =
- {
+{
0, /* Line 0 - Unused */
9, /* Line 1 */
11, /* Line 2 */
14, /* Line 3 */
15 /* Line 4 */
- };
+};
/* IBM Nobis */
static char Nobis_pci_IRQ_map[16] =
- {
+{
0, /* Slot 0 - unused */
0, /* Slot 1 - unused */
0, /* Slot 2 - unused */
@@ -164,54 +168,83 @@ static char Nobis_pci_IRQ_map[16] =
0, /* Slot 13 - unused */
0, /* Slot 14 - unused */
0, /* Slot 15 - unused */
- };
+};
static char Nobis_pci_IRQ_routes[] =
- {
+{
0, /* Line 0 - Unused */
13, /* Line 1 */
13, /* Line 2 */
13, /* Line 3 */
13 /* Line 4 */
- };
+};
+
+
+/*
+ * ibm 830 (and 850?).
+ * This is actually based on the Carolina motherboard
+ * -- Cort
+ */
+static char ibm8xx_pci_IRQ_map[23] = {
+ 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 - FireCoral */
+ 4, /* Slot 12 - Ethernet PCIINTD# */
+ 2, /* Slot 13 - PCI Slot #2 */
+ 2, /* Slot 14 - S3 Video PCIINTD# */
+ 0, /* Slot 15 - onboard SCSI (INDI) [1] */
+ 3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
+ 0, /* Slot 17 - unused */
+ 2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+ 0, /* Slot 19 - unused */
+ 0, /* Slot 20 - unused */
+ 0, /* Slot 21 - unused */
+ 2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+static char ibm8xx_pci_IRQ_routes[] = {
+ 0, /* Line 0 - unused */
+ 13, /* Line 1 */
+ 10, /* Line 2 */
+ 15, /* Line 3 */
+ 15, /* Line 4 */
+};
+/* This just changes the PCI slots & onboard SCSI + S3 to IRQ10, but
+ * it really needs some logic to set them to unique IRQ's, or even
+ * add some logic to the drivers to ask an irq.c routine to re-map
+ * the IRQ if it needs one to itself...
+ */
+static char Carolina_PIRQ_routes[] = {
+ 0xad, /* INTB# = 10, INTA# = 13 */
+ 0xff /* INTD# = 15, INTC# = 15 */
+};
+/* We have to turn on LEVEL mode for changed IRQ's */
+/* All PCI IRQ's need to be level mode, so this should be something
+ * other than hard-coded as well... IRQ's are individually mappable
+ * to either edge or level.
+ */
+#define CAROLINA_IRQ_EDGE_MASK_LO 0x00 /* IRQ's 0-7 */
+#define CAROLINA_IRQ_EDGE_MASK_HI 0xA4 /* IRQ's 8-15 [10,13,15] */
+#define PCI_DEVICE_ID_IBM_CORAL 0x000a
-#define PCI_DEBUG
#undef PCI_DEBUG
#ifdef PCI_STATS
int PCI_conversions[2];
#endif
-unsigned long pcibios_init(unsigned long mem_start,
- unsigned long mem_end)
-{
- return mem_start;
-}
unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
{
- return mem_start;
-}
-
-
-unsigned long
-_LE_to_BE_long(unsigned long val)
-{
- unsigned char *p = (unsigned char *)&val;
-#ifdef PCI_STATS
- PCI_conversions[0]++;
-#endif
- return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | (p[0] << 0));
-}
-
-unsigned short
-_LE_to_BE_short(unsigned long val)
-{
- unsigned char *p = (unsigned char *)&val;
-#ifdef PCI_STATS
- PCI_conversions[1]++;
-#endif
- return ((p[3] << 8) | (p[2] << 0));
+ return mem_start;
}
int
@@ -225,7 +258,7 @@ pcibios_present (void)
int
pcibios_read_config_dword (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned int *val)
+ unsigned char dev, unsigned char offset, unsigned int *val)
{
unsigned long _val;
unsigned long *ptr;
@@ -243,7 +276,7 @@ pcibios_read_config_dword (unsigned char bus,
#ifdef PCI_DEBUG
printk("[%x] ", ptr);
#endif
- _val = _LE_to_BE_long(*ptr);
+ _val = le32_to_cpu(*ptr);
}
#ifdef PCI_DEBUG
printk("%x\n", _val);
@@ -254,27 +287,27 @@ pcibios_read_config_dword (unsigned char bus,
int
pcibios_read_config_word (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned short *val)
+ unsigned char dev, unsigned char offset, unsigned short *val)
{
unsigned short _val;
unsigned short *ptr;
dev >>= 3;
-#ifdef PCI_DEBUG
+#ifdef PCI_DEBUG
printk("PCI Read config word[%d.%d.%x] = ", bus, dev, offset);
#endif
if ((bus != 0) || (dev < 11) || (dev > 16))
{
- *val = 0xFFFFFFFF;
+ *val = (unsigned short)0xFFFFFFFF;
return PCIBIOS_DEVICE_NOT_FOUND;
} else
{
ptr = (unsigned short *)(0x80800000 | (1<<dev) | offset);
-#ifdef PCI_DEBUG
+#ifdef PCI_DEBUG
printk("[%x] ", ptr);
#endif
- _val = _LE_to_BE_short(*ptr);
+ _val = le16_to_cpu(*ptr);
}
-#ifdef PCI_DEBUG
+#ifdef PCI_DEBUG
printk("%x\n", _val);
#endif
*val = _val;
@@ -283,7 +316,7 @@ pcibios_read_config_word (unsigned char bus,
int
pcibios_read_config_byte (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned char *val)
+ unsigned char dev, unsigned char offset, unsigned char *val)
{
unsigned char _val;
volatile unsigned char *ptr;
@@ -294,6 +327,9 @@ pcibios_read_config_byte (unsigned char bus,
if (Motherboard_map[dev] <= 4)
{
*val = Motherboard_routes[Motherboard_map[dev]];
+ /*printk("dev %d map %d route %d\n",
+ dev,Motherboard_map[dev],
+ Motherboard_routes[Motherboard_map[dev]]);*/
} else
{ /* Pseudo interrupts [for BeBox] */
*val = Motherboard_map[dev];
@@ -327,12 +363,12 @@ pcibios_read_config_byte (unsigned char bus,
int
pcibios_write_config_dword (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned int val)
+ unsigned char dev, unsigned char offset, unsigned int val)
{
unsigned long _val;
unsigned long *ptr;
dev >>= 3;
- _val = _LE_to_BE_long(val);
+ _val = le32_to_cpu(val);
#ifdef PCI_DEBUG
printk("PCI Write config dword[%d.%d.%x] = %x\n", bus, dev, offset, _val);
#endif
@@ -349,12 +385,12 @@ pcibios_write_config_dword (unsigned char bus,
int
pcibios_write_config_word (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned short val)
+ unsigned char dev, unsigned char offset, unsigned short val)
{
unsigned short _val;
unsigned short *ptr;
dev >>= 3;
- _val = _LE_to_BE_short(val);
+ _val = le16_to_cpu(val);
#ifdef PCI_DEBUG
printk("PCI Write config word[%d.%d.%x] = %x\n", bus, dev, offset, _val);
#endif
@@ -371,7 +407,7 @@ pcibios_write_config_word (unsigned char bus,
int
pcibios_write_config_byte (unsigned char bus,
- unsigned char dev, unsigned char offset, unsigned char val)
+ unsigned char dev, unsigned char offset, unsigned char val)
{
unsigned char _val;
unsigned char *ptr;
@@ -420,7 +456,7 @@ pcibios_find_device (unsigned short vendor, unsigned short device_id,
int
pcibios_find_class (unsigned int class_code, unsigned short index,
- unsigned char *bus, unsigned char *dev)
+ unsigned char *bus, unsigned char *dev)
{
int dev_nr, class, indx;
indx = 0;
@@ -437,7 +473,7 @@ pcibios_find_class (unsigned int class_code, unsigned short index,
*bus = 0;
*dev = dev_nr<<3;
#ifdef PCI_DEBUG
- printk(" - device: %x\n", dev_nr);
+ printk(" - device: %x\n", dev_nr);
#endif
return (0);
}
@@ -455,22 +491,22 @@ const char *pcibios_strerror(int error)
static char buf[32];
switch (error)
{ case PCIBIOS_SUCCESSFUL:
- return ("PCI BIOS: no error");
- case PCIBIOS_FUNC_NOT_SUPPORTED:
- return ("PCI BIOS: function not supported");
- case PCIBIOS_BAD_VENDOR_ID:
- return ("PCI BIOS: bad vendor ID");
- case PCIBIOS_DEVICE_NOT_FOUND:
- return ("PCI BIOS: device not found");
- case PCIBIOS_BAD_REGISTER_NUMBER:
- return ("PCI BIOS: bad register number");
- case PCIBIOS_SET_FAILED:
- return ("PCI BIOS: set failed");
- case PCIBIOS_BUFFER_TOO_SMALL:
- return ("PCI BIOS: buffer too small");
- default:
- sprintf(buf, "PCI BIOS: invalid error #%d", error);
- return(buf);
+ return ("PCI BIOS: no error");
+ case PCIBIOS_FUNC_NOT_SUPPORTED:
+ return ("PCI BIOS: function not supported");
+ case PCIBIOS_BAD_VENDOR_ID:
+ return ("PCI BIOS: bad vendor ID");
+ case PCIBIOS_DEVICE_NOT_FOUND:
+ return ("PCI BIOS: device not found");
+ case PCIBIOS_BAD_REGISTER_NUMBER:
+ return ("PCI BIOS: bad register number");
+ case PCIBIOS_SET_FAILED:
+ return ("PCI BIOS: set failed");
+ case PCIBIOS_BUFFER_TOO_SMALL:
+ return ("PCI BIOS: buffer too small");
+ default:
+ sprintf(buf, "PCI BIOS: invalid error #%d", error);
+ return(buf);
}
}
@@ -478,42 +514,112 @@ const char *pcibios_strerror(int error)
* Note: This routine has to access the PCI configuration space
* for the PCI bridge chip (Intel 82378).
*/
-
-void route_PCI_interrupts(void)
+unsigned long pcibios_init(unsigned long mem_start,unsigned long mem_end)
+{
+ return mem_start;
+}
+
+unsigned long route_pci_interrupts(void)
{
unsigned char *ibc_pirq = (unsigned char *)0x80800860;
unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
extern unsigned long isBeBox[];
int i;
- /* Decide which motherboard this is & how the PCI interrupts are routed */
- if (isBeBox[0])
- {
- Motherboard_map = BeBox_pci_IRQ_map;
- Motherboard_routes = BeBox_pci_IRQ_routes;
- } else
- if ((_get_PVR()>>16) == 1)
- { /* Nobis */
- Motherboard_map = Nobis_pci_IRQ_map;
- Motherboard_routes = Nobis_pci_IRQ_routes;
- } else
- { /* Motorola hardware */
+
+ if ( _machine == _MACH_Motorola)
+ {
switch (inb(0x800) & 0xF0)
{
- case 0x10: /* MVME16xx */
- Motherboard_map = Genesis_pci_IRQ_map;
- Motherboard_routes = Genesis_pci_IRQ_routes;
- break;
- case 0x20: /* Series E */
- Motherboard_map = Comet_pci_IRQ_map;
- Motherboard_routes = Comet_pci_IRQ_routes;
- break;
- case 0x40: /* PowerStack */
- default: /* Can't hurt, can it? */
- Motherboard_map = Blackhawk_pci_IRQ_map;
- Motherboard_routes = Blackhawk_pci_IRQ_routes;
- break;
+ case 0x10: /* MVME16xx */
+ Motherboard_map_name = "Genesis";
+ Motherboard_map = Genesis_pci_IRQ_map;
+ Motherboard_routes = Genesis_pci_IRQ_routes;
+ break;
+ case 0x20: /* Series E */
+ Motherboard_map_name = "Series E";
+ Motherboard_map = Comet_pci_IRQ_map;
+ Motherboard_routes = Comet_pci_IRQ_routes;
+ break;
+ case 0x40: /* PowerStack */
+ default: /* Can't hurt, can it? */
+ Motherboard_map_name = "Blackhawk (Powerstack)";
+ Motherboard_map = Blackhawk_pci_IRQ_map;
+ Motherboard_routes = Blackhawk_pci_IRQ_routes;
+ break;
+ }
+ } else
+ {
+ if ( _machine == _MACH_IBM )
+ {
+ unsigned char pl_id;
+ unsigned long flags;
+ unsigned index;
+ unsigned char fn, bus;
+ unsigned int addr;
+ unsigned char dma_mode, ide_mode;
+ int i;
+
+ Motherboard_map_name = "IBM 8xx (Carolina)";
+ Motherboard_map = ibm8xx_pci_IRQ_map;
+ Motherboard_routes = ibm8xx_pci_IRQ_routes;
+ll_printk("before loop\n");
+
+ for (index = 0;
+ !pcibios_find_device (PCI_VENDOR_ID_IBM,
+ PCI_DEVICE_ID_IBM_CORAL,
+ index, &bus, &fn); ++index)
+ {
+ pcibios_read_config_dword(bus, fn, 0x10, &addr);
+ addr &= ~0x3;
+ outb(0x26, addr);
+ dma_mode = inb(addr+4);
+ outb(0x25, addr);
+ ide_mode = inb(addr+4);
+ /*printk("CORAL I/O at 0x%x, DMA mode: %x, IDE mode: %x",
+ addr, dma_mode, ide_mode);*/
+ /* Make CDROM non-DMA */
+ ide_mode = (ide_mode & 0x0F) | 0x20;
+ outb(0x25, addr);
+ outb(ide_mode, addr+4);
+ dma_mode = dma_mode & ~0x80;
+ outb(0x26, addr);
+ outb(dma_mode, addr+4);
+ outb(0x26, addr);
+ dma_mode = inb(addr+4);
+ outb(0x25, addr);
+ ide_mode = inb(addr+4);
+ /*printk("=> DMA mode: %x, IDE mode: %x\n",
+ dma_mode, ide_mode);*/
+ }
+
+ /* Setup the PCI INT mappings for the Carolina */
+ /* These are PCI Interrupt Route Control [1|2] Register */
+ outb(Carolina_PIRQ_routes[0], 0x0890);
+ outb(Carolina_PIRQ_routes[1], 0x0891);
+
+ pl_id=inb(0x0852);
+ /*printk("CPU Planar ID is %#0x\n", pl_id);*/
+
+ if (pl_id == 0x0C) {
+ /* INDI */
+ Motherboard_map[12] = 1;
+ }
+ll_printk("before edge/level\n");
+#if 0
+ /*printk("Changing IRQ mode\n");*/
+ pl_id=inb(0x04d0);
+ /*printk("Low mask is %#0x\n", pl_id);*/
+ outb(pl_id|CAROLINA_IRQ_EDGE_MASK_LO, 0x04d0);
+
+ pl_id=inb(0x04d1);
+ /*printk("Hi mask is %#0x\n", pl_id);*/
+ outb(pl_id|CAROLINA_IRQ_EDGE_MASK_HI, 0x04d1);
+ pl_id=inb(0x04d1);
+ /*printk("Hi mask now %#0x\n", pl_id);*/
+#endif
}
}
+
/* Set up mapping from slots */
for (i = 1; i <= 4; i++)
{
@@ -521,4 +627,4 @@ void route_PCI_interrupts(void)
}
/* Enable PCI interrupts */
*ibc_pcicon |= 0x20;
-}
+}
diff --git a/arch/ppc/kernel/port_io.c b/arch/ppc/kernel/port_io.c
index e886705e1..cc8626a3a 100644
--- a/arch/ppc/kernel/port_io.c
+++ b/arch/ppc/kernel/port_io.c
@@ -1,149 +1,146 @@
/*
* I/O 'port' access routines
*/
+#include <asm/byteorder.h>
+#include <asm/io.h>
-/* This is really only correct for the MVME16xx (PreP)? */
+#define inb_asm(port) {( \
+ unsigned char ret; \
+ asm ( "lbz %0,0(%1)\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n" : "=r" (ret) : "r" (port+_IO_BASE)); \
+ return ret; \
+})
-#define _IO_BASE ((unsigned long)0x80000000)
-
-unsigned char
+inline unsigned char
inb(int port)
{
- return (*((unsigned char *)(_IO_BASE+port)));
+ unsigned char ret;
+ asm("/*inb*/\n");
+ asm ( "lbz %0,0(%1)" : "=r" (ret) : "r" (port+_IO_BASE));
+ return ret;
}
-unsigned short
+inline unsigned short
inw(int port)
{
- return (_LE_to_BE_short(*((unsigned short *)(_IO_BASE+port))));
+ unsigned short ret;
+ asm("/*inw*/\n");
+ asm ( "lhbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0));
+ return ret;
}
-unsigned long
+inline unsigned long
inl(int port)
{
- return (_LE_to_BE_long(*((unsigned long *)(_IO_BASE+port))));
+ unsigned long ret;
+ asm("/*inl*/\n");
+ asm ( "lwbrx %0,%1,%2" : "=r" (ret) : "r" (port+_IO_BASE), "r" (0));
+ return ret;
}
-void insb(int port, char *ptr, int len)
+inline unsigned char
+outb(unsigned char val,int port)
{
- unsigned char *io_ptr = (unsigned char *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *ptr++ = *io_ptr;
- }
+ asm("/*outb*/\n");
+ asm ( "stb %0,0(%1)" :: "r" (val), "r" (port+_IO_BASE));
+ return (val);
}
-#if 0
-void insw(int port, short *ptr, int len)
-{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *ptr++ = _LE_to_BE_short(*io_ptr);
- }
-}
-#else
-void insw(int port, short *ptr, int len)
+inline unsigned short
+outw(unsigned short val,int port)
{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- _insw(io_ptr, ptr, len);
+ asm("/*outw*/\n");
+ asm ( "sthbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0));
+ return (val);
}
-#endif
-void insw_unswapped(int port, short *ptr, int len)
+inline unsigned long
+outl(unsigned long val,int port)
{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *ptr++ = *io_ptr;
- }
+ asm("/*outl*/\n");
+ asm ( "stwbrx %0,%1,%2" :: "r" (val), "r" (port+_IO_BASE), "r" (0));
+ return (val);
}
-void insl(int port, long *ptr, int len)
+void insb(int port, char *ptr, int len)
{
- unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *ptr++ = _LE_to_BE_long(*io_ptr);
- }
+ memcpy( (void *)ptr, (void *)(port+_IO_BASE), len);
}
-unsigned char inb_p(int port) {return (inb(port)); }
-unsigned short inw_p(int port) {return (inw(port)); }
-unsigned long inl_p(int port) {return (inl(port)); }
-
-unsigned char
-outb(unsigned char val,int port)
+void insw(int port, short *ptr, int len)
{
- *((unsigned char *)(_IO_BASE+port)) = (val);
- return (val);
+ asm ("mtctr %2 \n\t"
+ "subi %1,%1,2 \n\t"
+ "00:\n\t"
+ "lhbrx %2,0,%0 \n\t"
+ "sthu %2,2(%1) \n\t"
+ "bdnz 00b \n\t"
+ :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
}
-unsigned short
-outw(unsigned short val,int port)
+void insw_unswapped(int port, short *ptr, int len)
{
- *((unsigned short *)(_IO_BASE+port)) = _LE_to_BE_short(val);
- return (val);
+ memcpy( (void *)ptr, (void *)(port+_IO_BASE), (len*sizeof(short)) );
}
-unsigned long
-outl(unsigned long val,int port)
+void insl(int port, long *ptr, int len)
{
- *((unsigned long *)(_IO_BASE+port)) = _LE_to_BE_long(val);
- return (val);
+ asm ("mtctr %2 \n\t"
+ "subi %1,%1,4 \n\t"
+ "00:\n\t"
+ "lhbrx %2,0,%0 \n\t"
+ "sthu %2,4(%1) \n\t"
+ "bdnz 00b \n\t"
+ :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
}
void outsb(int port, char *ptr, int len)
{
- unsigned char *io_ptr = (unsigned char *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *io_ptr = *ptr++;
- }
+ memcpy( (void *)ptr, (void *)(port+_IO_BASE), len );
}
-#if 0
void outsw(int port, short *ptr, int len)
{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *io_ptr = _LE_to_BE_short(*ptr++);
- }
+ asm ("mtctr %2\n\t"
+ "subi %1,%1,2\n\t"
+ "00:lhzu %2,2(%1)\n\t"
+ "sthbrx %2,0,%0\n\t"
+ "bdnz 00b\n\t"
+ :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
}
-#else
-void outsw(int port, short *ptr, int len)
-{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- _outsw(io_ptr, ptr, len);
-}
-#endif
void outsw_unswapped(int port, short *ptr, int len)
{
- unsigned short *io_ptr = (unsigned short *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *io_ptr = *ptr++;
- }
+ memcpy( (void *)ptr, (void *)(port+_IO_BASE), len*sizeof(short) );
}
void outsl(int port, long *ptr, int len)
{
- unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
- while (len-- > 0)
- {
- *io_ptr = _LE_to_BE_long(*ptr++);
- }
+ asm ("mtctr %2\n\t"
+ "subi %1,%1,4\n\t"
+ "00:lwzu %2,4(%1)\n\t"
+ "sthbrx %2,0,%0\n\t"
+ "bdnz 00b\n\t"
+ :: "r" (port+_IO_BASE), "r" (ptr), "r" (len));
}
-unsigned char outb_p(unsigned char val,int port) { return (outb(val,port)); }
-unsigned short outw_p(unsigned short val,int port) { return (outw(val,port)); }
-unsigned long outl_p(unsigned long val,int port) { return (outl(val,port)); }
-
+void insl_unswapped(int port, long *ptr, int len)
+{
+ unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ while (len-- > 0)
+ {
+ *ptr++ = (*io_ptr);
+ }
+}
-/* makes writing to the ibm acorn power management stuff easier -- Cort */
-/* args in forn of PA.B as in tech spec for ibm carolina */
-void ibm_write(unsigned char val,unsigned int port)
+void outsl_unswapped(int port, long *ptr, int len)
{
+ unsigned long *io_ptr = (unsigned long *)(_IO_BASE+port);
+ /* Ensure I/O operations complete */
+ __asm__ volatile("eieio");
+ while (len-- > 0)
+ {
+ *io_ptr = (*ptr++);
+ }
}
diff --git a/arch/ppc/kernel/ppc_asm.tmpl b/arch/ppc/kernel/ppc_asm.tmpl
index 5d357be22..e31dea266 100644
--- a/arch/ppc/kernel/ppc_asm.tmpl
+++ b/arch/ppc/kernel/ppc_asm.tmpl
@@ -2,19 +2,10 @@
* This file contains all the macros and symbols which define
* a PowerPC assembly language environment.
*/
-
+#include <linux/config.h>
#define _TEXT()\
.text
-#if 0 /* Old way */
-#define _EXTERN(n) .##n
-
-#define _GLOBAL(n)\
- .globl n;\
-n: .long _EXTERN(n);\
- .globl _EXTERN(n);\
-_EXTERN(n):
-#else
#define _EXTERN(n) n
#define SYMBOL_NAME(x) x
@@ -22,7 +13,6 @@ _EXTERN(n):
#define _GLOBAL(n)\
.globl n;\
n:
-#endif
#ifndef FALSE
#define FALSE 0
@@ -136,9 +126,13 @@ n:
#define SDR1 25 /* MMU hash base register */
#define DAR 19 /* Data Address Register */
#define SPR0 272 /* Supervisor Private Registers */
+#define SPRG0 272
#define SPR1 273
+#define SPRG1 273
#define SPR2 274
+#define SPRG2 274
#define SPR3 275
+#define SPRG3 275
#define DSISR 18
#define SRR0 26 /* Saved Registers (exception) */
#define SRR1 27
@@ -164,7 +158,36 @@ n:
#define SR14 14
#define SR15 15
+#define curptr r2
+
+/*
+ * Macros for storing registers into and loading registers from
+ * exception frames.
+ */
+#define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base)
+#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
+#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
+#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
+#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
+#define REST_GPR(n, base) lwz n,GPR0+4*(n)(base)
+#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
+#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
+#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
+#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
+
+#define SAVE_FPR(n, base) stfd n,TSS_FPR0+8*(n)(base)
+#define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base)
+#define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
+#define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
+#define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
+#define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
+#define REST_FPR(n, base) lfd n,TSS_FPR0+8*(n)(base)
+#define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base)
+#define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base)
+#define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base)
+#define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
+#define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
+
/* Missing instructions */
#define bdne bc 0,2,
-#include "asm/ppc_machine.h"
diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
index ee21c5cbe..f24872063 100644
--- a/arch/ppc/kernel/process.c
+++ b/arch/ppc/kernel/process.c
@@ -1,13 +1,20 @@
/*
* linux/arch/ppc/kernel/process.c
*
- * Copyright (C) 1995 Linus Torvalds
- * Adapted for PowerPC by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/i386/kernel/process.c"
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu) and
+ * 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/errno.h>
@@ -22,173 +29,449 @@
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/config.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
+#include <asm/smp_lock.h>
-#include <asm/ppc_machine.h>
+int dump_fpu(void);
+void switch_to(struct task_struct *, struct task_struct *);
+void print_backtrace(unsigned long *);
+void show_regs(struct pt_regs * regs);
+void inline zero_paged(void);
+extern unsigned long _get_SP(void);
-/*
- * Initial task structure. Make this a per-architecture thing,
- * because different architectures tend to have different
- * alignment requirements and potentially different initial
- * setup.
- */
-static unsigned long init_kernel_stack[1024] = { STACK_MAGIC, };
-unsigned long init_user_stack[1024] = { STACK_MAGIC, };
+#undef SHOW_TASK_SWITCHES 1
+#undef CHECK_STACK 1
+#undef IDLE_ZERO 1
+
+unsigned long
+kernel_stack_top(struct task_struct *tsk)
+{
+ return ((unsigned long)tsk) + sizeof(union task_union);
+}
+
+unsigned long
+task_top(struct task_struct *tsk)
+{
+ return ((unsigned long)tsk) + sizeof(struct task_struct);
+}
+
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
-struct task_struct init_task = INIT_TASK;
-
-
-int dump_fpu(void);
-void hard_reset_now(void);
-void switch_to(struct task_struct *, struct task_struct *);
-void copy_thread(int,unsigned long,unsigned long,struct task_struct *,
- struct pt_regs *);
-void print_backtrace(unsigned long *);
+union task_union init_task_union = { INIT_TASK };
int
dump_fpu(void)
{
- return (1);
+ return (1);
}
-
/* check to make sure the kernel stack is healthy */
int check_stack(struct task_struct *tsk)
{
- extern unsigned long init_kernel_stack[PAGE_SIZE/sizeof(long)];
- int ret = 0;
- int i;
-
- /* skip check in init_kernel_task -- swapper */
- if ( tsk->kernel_stack_page == (unsigned long)&init_kernel_stack )
- return;
- /* check bounds on stack -- above/below kstack page */
- if ( (tsk->tss.ksp-1 & KERNEL_STACK_MASK) != tsk->kernel_stack_page )
- {
- printk("check_stack(): not in bounds %s/%d ksp %x/%x\n",
- tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page);
- ret |= 1;
- }
-
- /* check for magic on kstack */
- if ( *(unsigned long *)(tsk->kernel_stack_page) != STACK_MAGIC)
- {
- printk("check_stack(): no magic %s/%d ksp %x/%x magic %x\n",
- tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page,
- *(unsigned long *)(tsk->kernel_stack_page));
- ret |= 2;
- }
-
-#ifdef KERNEL_STACK_BUFFER
- /* check extra padding page under kernel stack */
- for ( i = PAGE_SIZE/sizeof(long) ; i >= 1; i--)
- {
- struct pt_regs *regs;
-
- if ( *((unsigned long *)(tsk->kernel_stack_page)-1) )
- {
- printk("check_stack(): padding touched %s/%d ksp %x/%x value %x/%d\n",
- tsk->comm,tsk->pid,tsk->tss.ksp,tsk->kernel_stack_page,
- *(unsigned long *)(tsk->kernel_stack_page-i),i*sizeof(long));
- regs = (struct pt_regs *)(tsk->kernel_stack_page-(i*sizeof(long)));
- printk("marker %x trap %x\n", regs->marker,regs->trap);
- print_backtrace((unsigned long *)(tsk->tss.ksp));
-
- ret |= 4;
- break;
- }
- }
+ unsigned long stack_top = kernel_stack_top(tsk);
+ unsigned long tsk_top = task_top(tsk);
+ int ret = 0;
+ unsigned long *i;
+
+#if 0
+ /* check tss magic */
+ if ( tsk->tss.magic != TSS_MAGIC )
+ {
+ ret |= 1;
+ printk("tss.magic bad: %08x\n", tsk->tss.magic);
+ }
#endif
-
-#if 0
- if (ret)
- panic("bad stack");
+
+ if ( !tsk )
+ printk("check_stack(): tsk bad tsk %p\n",tsk);
+
+ /* check if stored ksp is bad */
+ if ( (tsk->tss.ksp > stack_top) || (tsk->tss.ksp < tsk_top) )
+ {
+ printk("stack out of bounds: %s/%d\n"
+ " tsk_top %08x ksp %08x stack_top %08x\n",
+ tsk->comm,tsk->pid,
+ tsk_top, tsk->tss.ksp, stack_top);
+ ret |= 2;
+ }
+
+ /* check if stack ptr RIGHT NOW is bad */
+ if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) )
+ {
+ printk("current stack ptr out of bounds: %s/%d\n"
+ " tsk_top %08x sp %08x stack_top %08x\n",
+ current->comm,current->pid,
+ tsk_top, _get_SP(), stack_top);
+ ret |= 4;
+ }
+
+#if 0
+ /* check amount of free stack */
+ for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ )
+ {
+ if ( !i )
+ printk("check_stack(): i = %p\n", i);
+ if ( *i != 0 )
+ {
+ /* only notify if it's less than 900 bytes */
+ if ( (i - (unsigned long *)task_top(tsk)) < 900 )
+ printk("%d bytes free on stack\n",
+ i - task_top(tsk));
+ break;
+ }
+ }
#endif
- return(ret);
-}
+ if (ret)
+ {
+ panic("bad kernel stack");
+ }
+ return(ret);
+}
void
switch_to(struct task_struct *prev, struct task_struct *new)
{
- struct pt_regs *regs;
struct thread_struct *new_tss, *old_tss;
int s = _disable_interrupts();
- regs = (struct pt_regs *)(new->tss.ksp);
-#if 1
+ struct pt_regs *regs = (struct pt_regs *)(new->tss.ksp+STACK_FRAME_OVERHEAD);
+
+#if CHECK_STACK
check_stack(prev);
check_stack(new);
#endif
- /* if a process has used fp 15 times, then turn
- on the fpu for good otherwise turn it on with the fp
- exception handler as needed.
- skip this for kernel tasks.
- -- Cort */
- if ( (regs->msr & MSR_FP)&&(regs->msr & MSR_PR)&&(new->tss.fp_used < 15) )
- {
-#if 0
- printk("turning off fpu: %s/%d fp_used %d\n",
- new->comm,new->pid,new->tss.fp_used);
-#endif
- regs->msr = regs->msr & ~MSR_FP;
- }
-#if 0
- printk("%s/%d -> %s/%d\n",prev->comm,prev->pid,new->comm,new->pid);
+ /* turn off fpu for task last to run */
+ /*prev->tss.regs->msr &= ~MSR_FP;*/
+
+#ifdef SHOW_TASK_SWITCHES
+ printk("%s/%d (%x) -> %s/%d (%x) ctx %x\n",
+ prev->comm,prev->pid,prev->tss.regs->nip,
+ new->comm,new->pid,new->tss.regs->nip,new->mm->context);
#endif
new_tss = &new->tss;
old_tss = &current->tss;
- current_set[0] = new;
- _switch(old_tss, new_tss);
+ _switch(old_tss, new_tss, new->mm->context);
+ /* turn off fpu for task last to run */
_enable_interrupts(s);
}
+
+#include <linux/mc146818rtc.h>
+asmlinkage int sys_debug(long a, long b, long c, long d, long e, long f,struct pt_regs *regs)
+{
+#if 1
+ struct task_struct *p;
+ printk("sys_debug(): r3 %x r4 %x r5 %x r6 %x\n", a,b,c,d);
+ printk("last %x\n", last_task_used_math);
+ printk("cur %x regs %x/%x tss %x/%x\n",
+ current, current->tss.regs,regs,&current->tss,current->tss);
+ for_each_task(p)
+ {
+ if ((long)p < KERNELBASE)
+ {
+ printk("nip %x lr %x r3 %x\n", regs->nip,regs->link,a);
+ print_mm_info();
+ __cli();
+ while(1);
+ }
+ }
+ return regs->gpr[3];
+#endif
+#if 0
+ /* set the time in the cmos clock */
+ unsigned long hwtime, nowtime;
+ struct rtc_time tm;
+
+ hwtime = get_cmos_time();
+ to_tm(hwtime, &tm);
+ printk("hw: H:M:S M/D/Y %02d:%02d:%02d %d/%d/%d\n",
+ tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_mon,
+ tm.tm_mday, tm.tm_year);
+ return;
+#endif
+}
-asmlinkage int sys_debug(unsigned long r3)
+/*
+ * vars for idle task zero'ing out pages
+ */
+unsigned long zero_list = 0; /* head linked list of pre-zero'd pages */
+unsigned long bytecount = 0; /* pointer into the currently being zero'd page */
+unsigned long zerocount = 0; /* # currently pre-zero'd pages */
+unsigned long zerototal = 0; /* # pages zero'd over time -- for ooh's and ahhh's */
+unsigned long pageptr = 0; /* current page being zero'd */
+unsigned long zeropage_hits = 0;/* # zero'd pages request that we've done */
+
+/*
+ * Returns a pre-zero'd page from the list otherwise returns
+ * NULL.
+ */
+unsigned long get_prezerod_page(void)
{
- lock_kernel();
- if (!strcmp(current->comm,"crashme"))
- printk("sys_debug(): r3 (syscall) %d\n", r3);
- unlock_kernel();
+ unsigned long page;
+ unsigned long s;
+
+ if ( zero_list )
+ {
+ /* atomically remove this page from the list */
+ asm ( "101:lwarx %1,0,%2\n" /* reserve zero_list */
+ " lwz %0,0(%1)\n" /* get next -- new zero_list */
+ " stwcx. %0,0,%2\n" /* update zero_list */
+ " bne- 101b\n" /* if lost reservation try again */
+ : "=&r" (zero_list), "=&r" (page)
+ : "r" (&zero_list)
+ : "cc" );
+ /* we can update zerocount after the fact since it is not
+ * used for anything but control of a loop which doesn't
+ * matter since it won't effect anything if it zero's one
+ * less page -- Cort
+ */
+ atomic_inc((atomic_t *)&zeropage_hits);
+ atomic_dec((atomic_t *)&zerocount);
+ /* zero out the pointer to next in the page */
+ *(unsigned long *)page = 0;
+ return page;
+ }
return 0;
}
+/*
+ * Experimental stuff to zero out pages in the idle task
+ * to speed up get_free_pages() -- Cort
+ * Zero's out pages until we need to resched or
+ * we've reached the limit of zero'd pages.
+ */
+void inline zero_paged(void)
+{
+ extern pte_t *get_pte( struct mm_struct *mm, unsigned long address );
+ unsigned long tmp;
+ pte_t ptep;
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ sprintf(current->comm, "zero_paged");
+ printk("Started zero_paged\n");
+ /* want priority over idle task and powerd */
+ current->priority = -98;
+ current->counter = -98;
+ __sti();
+
+ while ( zerocount < 128 )
+ {
+ /*
+ * Mark a page as reserved so we can mess with it
+ * If we're interrupted we keep this page and our place in it
+ * since we validly hold it and it's reserved for us.
+ */
+ pageptr = __get_free_pages(GFP_ATOMIC, 0, 0 );
+ if ( !pageptr )
+ {
+ printk("!pageptr in zero_paged\n");
+ goto retry;
+ }
+
+ if ( need_resched )
+ schedule();
+
+ /*
+ * Make the page no cache so we don't blow our cache with 0's
+ */
+ dir = pgd_offset( init_task.mm, pageptr );
+ if (dir)
+ {
+ pmd = pmd_offset(dir, pageptr & PAGE_MASK);
+ if (pmd && pmd_present(*pmd))
+ {
+ pte = pte_offset(pmd, pageptr & PAGE_MASK);
+ if (pte && pte_present(*pte))
+ {
+ pte_uncache(*pte);
+ flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr);
+ }
+ }
+ }
+
+ /*
+ * Important here to not take time away from real processes.
+ */
+ for ( bytecount = 0; bytecount < PAGE_SIZE ; bytecount += 4 )
+ {
+ if ( need_resched )
+ schedule();
+ *(unsigned long *)(bytecount + pageptr) = 0;
+ }
+
+ /*
+ * If we finished zero-ing out a page add this page to
+ * the zero_list atomically -- we can't use
+ * down/up since we can't sleep in idle.
+ * Disabling interrupts is also a bad idea since we would
+ * steal time away from real processes.
+ * We can also have several zero_paged's running
+ * on different processors so we can't interfere with them.
+ * So we update the list atomically without locking it.
+ * -- Cort
+ */
+ /* turn cache on for this page */
+ pte_cache(*pte);
+ flush_tlb_page(find_vma(init_task.mm,pageptr),pageptr);
+
+ /* atomically add this page to the list */
+ asm ( "101:lwarx %0,0,%1\n" /* reserve zero_list */
+ " stw %0,0(%2)\n" /* update *pageptr */
+#ifdef __SMP__
+ " sync\n" /* let store settle */
+#endif
+ " mr %0,%2\n" /* update zero_list in reg */
+ " stwcx. %2,0,%1\n" /* update zero_list in mem */
+ " bne- 101b\n" /* if lost reservation try again */
+ : "=&r" (zero_list)
+ : "r" (&zero_list), "r" (pageptr)
+ : "cc" );
+ /*
+ * This variable is used in the above loop and nowhere
+ * else so the worst that could happen is we would
+ * zero out one more or one less page than we want
+ * per processor on the machine. This is because
+ * we could add our page to the list but not have
+ * zerocount updated yet when another processor
+ * reads it. -- Cort
+ */
+ atomic_inc((atomic_t *)&zerocount);
+ atomic_inc((atomic_t *)&zerototal);
+retry:
+ schedule();
+ }
+}
+
+void powerd(void)
+{
+ unsigned long msr, hid0;
+
+ sprintf(current->comm, "powerd");
+ __sti();
+ while (1)
+ {
+ /* want priority over idle task 'swapper' -- Cort */
+ current->priority = -99;
+ current->counter = -99;
+ asm volatile(
+ /* clear powersaving modes and set nap mode */
+ "mfspr %3,1008 \n\t"
+ "andc %3,%3,%4 \n\t"
+ "or %3,%3,%5 \n\t"
+ "mtspr 1008,%3 \n\t"
+ /* enter the mode */
+ "mfmsr %0 \n\t"
+ "oris %0,%0,%2 \n\t"
+ "sync \n\t"
+ "mtmsr %0 \n\t"
+ "isync \n\t"
+ : "=&r" (msr)
+ : "0" (msr), "i" (MSR_POW>>16),
+ "r" (hid0),
+ "r" (HID0_DOZE|HID0_NAP|HID0_SLEEP),
+ "r" (HID0_NAP));
+ if ( need_resched )
+ schedule();
+ /*
+ * The ibm carolina spec says that the eagle memory
+ * controller will detect the need for a snoop
+ * and wake up the processor so we don't need to
+ * check for cache operations that need to be
+ * snooped. The ppc book says the run signal
+ * must be asserted while napping for this though.
+ * -- Cort
+ */
+ }
+}
+
asmlinkage int sys_idle(void)
{
int ret = -EPERM;
-
- lock_kernel();
if (current->pid != 0)
goto out;
- /* endless idle loop with no priority at all */
+#ifdef IDLE_ZERO
+ /*
+ * want one per cpu since it would be nice to have all
+ * processors who aren't doing anything
+ * zero-ing pages since this daemon is lock-free
+ * -- Cort
+ */
+ kernel_thread(zero_paged, NULL, 0);
+#endif /* IDLE_ZERO */
+
+#ifdef CONFIG_POWERSAVING
+ /* no powersaving modes on 601 - one per processor */
+ if( (_get_PVR()>>16) != 1 )
+ kernel_thread(powerd, NULL, 0);
+#endif /* CONFIG_POWERSAVING */
+
+ /* endless loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
- for (;;) {
+ for (;;)
+ {
schedule();
}
ret = 0;
out:
- unlock_kernel();
return ret;
}
void show_regs(struct pt_regs * regs)
{
+ int i;
+
+ printk("NIP: %08X XER: %08X LR: %08X REGS: %08X TRAP: %04x\n",
+ regs->nip, regs->xer, regs->link, regs,regs->trap);
+ printk("MSR: %08x EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
+ regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
+ regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
+ regs->msr&MSR_IR ? 1 : 0,
+ regs->msr&MSR_DR ? 1 : 0);
+ printk("TASK = %x[%d] '%s' mm->pgd %08X ",
+ current, current->pid, current->comm, current->mm->pgd);
+ printk("Last syscall: %d ", current->tss.last_syscall);
+ printk("\nlast math %08X\n", last_task_used_math);
+ for (i = 0; i < 32; i++)
+ {
+ long r;
+ if ((i % 8) == 0)
+ {
+ printk("GPR%02d: ", i);
+ }
+
+ if ( get_user(r, &(regs->gpr[i])) )
+ goto out;
+ printk("%08X ", r);
+ if ((i % 8) == 7)
+ {
+ printk("\n");
+ }
+ }
+out:
}
void exit_thread(void)
{
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
}
void flush_thread(void)
{
+ if (last_task_used_math == current)
+ last_task_used_math = NULL;
}
void
@@ -197,50 +480,25 @@ release_thread(struct task_struct *t)
}
/*
- * Copy a thread..
- */
-int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
- struct task_struct * p, struct pt_regs * regs)
+ * Copy a thread..
+ */
+int
+copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ struct task_struct * p, struct pt_regs * regs)
{
int i;
- SEGREG *segs;
struct pt_regs * childregs;
-
- /* Construct segment registers */
- segs = (SEGREG *)(p->tss.segs);
- for (i = 0; i < 8; i++)
- {
- segs[i].ks = 0;
- segs[i].kp = 1;
-#if 0
- segs[i].vsid = i | (nr << 4);
-#else
- segs[i].vsid = i | ((nr * 10000) << 4);
-#endif
- }
- if ((p->mm->context == 0) || (p->mm->count == 1))
- {
-#if 0
- p->mm->context = ((nr)<<4);
-#else
- p->mm->context = ((nr*10000)<<4);
-#endif
- }
-
- /* Last 8 are shared with kernel & everybody else... */
- for (i = 8; i < 16; i++)
- {
- segs[i].ks = 0;
- segs[i].kp = 1;
- segs[i].vsid = i;
- }
-
/* Copy registers */
- childregs = ((struct pt_regs *) (p->kernel_stack_page + PAGE_SIZE)) - 2;
+ childregs = ((struct pt_regs *)
+ ((unsigned long)p + sizeof(union task_union)
+ - STACK_FRAME_OVERHEAD)) - 2;
+ *childregs = *regs;
- *childregs = *regs; /* STRUCT COPY */
+ if ((childregs->msr & MSR_PR) == 0)
+ childregs->gpr[2] = (unsigned long) p; /* `current' in new task */
childregs->gpr[3] = 0; /* Result from fork() */
- p->tss.ksp = (unsigned long)(childregs);
+ p->tss.ksp = (unsigned long)(childregs) - STACK_FRAME_OVERHEAD;
+ p->tss.regs = (struct pt_regs *)(childregs);
if (usp >= (unsigned long)regs)
{ /* Stack is in kernel space - must adjust */
childregs->gpr[1] = (long)(childregs+1);
@@ -248,23 +506,29 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
{ /* Provided stack is in user space */
childregs->gpr[1] = usp;
}
- p->tss.fp_used = 0;
- return 0;
-}
+ p->tss.last_syscall = -1;
-/*
- * fill in the user structure for a core dump..
- */
-void dump_thread(struct pt_regs * regs, struct user * dump)
-{
+ /*
+ * copy fpu info - assume lazy fpu switch now always
+ * this should really be conditional on whether or
+ * not the process has used the fpu
+ * -- Cort
+ */
+ if ( last_task_used_math == current )
+ giveup_fpu();
+
+ memcpy(&p->tss.fpr, &current->tss.fpr, sizeof(p->tss.fpr));
+ p->tss.fpscr = current->tss.fpscr;
+ childregs->msr &= ~MSR_FP;
+
+ return 0;
}
-
-asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs)
+asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
+ struct pt_regs *regs)
{
int ret;
-
lock_kernel();
ret = do_fork(SIGCHLD, regs->gpr[1], regs);
unlock_kernel();
@@ -272,46 +536,21 @@ asmlinkage int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct p
}
asmlinkage int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs *regs)
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs *regs)
{
int error;
char * filename;
-
- lock_kernel();
- /* getname does it's own verification of the address
- when it calls get_max_filename() but
- it will assume it's valid if get_fs() == KERNEL_DS
- which is always true on the ppc so we check
- it here
-
- this doesn't completely check any of these data structures,
- it just makes sure that the 1st long is in a good area
- and from there we assume that it's safe then
- -- Cort
- */
- /* works now since get_fs/set_fs work properly */
-#if 0
- if ( verify_area(VERIFY_READ,(void *)a0,1)
- && verify_area(VERIFY_READ,(void *)a1,1)
- && verify_area(VERIFY_READ,(void *)a2,1)
- )
- {
- return -EFAULT;
- }
-#endif
- error = getname((char *) a0, &filename);
- if (error)
+ filename = (int) getname((char *) a0);
+ error = PTR_ERR(filename);
+ if(IS_ERR(filename))
goto out;
- flush_instruction_cache();
+ if ( last_task_used_math == current )
+ last_task_used_math = NULL;
error = do_execve(filename, (char **) a1, (char **) a2, regs);
-#if 0
-if (error)
-{
-printk("EXECVE - file = '%s', error = %d\n", filename, error);
-}
-#endif
+
putname(filename);
+
out:
unlock_kernel();
return error;
@@ -321,7 +560,7 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct
{
unsigned long clone_flags = p1;
int res;
-
+
lock_kernel();
res = do_fork(clone_flags, regs->gpr[1], regs);
unlock_kernel();
@@ -331,13 +570,17 @@ asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, struct
void
print_backtrace(unsigned long *sp)
{
-#if 0
int cnt = 0;
- printk("... Call backtrace:\n");
- while (verify_area(VERIFY_READ,sp,sizeof(long)) && *sp)
+ int i;
+ printk("Call backtrace: ");
+ while ( !get_user(i, sp) && i)
{
- printk("%08X ", sp[1]);
- sp = (unsigned long *)*sp;
+ if ( get_user( i, &sp[1] ) )
+ return;
+ printk("%08X ", i);
+ if ( get_user( (ulong)sp, sp) )
+ return;
+ if (cnt == 6 ) cnt = 7; /* wraparound early -- Cort */
if (++cnt == 8)
{
printk("\n");
@@ -345,43 +588,66 @@ print_backtrace(unsigned long *sp)
if (cnt > 32) break;
}
printk("\n");
-#endif
-}
-
-void
-print_user_backtrace(unsigned long *sp)
-{
-#if 0
- int cnt = 0;
- printk("... [User] Call backtrace:\n");
- while (verify_area(VERIFY_READ,sp,sizeof(long)) && *sp)
- {
- printk("%08X ", sp[1]);
- sp = (unsigned long *)*sp;
- if (++cnt == 8)
- {
- printk("\n");
- }
- if (cnt > 16) break;
- }
- printk("\n");
-#endif
}
-void
-print_kernel_backtrace(void)
-{
-#if 0
- unsigned long *_get_SP(void);
- print_backtrace(_get_SP());
-#endif
-}
inline void start_thread(struct pt_regs * regs,
unsigned long eip, unsigned long esp)
{
+ set_fs(USER_DS);
regs->nip = eip;
regs->gpr[1] = esp;
regs->msr = MSR_USER;
- set_fs(USER_DS);
}
+/*
+ * Low level print for debugging - Cort
+ */
+int ll_printk(const char *fmt, ...)
+{
+ va_list args;
+ char buf[256];
+ int i;
+
+ va_start(args, fmt);
+ i=sprintf(buf,fmt,args);
+ ll_puts(buf);
+ va_end(args);
+ return i;
+}
+
+char *vidmem = (char *)0xC00B8000;
+int lines = 24, cols = 80;
+int orig_x = 0, orig_y = 0;
+
+void ll_puts(const char *s)
+{
+ int x,y;
+ char c;
+
+ x = orig_x;
+ y = orig_y;
+
+ while ( ( c = *s++ ) != '\0' ) {
+ if ( c == '\n' ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ /*scroll();*/
+ /*y--;*/
+ y = 0;
+ }
+ } else {
+ vidmem [ ( x + cols * y ) * 2 ] = c;
+ if ( ++x >= cols ) {
+ x = 0;
+ if ( ++y >= lines ) {
+ /*scroll();*/
+ /*y--;*/
+ y = 0;
+ }
+ }
+ }
+ }
+
+ orig_x = x;
+ orig_y = y;
+}
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index dc8a95302..a5ec62d20 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -1,12 +1,14 @@
/*
* linux/arch/ppc/kernel/ptrace.c
*
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/m68k/kernel/ptrace.c"
* Copyright (C) 1994 by Hamish Macdonald
* Taken from linux/kernel/ptrace.c and modified for M680x0.
* linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
*
- * Adapted from 'linux/arch/m68k/kernel/ptrace.c'
- * PowerPC version by Gary Thomas (gdt@linuxppc.org)
* Modified by Cort Dougan (cort@cs.nmt.edu)
*
* This file is subject to the terms and conditions of the GNU General
@@ -34,52 +36,13 @@
* in exit.c or in signal.c.
*/
-/* Find the stack offset for a register, relative to tss.ksp. */
-#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
-/* Mapping from PT_xxx to the stack offset at which the register is
- saved. Notice that usp has no stack-slot and needs to be treated
- specially (see get_reg/put_reg below). */
-static int regoff[] = {
-};
-
/*
* Get contents of register REGNO in task TASK.
*/
static inline long get_reg(struct task_struct *task, int regno)
{
- struct pt_regs *regs = task->tss.regs;
- if (regno <= PT_R31)
- {
- return (regs->gpr[regno]);
- } else
- if (regno == PT_NIP)
- {
- return (regs->nip);
- } else
- if (regno == PT_MSR)
- {
- return (regs->msr);
- } else
- if (regno == PT_ORIG_R3)
- {
- return (regs->orig_gpr3);
- } else
- if (regno == PT_CTR)
- {
- return (regs->ctr);
- } else
- if (regno == PT_LNK)
- {
- return (regs->link);
- } else
- if (regno == PT_XER)
- {
- return (regs->xer);
- } else
- if (regno == PT_CCR)
- {
- return (regs->ccr);
- }
+ if (regno <= PT_CCR)
+ return ((unsigned long *)task->tss.regs)[regno];
return (0);
}
@@ -89,52 +52,21 @@ static inline long get_reg(struct task_struct *task, int regno)
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
- struct pt_regs *regs = task->tss.regs;
- if (regno <= PT_R31)
- {
- regs->gpr[regno] = data;
- } else
- if (regno == PT_NIP)
- {
- regs->nip = data;
- } else
- if (regno == PT_MSR)
- {
- regs->msr = data;
- } else
- if (regno == PT_CTR)
- {
- regs->ctr = data;
- } else
- if (regno == PT_LNK)
- {
- regs->link = data;
- } else
- if (regno == PT_XER)
- {
- regs->xer = data;
- } else
- if (regno == PT_CCR)
- {
- regs->ccr = data;
- } else
- { /* Invalid register */
- return (-1);
+ if (regno <= PT_CCR) {
+ ((unsigned long *)task->tss.regs)[regno] = data;
+ return 0;
}
- return (0);
+ return -1;
}
-static inline
+static inline void
set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->tss.regs;
-printk("Set single step - Task: %x, Regs: %x", task, regs);
-printk(", MSR: %x/", regs->msr);
regs->msr |= MSR_SE;
-printk("%x\n", regs->msr);
}
-static inline
+static inline void
clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->tss.regs;
@@ -159,33 +91,32 @@ static unsigned long get_long(struct task_struct * tsk,
repeat:
pgdir = pgd_offset(vma->vm_mm, addr);
if (pgd_none(*pgdir)) {
- do_no_page(tsk, vma, addr, 0);
+ handle_mm_fault(tsk, vma, addr, 0);
goto repeat;
}
if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
+ printk("ptrace[1]: bad page directory %lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
return 0;
}
pgmiddle = pmd_offset(pgdir,addr);
if (pmd_none(*pgmiddle)) {
- do_no_page(tsk, vma, addr, 0);
+ handle_mm_fault(tsk, vma, addr, 0);
goto repeat;
}
if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page directory %08lx\n",
- pmd_val(*pgmiddle));
+ printk("ptrace[3]: bad pmd %lx\n", pmd_val(*pgmiddle));
pmd_clear(pgmiddle);
return 0;
}
pgtable = pte_offset(pgmiddle, addr);
if (!pte_present(*pgtable)) {
- do_no_page(tsk, vma, addr, 0);
+ handle_mm_fault(tsk, vma, addr, 0);
goto repeat;
}
page = pte_page(*pgtable);
/* this is a hack for non-kernel-mapped video buffers and similar */
- if (page >= high_memory)
+ if (MAP_NR(page) >= max_mapnr)
return 0;
page += addr & ~PAGE_MASK;
return *(unsigned long *) page;
@@ -200,8 +131,8 @@ repeat:
* Now keeps R/W state of page so that a text page stays readonly
* even if a debugger scribbles breakpoints into it. -M.U-
*/
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsigned long addr,
- unsigned long data)
+static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
+ unsigned long addr, unsigned long data)
{
pgd_t *pgdir;
pmd_t *pgmiddle;
@@ -211,42 +142,40 @@ static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, unsi
repeat:
pgdir = pgd_offset(vma->vm_mm, addr);
if (!pgd_present(*pgdir)) {
- do_no_page(tsk, vma, addr, 1);
+ handle_mm_fault(tsk, vma, addr, 1);
goto repeat;
}
if (pgd_bad(*pgdir)) {
- printk("ptrace: bad page directory %08lx\n", pgd_val(*pgdir));
+ printk("ptrace[2]: bad page directory %lx\n", pgd_val(*pgdir));
pgd_clear(pgdir);
return;
}
pgmiddle = pmd_offset(pgdir,addr);
if (pmd_none(*pgmiddle)) {
- do_no_page(tsk, vma, addr, 1);
+ handle_mm_fault(tsk, vma, addr, 1);
goto repeat;
}
if (pmd_bad(*pgmiddle)) {
- printk("ptrace: bad page directory %08lx\n",
- pmd_val(*pgmiddle));
+ printk("ptrace[4]: bad pmd %lx\n", pmd_val(*pgmiddle));
pmd_clear(pgmiddle);
return;
}
pgtable = pte_offset(pgmiddle, addr);
if (!pte_present(*pgtable)) {
- do_no_page(tsk, vma, addr, 1);
+ handle_mm_fault(tsk, vma, addr, 1);
goto repeat;
}
page = pte_page(*pgtable);
if (!pte_write(*pgtable)) {
- do_wp_page(tsk, vma, addr, 2);
+ handle_mm_fault(tsk, vma, addr, 1);
goto repeat;
}
/* this is a hack for non-kernel-mapped video buffers and similar */
- if (page < high_memory) {
+ if (MAP_NR(page) < max_mapnr)
*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
- }
/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
/* this should also re-instate whatever read-only mode there was before */
- *pgtable = pte_mkdirty(mk_pte(page, vma->vm_page_prot));
+ set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
flush_tlb_all();
}
@@ -366,7 +295,6 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
- struct user * dummy = NULL;
int ret = -EPERM;
lock_kernel();
@@ -436,8 +364,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_PEEKUSR: {
unsigned long tmp;
- if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
- return -EIO;
+ if ((addr & 3) || addr < 0 || addr >= sizeof(struct user)) {
+ ret = -EIO;
+ goto out;
+ }
ret = verify_area(VERIFY_WRITE, (void *) data,
sizeof(long));
@@ -445,15 +375,19 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
goto out;
tmp = 0; /* Default return condition */
addr = addr >> 2; /* temporary hack. */
- if (addr < PT_FPR0)
+ if (addr < PT_FPR0) {
tmp = get_reg(child, addr);
-#if 0
- else if (addr >= PT_FPR0 && addr < PT_FPR31)
- tmp = child->tss.fpr[addr - PT_FPR0];
-#endif
+ }
+#if 1
+ else if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
+ if (last_task_used_math == child)
+ giveup_fpu();
+ tmp = ((long *)child->tss.fpr)[addr - PT_FPR0];
+ }
+#endif
else
ret = -EIO;
- if(!ret)
+ if (!ret)
put_user(tmp,(unsigned long *) data);
goto out;
}
@@ -486,13 +420,13 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = 0;
goto out;
}
-#if 0
- if (addr >= 21 && addr < 48) {
- child->tss.fp[addr - 21] = data;
+ if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
+ if (last_task_used_math == child)
+ giveup_fpu();
+ ((long *)child->tss.fpr)[addr - PT_FPR0] = data;
ret = 0;
goto out;
}
-#endif
goto out;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 25f03cc11..e69de29bb 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -1,409 +0,0 @@
-/*
- * linux/arch/ppc/kernel/setup.c
- *
- * Copyright (C) 1995 Linus Torvalds
- * Adapted from 'alpha' version by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/malloc.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/major.h>
-
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-
-extern unsigned long *end_of_DRAM;
-extern PTE *Hash;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-unsigned long empty_zero_page[1024];
-
-unsigned char aux_device_present;
-#ifdef CONFIG_BLK_DEV_RAM
-extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
-extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start; /* starting block # of image */
-#endif
-
-#undef HASHSTATS
-
-extern unsigned long isBeBox[];
-
-/* copy of the residual data */
-RESIDUAL res;
-unsigned long resptr = 0; /* ptr to residual data from hw */
-
-/*
- * The format of "screen_info" is strange, and due to early
- * i386-setup code. This is just enough to make the console
- * code think we're on a EGA+ colour display.
- */
- /* this is changed only in minor ways from the original
- -- Cort
- */
-struct screen_info screen_info = {
- 0, 25, /* orig-x, orig-y */
- { 0, 0 }, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 80, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 25, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-};
-
-
-unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
-{
- return memory_start;
-}
-
-#ifdef HASHSTATS
-unsigned long *hashhits;
-#endif
-
-extern unsigned long _TotalMemory;
-/* find the physical size of RAM and setup hardware hash table */
-unsigned long *find_end_of_memory(void)
-{
- extern BAT BAT2;
- _TotalMemory = res.TotalMemory;
-
- if (_TotalMemory == 0 )
- {
- printk("Ramsize from residual data was 0 -- Probing for value\n");
- /* this needs be done differently since the bats actually map
- addresses beyond physical memory! -- Cort */
-#if 0
- probingmem = 1;
- while ( probingmem )
- {
- _TotalMemory += 0x00800000; /* 8M */
- *(unsigned long *)_TotalMemory+KERNELBASE;
- }
- _TotalMemory -= 0x00800000;
-#else
- _TotalMemory = 0x03000000;
-#endif
- printk("Ramsize probed to be %dM\n", _TotalMemory>>20);
- }
-
- /* setup BAT2 mapping so that it covers kernelbase to kernelbase+ramsize */
- switch(_TotalMemory)
- {
- case 0x01000000: /* 16M */
- BAT2.batu.bl = BL_16M;
- Hash_size = HASH_TABLE_SIZE_128K;
- Hash_mask = HASH_TABLE_MASK_128K;
- break;
- case 0x00800000: /* 8M */
- BAT2.batu.bl = BL_8M;
- Hash_size = HASH_TABLE_SIZE_64K;
- Hash_mask = HASH_TABLE_MASK_64K;
- break;
- case 0x01800000: /* 24M */
- case 0x02000000: /* 32M */
- BAT2.batu.bl = BL_32M;
- Hash_size = HASH_TABLE_SIZE_256K;
- Hash_mask = HASH_TABLE_MASK_256K;
- break;
- case 0x03000000: /* 48M */
- case 0x04000000: /* 64M */
- BAT2.batu.bl = BL_64M;
- Hash_size = HASH_TABLE_SIZE_512K;
- Hash_mask = HASH_TABLE_MASK_512K;
- break;
- case 0x05000000: /* 80M */
- BAT2.batu.bl = BL_128M;
- Hash_size = HASH_TABLE_SIZE_1M;
- Hash_mask = HASH_TABLE_MASK_1M;
- break;
- default:
- printk("WARNING: setup.c: find_end_of_memory() unknown total ram size %x\n",
- _TotalMemory);
- break;
- }
-
- Hash = (PTE *)((_TotalMemory-Hash_size)+KERNELBASE);
- bzero(Hash, Hash_size);
-
-
-#ifdef HASHSTATS
- hashhits = (unsigned long *)Hash - (Hash_size/sizeof(struct _PTE))/2;
- bzero(hashhits, (Hash_size/sizeof(struct _PTE))/2);
- return ((unsigned long *)hashhits);
-#else
- return ((unsigned long *)Hash);
-#endif
-}
-
-int size_memory;
-
-/*
- * This is set up by the setup-routine at boot-time
- */
-#define EXT_MEM_K (*(unsigned short *) (PARAM+2))
-#ifdef CONFIG_APM
-#define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+64))
-#endif
-#define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80))
-#define SCREEN_INFO (*(struct screen_info *) (PARAM+0))
-#define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2))
-#define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
-#define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
-#define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
-#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
-#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
-#define INITRD_START (*(unsigned long *) (PARAM+0x218))
-#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
-#define COMMAND_LINE ((char *) (PARAM+2048))
-#define COMMAND_LINE_SIZE 256
-
-#define RAMDISK_IMAGE_START_MASK 0x07FF
-#define RAMDISK_PROMPT_FLAG 0x8000
-#define RAMDISK_LOAD_FLAG 0x4000
-
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
- char saved_command_line[COMMAND_LINE_SIZE];
-
-
-void
-setup_arch(char **cmdline_p, unsigned long * memory_start_p,
- unsigned long * memory_end_p)
-{
- extern int _end;
- extern char cmd_line[];
- unsigned char reg;
- extern int panic_timeout;
- char inf[512];
- int i;
-
- if (isBeBox[0])
- _Processor = _PROC_Be;
- else
- {
- if (strncmp(res.VitalProductData.PrintableModel,"IBM",3))
- {
- _Processor = _PROC_Motorola;
- }
- else
- _Processor = _PROC_IBM;
- }
-
- get_cpuinfo(&inf);
- printk("%s",inf);
-
- /* Set up floppy in PS/2 mode */
- outb(0x09, SIO_CONFIG_RA);
- reg = inb(SIO_CONFIG_RD);
- reg = (reg & 0x3F) | 0x40;
- outb(reg, SIO_CONFIG_RD);
- outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
-
- switch ( _Processor )
- {
- case _PROC_IBM:
- ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
- break;
- case _PROC_Motorola:
- ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
- break;
- }
- aux_device_present = 0xaa;
-
- panic_timeout = 300; /* reboot on panic */
-
-#if 0
- /* get root via nfs from charon -- was only used for testing */
- ROOT_DEV = MKDEV(UNNAMED_MAJOR, 255); /* nfs */
- /*nfsaddrs=myip:serverip:gateip:netmaskip:clientname*/
- strcpy(cmd_line,
- "nfsaddrs=129.138.6.101:129.138.6.90:129.138.6.1:255.255.255.0:gordito nfsroot=/joplin/ppc/root/");
-#endif
- *cmdline_p = cmd_line;
- *memory_start_p = (unsigned long) &_end;
- (unsigned long *)*memory_end_p = (unsigned long *)end_of_DRAM;
- size_memory = *memory_end_p - KERNELBASE; /* Relative size of memory */
-
-#ifdef CONFIG_BLK_DEV_RAM
- rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
- rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
- rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
-#if 1
- rd_prompt = 1;
- rd_doload = 1;
- rd_image_start = 0;
-#endif
-#endif
-
- /* Save unparsed command line copy for /proc/cmdline */
- memcpy(saved_command_line, cmd_line,strlen(cmd_line)+1);
- printk("Command line: %s\n", cmd_line);
-}
-
-asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
-{
- return -EIO;
-}
-
-
-int
-get_cpuinfo(char *buffer)
-{
- extern unsigned long loops_per_sec;
- int i;
- int pvr = _get_PVR();
- int len;
- char *model;
- unsigned long full = 0, overflow = 0;
- unsigned int ti;
- PTE *ptr;
-
- switch (pvr>>16)
- {
- case 3:
- model = "603";
- break;
- case 4:
- model = "604";
- break;
- case 6:
- model = "603e";
- break;
- case 7:
- model = "603ev";
- break;
- default:
- model = "unknown";
- break;
- }
-
-#ifdef __SMP__
-#define CD(X) (cpu_data[n].X)
-#else
-#define CD(X) (X)
-#define CPUN 0
-#endif
-
- len = sprintf(buffer, "PowerPC %s/%dMHz revision %d.%d %s\n",
- model,
- (res.VitalProductData.ProcessorHz > 1024) ?
- res.VitalProductData.ProcessorHz>>20 :
- res.VitalProductData.ProcessorHz,
- MAJOR(pvr), MINOR(pvr),
- (inb(IBM_EQUIP_PRESENT) & 2) ? "" : "upgrade");
-#if 1
- if ( res.VitalProductData.PrintableModel[0] )
- len += sprintf(buffer+len,"%s\n",res.VitalProductData.PrintableModel);
-
- len += sprintf(buffer+len,"Bus %dMHz\n",
- (res.VitalProductData.ProcessorBusHz > 1024) ?
- res.VitalProductData.ProcessorBusHz>>20 :
- res.VitalProductData.ProcessorBusHz);
-
- /* make sure loops_per_sec has been setup -- ie not at boottime -- Cort */
- if ( CD(loops_per_sec+2500)/500000 > 0)
- len += sprintf(buffer+len,
- "bogomips: %lu.%02lu\n",
- CD(loops_per_sec+2500)/500000,
- (CD(loops_per_sec+2500)/5000) % 100);
-
-
- len += sprintf(buffer+len,"Total Ram: %dM Hash Table: %dkB (%dk buckets)\n",
- _TotalMemory>>20, Hash_size>>10,
- (Hash_size/(sizeof(PTE)*8)) >> 10);
-
- for ( i = 0 ; (res.ActualNumMemories) && (i < MAX_MEMS) ; i++ )
- {
- if (i == 0)
- len += sprintf(buffer+len,"SIMM Banks: ");
- if ( res.Memories[i].SIMMSize != 0 )
- len += sprintf(buffer+len,"%d:%dM ",i,
- (res.Memories[i].SIMMSize > 1024) ?
- res.Memories[i].SIMMSize>>20 :
- res.Memories[i].SIMMSize);
- if ( i == MAX_MEMS-1)
- len += sprintf(buffer+len,"\n");
- }
-
- /* TLB */
- len += sprintf(buffer+len,"TLB");
- switch(res.VitalProductData.TLBAttrib)
- {
- case CombinedTLB:
- len += sprintf(buffer+len,": %d entries\n",
- res.VitalProductData.TLBSize);
- break;
- case SplitTLB:
- len += sprintf(buffer+len,": (split I/D) %d/%d entries\n",
- res.VitalProductData.I_TLBSize,
- res.VitalProductData.D_TLBSize);
- break;
- case NoneTLB:
- len += sprintf(buffer+len,": not present\n");
- break;
- }
-
- /* L1 */
- len += sprintf(buffer+len,"L1: ");
- switch(res.VitalProductData.CacheAttrib)
- {
- case CombinedCAC:
- len += sprintf(buffer+len,"%dkB LineSize\n",
- res.VitalProductData.CacheSize,
- res.VitalProductData.CacheLineSize);
- break;
- case SplitCAC:
- len += sprintf(buffer+len,"(split I/D) %dkB/%dkB Linesize %dB/%dB\n",
- res.VitalProductData.I_CacheSize,
- res.VitalProductData.D_CacheSize,
- res.VitalProductData.D_CacheLineSize,
- res.VitalProductData.D_CacheLineSize);
- break;
- case NoneCAC:
- len += sprintf(buffer+len,"not present\n");
- break;
- }
-
- /* L2 */
- if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */
- {
- int size;
-
- len += sprintf(buffer+len,"L2: %dkB %s\n",
- ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256,
- (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled");
- }
- else
- {
- len += sprintf(buffer+len,"L2: not present\n");
- }
-#if 0
- len+= sprintf(buffer+len,"Equip register %x\n",
- inb(IBM_EQUIP_PRESENT));
- len+= sprintf(buffer+len,"L2Status register %x\n",
- inb(IBM_L2_STATUS));
-#endif
-#endif
-
-
- return len;
-}
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index ba8864251..2f602059c 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -1,9 +1,17 @@
/*
* linux/arch/ppc/kernel/signal.c
*
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Adapted for PowerPC by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Derived from "arch/i386/kernel/signal.c"
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 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/sched.h>
@@ -22,6 +30,12 @@
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+#define DEBUG_SIGNALS
+#undef DEBUG_SIGNALS
+
+#define PAUSE_AFTER_SIGNAL
+#undef PAUSE_AFTER_SIGNAL
+
asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
/*
@@ -30,79 +44,85 @@ asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
asmlinkage int sys_sigsuspend(unsigned long set, int p2, int p3, int p4, int p6, int p7, struct pt_regs *regs)
{
unsigned long mask;
- int ret = -EINTR;
- lock_kernel();
+ spin_lock_irq(&current->sigmask_lock);
mask = current->blocked;
current->blocked = set & _BLOCKABLE;
+ spin_unlock_irq(&current->sigmask_lock);
+
regs->gpr[3] = -EINTR;
-#if 0
+#ifdef DEBUG_SIGNALS
printk("Task: %x[%d] - SIGSUSPEND at %x, Mask: %x\n", current, current->pid, regs->nip, set);
#endif
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(mask,regs))
- goto out;
+ if (do_signal(mask,regs)) {
+ /*
+ * If a signal handler needs to be called,
+ * do_signal() has set R3 to the signal number (the
+ * first argument of the signal handler), so don't
+ * overwrite that with EINTR !
+ * In the other cases, do_signal() doesn't touch
+ * R3, so it's still set to -EINTR (see above).
+ */
+ return regs->gpr[3];
+ }
}
-out:
- unlock_kernel();
- return ret;
}
+/*
+ * This sets regs->esp even though we don't actually use sigstacks yet..
+ */
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
struct sigcontext_struct *sc;
struct pt_regs *int_regs;
int signo, ret;
- lock_kernel();
#if 1
if (verify_area(VERIFY_READ, (void *) regs->gpr[1], sizeof(sc))
- || (regs->gpr[1] >=KERNELBASE))
+ || (regs->gpr[1] >= KERNELBASE))
goto badframe;
#endif
- sc = (struct sigcontext_struct *)regs->gpr[1];
- current->blocked = sc->oldmask & _BLOCKABLE;
- int_regs = sc->regs;
- signo = sc->signal;
- sc++; /* Pop signal 'context' */
+ sc = (struct sigcontext_struct *)(regs->gpr[1]+STACK_FRAME_OVERHEAD);
+ get_user(current->blocked, &sc->oldmask);
+ current->blocked &= _BLOCKABLE;
+ get_user(int_regs, &sc->regs);
+ get_user(signo, &sc->signal);
+ sc++; /* Pop signal 'context' */
+#ifdef DEBUG_SIGNALS
+printk("Sig return - Regs: %x, sc: %x, sig: %d\n", int_regs, sc, signo);
+#endif
if (sc == (struct sigcontext_struct *)(int_regs)) {
/* Last stacked signal */
-#if 0
- /* This doesn't work - it blows away the return address! */
memcpy(regs, int_regs, sizeof(*regs));
-#else
- /* Don't mess up 'my' stack frame */
- memcpy(&regs->gpr, &int_regs->gpr, sizeof(*regs)-sizeof(regs->_overhead));
-#endif
- if ((int)regs->orig_gpr3 >= 0 &&
+ if (regs->trap == 0x0C00 /* System Call! */ &&
((int)regs->result == -ERESTARTNOHAND ||
(int)regs->result == -ERESTARTSYS ||
- (int)regs->result == -ERESTARTNOINTR))
- {
+ (int)regs->result == -ERESTARTNOINTR)) {
regs->gpr[3] = regs->orig_gpr3;
regs->nip -= 4; /* Back up & retry system call */
regs->result = 0;
}
- ret = (regs->result);
- } else { /* More signals to go */
- regs->gpr[1] = (unsigned long)sc;
- regs->gpr[3] = sc->signal;
- regs->gpr[4] = sc->regs;
- regs->link = (unsigned long)((sc->regs)+1);
- regs->nip = sc->handler;
- ret = sc->signal;
+ ret = regs->result;
+ } else {
+ /* More signals to go */
+ regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD;
+ get_user(regs->gpr[3], &sc->signal);
+ get_user(int_regs, (struct pt_regs **) &sc->regs);
+ regs->gpr[4] = (unsigned long) int_regs;
+ regs->link = (unsigned long) (int_regs+1);
+ get_user(regs->nip, &sc->handler);
+ ret = regs->gpr[3];
}
- goto out;
+ return ret;
badframe:
- /*printk("sys_sigreturn(): badstack regs %x cur %s/%d\n",
- regs,current->comm,current->pid);*/
+ lock_kernel();
do_exit(SIGSEGV);
-out:
unlock_kernel();
- return ret;
+ return -EFAULT;
}
@@ -120,21 +140,24 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
unsigned long mask;
unsigned long handler_signal = 0;
unsigned long *frame = NULL;
- unsigned long *trampoline, *regs_ptr;
+ unsigned long *trampoline;
+ unsigned long *regs_ptr;
unsigned long nip = 0;
unsigned long signr;
struct sigcontext_struct *sc;
struct sigaction * sa;
- int bitno, s, ret;
+ int bitno;
- lock_kernel();
mask = ~current->blocked;
while ((signr = current->signal & mask)) {
+#if 0
+ signr = ffz(~signr); /* Compute bit # */
+#else
for (bitno = 0; bitno < 32; bitno++)
if (signr & (1<<bitno))
break;
signr = bitno;
-
+#endif
current->signal &= ~(1<<signr); /* Clear bit */
sa = current->sig->action + signr;
signr++;
@@ -150,6 +173,8 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
continue;
if (_S(signr) & current->blocked) {
current->signal |= _S(signr);
+ spin_lock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sigmask_lock);
continue;
}
sa = current->sig->action + signr - 1;
@@ -169,32 +194,45 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
case SIGCONT: case SIGCHLD: case SIGWINCH:
continue;
- case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (is_orphaned_pgrp(current->pgrp))
+ continue;
+ case SIGSTOP:
if (current->flags & PF_PTRACED)
continue;
current->state = TASK_STOPPED;
current->exit_code = signr;
if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
- SA_NOCLDSTOP))
+ SA_NOCLDSTOP))
notify_parent(current);
schedule();
continue;
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
+ lock_kernel();
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
signr |= 0x80;
}
+ unlock_kernel();
/* fall through */
default:
+ spin_lock_irq(&current->sigmask_lock);
current->signal |= _S(signr & 0x7f);
+ spin_unlock_irq(&current->sigmask_lock);
+
+ current->flags |= PF_SIGNALED;
+
+ lock_kernel(); /* 8-( */
do_exit(signr);
+ unlock_kernel();
}
}
-
- /* handle signal */
- if ((int)regs->orig_gpr3 >= 0) {
+ /*
+ * OK, we're invoking a handler
+ */
+ if (regs->trap == 0x0C00 /* System Call! */) {
if ((int)regs->result == -ERESTARTNOHAND ||
((int)regs->result == -ERESTARTSYS &&
!(sa->sa_flags & SA_RESTART)))
@@ -203,9 +241,18 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
handler_signal |= 1 << (signr-1);
mask &= ~sa->sa_mask;
}
- ret = 0;
- if (!handler_signal) /* no handler will be called - return 0 */
- goto out;
+
+ if (regs->trap == 0x0C00 /* System Call! */ &&
+ ((int)regs->result == -ERESTARTNOHAND ||
+ (int)regs->result == -ERESTARTSYS ||
+ (int)regs->result == -ERESTARTNOINTR)) {
+ regs->gpr[3] = regs->orig_gpr3;
+ regs->nip -= 4; /* Back up & retry system call */
+ regs->result = 0;
+ }
+
+ if (!handler_signal) /* no handler will be called - return 0 */
+ return 0;
nip = regs->nip;
frame = (unsigned long *) regs->gpr[1];
@@ -213,20 +260,18 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
/* Build trampoline code on stack */
frame -= 2;
trampoline = frame;
-#if 1
/* verify stack is valid for writing regs struct */
if (verify_area(VERIFY_WRITE,(void *)frame, sizeof(long)*2+sizeof(*regs))
- || (frame >= KERNELBASE ))
+ || ((unsigned long) frame >= KERNELBASE ))
goto badframe;
-#endif
- trampoline[0] = 0x38007777; /* li r0,0x7777 */
- trampoline[1] = 0x44000002; /* sc */
+ put_user(0x38007777UL, trampoline); /* li r0,0x7777 */
+ put_user(0x44000002UL, trampoline+1); /* sc */
frame -= sizeof(*regs) / sizeof(long);
regs_ptr = frame;
- memcpy(regs_ptr, regs, sizeof(*regs));
+ copy_to_user(regs_ptr, regs, sizeof(*regs));
signr = 1;
sa = current->sig->action;
-
+
for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
if (mask > handler_signal)
break;
@@ -234,50 +279,39 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
continue;
frame -= sizeof(struct sigcontext_struct) / sizeof(long);
-#if 1
if (verify_area(VERIFY_WRITE,(void *)frame,
sizeof(struct sigcontext_struct)/sizeof(long)))
goto badframe;
-#endif
sc = (struct sigcontext_struct *)frame;
nip = (unsigned long) sa->sa_handler;
-#if 0 /* Old compiler */
- nip = *(unsigned long *)nip;
-#endif
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- sc->handler = nip;
- sc->oldmask = current->blocked;
- sc->regs = (unsigned long)regs_ptr;
- sc->signal = signr;
+ put_user(nip, &sc->handler);
+ put_user(oldmask, &sc->oldmask); /* was current->blocked */
+ put_user(regs_ptr, &sc->regs);
+ put_user(signr, &sc->signal);
current->blocked |= sa->sa_mask;
regs->gpr[3] = signr;
regs->gpr[4] = (unsigned long)regs_ptr;
}
regs->link = (unsigned long)trampoline;
regs->nip = nip;
- regs->gpr[1] = (unsigned long)sc;
+ regs->gpr[1] = (unsigned long)sc - STACK_FRAME_OVERHEAD;
- /* The DATA cache must be flushed here to insure coherency
- * between the DATA & INSTRUCTION caches. Since we just
- * created an instruction stream using the DATA [cache] space
- * and since the instruction cache will not look in the DATA
- * cache for new data, we have to force the data to go on to
- * memory and flush the instruction cache to force it to look
- * there. The following function performs this magic
- */
- flush_instruction_cache();
- ret = 1;
- goto out;
+ /* The DATA cache must be flushed here to insure coherency */
+ /* between the DATA & INSTRUCTION caches. Since we just */
+ /* created an instruction stream using the DATA [cache] space */
+ /* and since the instruction cache will not look in the DATA */
+ /* cache for new data, we have to force the data to go on to */
+ /* memory and flush the instruction cache to force it to look */
+ /* there. The following function performs this magic */
+ store_cache_range((unsigned long) trampoline,
+ (unsigned long) (trampoline + 2));
+ return 1;
badframe:
-#if 0
- printk("do_signal(): badstack signr %d frame %x regs %x cur %s/%d\n",
- signr, frame, regs, current->comm, current->pid);
-#endif
+ lock_kernel();
do_exit(SIGSEGV);
-
-out:
unlock_kernel();
- return ret;
+ return 0;
}
diff --git a/arch/ppc/kernel/stubs.c b/arch/ppc/kernel/stubs.c
index 30f028279..e69de29bb 100644
--- a/arch/ppc/kernel/stubs.c
+++ b/arch/ppc/kernel/stubs.c
@@ -1,58 +0,0 @@
-/*#include <linux/in.h>*/
-#include <linux/autoconf.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-
-void sys_iopl(void)
-{
- lock_kernel();
- panic("sys_iopl");
- unlock_kernel();
-}
-void sys_vm86(void)
-{
- lock_kernel();
- panic("sys_vm86");
- unlock_kernel();
-}
-void sys_modify_ldt(void)
-{
- lock_kernel();
- panic("sys_modify_ldt");
- unlock_kernel();
-}
-
-void sys_ipc(void)
-{
- lock_kernel();
- panic("sys_ipc");
- unlock_kernel();
-}
-
-void sys_newselect(void)
-{
- lock_kernel();
- panic("sys_newselect");
- unlock_kernel();
-}
-
-#ifndef CONFIG_MODULES
-void
-scsi_register_module(void)
-{
- lock_kernel();
- panic("scsi_register_module");
- unlock_kernel();
-}
-
-void
-scsi_unregister_module(void)
-{
- lock_kernel();
- panic("scsi_unregister_module");
- unlock_kernel();
-}
-#endif
-
-
-
diff --git a/arch/ppc/kernel/support.c b/arch/ppc/kernel/support.c
index cd2b58b8a..e69de29bb 100644
--- a/arch/ppc/kernel/support.c
+++ b/arch/ppc/kernel/support.c
@@ -1,84 +0,0 @@
-/*
- * Miscellaneous support routines
- */
-
-#include <asm/bitops.h>
-
-/*extern __inline__*/ int find_first_zero_bit(void *add, int len)
-{
- int mask, nr, i;
- BITFIELD *addr = add;
- nr = 0;
- while (len)
- {
- if (~*addr != 0)
- { /* Contains at least one zero */
- for (i = 0; i < 32; i++, nr++)
- {
- mask = BIT(nr);
- if ((mask & *addr) == 0)
- {
- return (nr);
- }
- }
- }
- len -= 32;
- addr++;
- nr += 32;
- }
- return (0); /* Shouldn't happen */
-}
-
-/*extern __inline__*/ int find_next_zero_bit(void *add, int last_bit, int nr)
-{
- int mask, i;
- BITFIELD *addr = add;
-#if 0
-printk("Find next (%x, %x)", addr, nr);
-#endif
- addr += nr >> 5;
-#if 0
-printk(" - Pat: %x(%08X)\n", addr, *addr);
-#endif
- if ((nr & 0x1F) != 0)
- {
- if (*addr != 0xFFFFFFFF)
- { /* At least one more bit available in this longword */
- for (i = (nr&0x1F); i < 32; i++, nr++)
- {
- mask = BIT(nr);
- if ((mask & *addr) == 0)
- {
-#if 0
-printk("(1)Bit: %x(%d), Pat: %x(%08x)\n", nr, nr&0x1F, addr, *addr);
-#endif
- return (nr);
- }
- }
- }
- addr++;
- nr = (nr + 0x1F) & ~0x1F;
- }
- while (nr < last_bit)
- {
- if (*addr != 0xFFFFFFFF)
- { /* Contains at least one zero */
- for (i = 0; i < 32; i++, nr++)
- {
- mask = BIT(nr);
- if ((mask & *addr) == 0)
- {
-#if 0
-printk("(2)Bit: %x(%d), Pat: %x(%08x)\n", nr, nr&0x1F, addr, *addr);
-#endif
- return (nr);
- }
- }
- }
- addr++;
- nr += 32;
- }
- return (nr); /* Shouldn't happen */
-}
-
-
diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c
index 9d18c45ab..bfdccdee6 100644
--- a/arch/ppc/kernel/syscalls.c
+++ b/arch/ppc/kernel/syscalls.c
@@ -9,6 +9,7 @@
* platform.
*/
+#include <linux/config.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -19,105 +20,45 @@
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/mman.h>
+#include <linux/ipc.h>
#include <asm/uaccess.h>
+#include <asm/ipc.h>
-/*
- * sys_pipe() is the normal C calling standard for creating
- * a pipe. It's not the way unix traditionally does this, though.
- */
-asmlinkage int sys_pipe(unsigned long * fildes)
-{
- int error;
- lock_kernel();
- error = verify_area(VERIFY_WRITE,fildes,8);
- if (error)
- goto out;
- error = do_pipe(fildes);
-out:
- unlock_kernel();
- return error;
+void
+check_bugs(void)
+{
}
-asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
- int flags, int fd, off_t offset)
+asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
{
- struct file * file = NULL;
- int ret = -EBADF;
+ printk("sys_ioperm()\n");
+ return -EIO;
+}
+int sys_iopl(int a1, int a2, int a3, int a4)
+{
lock_kernel();
- if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
- }
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- ret = do_mmap(file, addr, len, prot, flags, offset);
-out:
+ printk( "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
unlock_kernel();
- return ret;
+ return (ENOSYS);
}
-/*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
- */
-asmlinkage int old_mmap(unsigned long *buffer)
+int sys_vm86(int a1, int a2, int a3, int a4)
{
- int error;
- unsigned long flags;
- long a,b,c,d,e;
- struct file * file = NULL;
-
lock_kernel();
- error = verify_area(VERIFY_READ, buffer, 6*sizeof(long));
- if (error)
- goto out;
- get_user(flags,buffer+3);
- if (!(flags & MAP_ANONYMOUS)) {
- unsigned long fd;
- get_user(fd,buffer+4);
- error = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- goto out;
- }
- flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- error = -EFAULT;
- if ( get_user(a,buffer) || get_user(b,buffer+1) ||
- get_user(c,buffer+2)||get_user(d,buffer+5) )
- goto out;
- error = do_mmap(file,a,b,c, flags, d);
-out:
+ printk( "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
unlock_kernel();
- return error;
+ return (ENOSYS);
}
-extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
-
-asmlinkage int old_select(unsigned long *buffer)
+int sys_modify_ldt(int a1, int a2, int a3, int a4)
{
- int n;
- fd_set *inp;
- fd_set *outp;
- fd_set *exp;
- struct timeval *tvp;
-
lock_kernel();
- n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long));
- if (n)
- goto out;
- get_user(n,buffer);
- get_user(inp,buffer+1);
- get_user(outp,buffer+2);
- get_user(exp,buffer+3);
- get_user(tvp,buffer+4);
- n = sys_select(n, inp, outp, exp, tvp);
-out:
+ printk( "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
unlock_kernel();
- return n;
+ return (ENOSYS);
}
-#if 0
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
@@ -145,12 +86,12 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
ret = -EINVAL;
if (!ptr)
goto out;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long))))
- goto out;
- fourth.__pad = (void *) get_fs_long(ptr);
+ ret = -EFAULT;
+ if (get_user(fourth.__pad, (void **) ptr))
+ goto out;
ret = sys_semctl (first, second, third, fourth);
goto out;
- }
+ }
default:
ret = -EINVAL;
goto out;
@@ -168,13 +109,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
ret = -EINVAL;
if (!ptr)
goto out;
- if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
- goto out;
- memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
- sizeof (tmp));
+ ret = -EFAULT;
+ if (copy_from_user(&tmp,(struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ goto out;
ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
goto out;
- }
+ }
case 1: default:
ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
goto out;
@@ -195,15 +136,12 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
- if ((ret = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
- goto out;
ret = sys_shmat (first, (char *) ptr, second, &raddr);
if (ret)
goto out;
- put_fs_long (raddr, (ulong *) third);
- ret = 0;
+ ret = put_user (raddr, (ulong *) third);
goto out;
- }
+ }
case 1: /* iBCS2 emulator entry point */
ret = -EINVAL;
if (get_fs() != get_ds())
@@ -230,4 +168,81 @@ out:
unlock_kernel();
return ret;
}
+
+
+#ifndef CONFIG_MODULES
+void
+scsi_register_module(void)
+{
+ lock_kernel();
+ panic("scsi_register_module");
+ unlock_kernel();
+}
+
+void
+scsi_unregister_module(void)
+{
+ lock_kernel();
+ panic("scsi_unregister_module");
+ unlock_kernel();
+}
#endif
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long * fildes)
+{
+ int fd[2];
+ int error;
+
+ error = verify_area(VERIFY_WRITE,fildes,8);
+ if (error)
+ return error;
+ error = do_pipe(fd);
+ if (error)
+ return error;
+ put_user(fd[0],0+fildes);
+ put_user(fd[1],1+fildes);
+ return 0;
+}
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, off_t offset)
+{
+ struct file * file = NULL;
+ if (!(flags & MAP_ANONYMOUS)) {
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ return do_mmap(file, addr, len, prot, flags, offset);
+}
+
+extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+
+/*
+ * Due to some executables calling the wrong select we sometimes
+ * get wrong args. This determines how the args are being passed
+ * (a single ptr to them all args passed) then calls
+ * sys_select() with the appropriate args. -- Cort
+ */
+asmlinkage int
+ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
+{
+ int err;
+ if ( (unsigned long)n >= 4096 )
+ {
+ unsigned long *buffer = (unsigned long *)n;
+ if ( get_user(n, buffer) ||
+ get_user(inp,buffer+1) ||
+ get_user(outp,buffer+2) ||
+ get_user(exp,buffer+3) ||
+ get_user(tvp,buffer+4) )
+ return -EFAULT;
+ }
+ return sys_select(n, inp, outp, exp, tvp);
+}
diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
index cdcad8204..e69de29bb 100644
--- a/arch/ppc/kernel/time.c
+++ b/arch/ppc/kernel/time.c
@@ -1,465 +0,0 @@
-/*
- * linux/arch/i386/kernel/time.c
- *
- * Copyright (C) 1991, 1992, 1995 Linus Torvalds
- *
- * Adapted for PowerPC (PreP) by Gary Thomas
- *
- * This file contains the PC-specific time handling details:
- * reading the RTC at bootup, etc..
- * 1994-07-02 Alan Modra
- * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
- * 1995-03-26 Markus Kuhn
- * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
- * precision CMOS clock update
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/nvram.h>
-#include <asm/mc146818rtc.h>
-#include <asm/processor.h>
-
-#include <linux/timex.h>
-#include <linux/config.h>
-
-extern int isBeBox[];
-
-#define TIMER_IRQ 0
-
-/* Cycle counter value at the previous timer interrupt.. */
-static unsigned long long last_timer_cc = 0;
-static unsigned long long init_timer_cc = 0;
-
-static inline int CMOS_READ(int addr)
-{
- outb(addr>>8, NVRAM_AS1);
- outb(addr, NVRAM_AS0);
- return (inb(NVRAM_DATA));
-}
-
-static inline int CMOS_WRITE(int addr, int val)
-{
- outb(addr>>8, NVRAM_AS1);
- outb(addr, NVRAM_AS0);
- return (outb(val, NVRAM_DATA));
-}
-
-/* This function must be called with interrupts disabled
- * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
- *
- * However, the pc-audio speaker driver changes the divisor so that
- * it gets interrupted rather more often - it loads 64 into the
- * counter rather than 11932! This has an adverse impact on
- * do_gettimeoffset() -- it stops working! What is also not
- * good is that the interval that our timer function gets called
- * is no longer 10.0002 ms, but 9.9767 ms. To get around this
- * would require using a different timing source. Maybe someone
- * could use the RTC - I know that this can interrupt at frequencies
- * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
- * it so that at startup, the timer code in sched.c would select
- * using either the RTC or the 8253 timer. The decision would be
- * based on whether there was any other device around that needed
- * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
- * and then do some jiggery to have a version of do_timer that
- * advanced the clock by 1/1024 s. Every time that reached over 1/100
- * of a second, then do all the old code. If the time was kept correct
- * then do_gettimeoffset could just return 0 - there is no low order
- * divider that can be accessed.
- *
- * Ideally, you would be able to use the RTC for the speaker driver,
- * but it appears that the speaker driver really needs interrupt more
- * often than every 120 us or so.
- *
- * Anyway, this needs more thought.... pjsg (1993-08-28)
- *
- * If you are really that interested, you should be reading
- * comp.protocols.time.ntp!
- */
-
-#define TICK_SIZE tick
-
-static unsigned long do_slow_gettimeoffset(void)
-{
- int count;
- unsigned long offset = 0;
-
- /* timer count may underflow right here */
- outb_p(0x00, 0x43); /* latch the count ASAP */
- count = inb_p(0x40); /* read the latched count */
- count |= inb(0x40) << 8;
- /* we know probability of underflow is always MUCH less than 1% */
- if (count > (LATCH - LATCH/100)) {
- /* check for pending timer interrupt */
- outb_p(0x0a, 0x20);
- if (inb(0x20) & 1)
- offset = TICK_SIZE;
- }
- count = ((LATCH-1) - count) * TICK_SIZE;
- count = (count + LATCH/2) / LATCH;
- return offset + count;
-}
-
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-
-/*
- * This version of gettimeofday has near microsecond resolution.
- */
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
-
- save_flags(flags);
- cli();
- *tv = xtime;
- tv->tv_usec += do_gettimeoffset();
- if (tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
- restore_flags(flags);
-}
-
-void do_settimeofday(struct timeval *tv)
-{
- cli();
- /* This is revolting. We need to set the xtime.tv_usec
- * correctly. However, the value in this location is
- * is value at the last tick.
- * Discover what correction gettimeofday
- * would have done, and then undo it!
- */
- tv->tv_usec -= do_gettimeoffset();
-
- if (tv->tv_usec < 0) {
- tv->tv_usec += 1000000;
- tv->tv_sec--;
- }
-
- xtime = *tv;
- time_state = TIME_BAD;
- time_maxerror = 0x70000000;
- time_esterror = 0x70000000;
- set_rtc(xtime.tv_sec);
- sti();
-}
-
-static int month_days[12] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-#define FEBRUARY 2
-#define STARTOFTIME 1970
-#define SECDAY 86400L
-#define SECYR (SECDAY * 365)
-#define leapyear(year) ((year) % 4 == 0)
-#define days_in_year(a) (leapyear(a) ? 366 : 365)
-#define days_in_month(a) (month_days[(a) - 1])
-
-struct _tm
-{
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_day;
- int tm_month;
- int tm_year;
-};
-
-static _to_tm(int tim, struct _tm * tm)
-{
- register int i;
- register long hms, day;
-
- day = tim / SECDAY;
- hms = tim % SECDAY;
-
- /* Hours, minutes, seconds are easy */
- tm->tm_hour = hms / 3600;
- tm->tm_min = (hms % 3600) / 60;
- tm->tm_sec = (hms % 3600) % 60;
-
- /* Number of years in days */
- for (i = STARTOFTIME; day >= days_in_year(i); i++)
- day -= days_in_year(i);
- tm->tm_year = i;
-
- /* Number of months in days left */
- if (leapyear(tm->tm_year))
- days_in_month(FEBRUARY) = 29;
- for (i = 1; day >= days_in_month(i); i++)
- day -= days_in_month(i);
- days_in_month(FEBRUARY) = 28;
- tm->tm_month = i;
-
- /* Days are what is left over (+1) from all that. */
- tm->tm_day = day + 1;
-}
-
-/*
- * Set the time into the CMOS
- */
-static void set_rtc(unsigned long nowtime)
-{
- int retval = 0;
- struct _tm tm;
- unsigned char save_control, save_freq_select;
-
- /*if (_Processor != _PROC_IBM) return;*/
-
- _to_tm(nowtime, &tm);
-
- /* tell the clock it's being set */
- save_control = CMOS_MCRTC_READ(MCRTC_CONTROL);
- CMOS_MCRTC_WRITE((save_control|MCRTC_SET), MCRTC_CONTROL);
- /* stop and reset prescaler */
- save_freq_select = CMOS_MCRTC_READ(MCRTC_FREQ_SELECT);
- CMOS_MCRTC_WRITE((save_freq_select|MCRTC_DIV_RESET2), MCRTC_FREQ_SELECT);
-
- printk("Set RTC H:M:S M/D/Y %d:%02d:%02d %d/%d/%d\n",
- tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_month, tm.tm_day, tm.tm_year);
- if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD) {
- BIN_TO_BCD(tm.tm_sec);
- BIN_TO_BCD(tm.tm_min);
- BIN_TO_BCD(tm.tm_hour);
- BIN_TO_BCD(tm.tm_month);
- BIN_TO_BCD(tm.tm_day);
- BIN_TO_BCD(tm.tm_year);
- }
-
- CMOS_MCRTC_WRITE(tm.tm_sec, MCRTC_SECONDS);
- CMOS_MCRTC_WRITE(tm.tm_min, MCRTC_MINUTES);
- CMOS_MCRTC_WRITE(tm.tm_hour, MCRTC_HOURS);
- CMOS_MCRTC_WRITE(tm.tm_month, MCRTC_MONTH);
- CMOS_MCRTC_WRITE(tm.tm_day, MCRTC_MINUTES);
- CMOS_MCRTC_WRITE(tm.tm_year - 1900, MCRTC_MINUTES);
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_MCRTC_WRITE(save_control, MCRTC_CONTROL);
- CMOS_MCRTC_WRITE(save_freq_select, MCRTC_FREQ_SELECT);
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- */
-static int set_rtc_mmss(unsigned long nowtime)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
- unsigned char save_control, save_freq_select;
-
-#ifdef __powerpc__
-printk("%s: %d - set TOD\n", __FILE__, __LINE__);
-return (-1); /* Not implemented */
-#else
-
-printk("%s: %d - set TOD\n", __FILE__, __LINE__);
- save_control = CMOS_MCRTC_READ(MCRTC_CONTROL); /* tell the clock it's being set */
- CMOS_MCRTC_WRITE((save_control|MCRTC_SET), MCRTC_CONTROL);
-
- save_freq_select = CMOS_MCRTC_READ(MCRTC_FREQ_SELECT); /* stop and reset prescaler */
- CMOS_MCRTC_WRITE((save_freq_select|MCRTC_DIV_RESET2), MCRTC_FREQ_SELECT);
-
- cmos_minutes = CMOS_MCRTC_READ(MCRTC_MINUTES);
- if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD)
- BCD_TO_BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- if (!(save_control & MCRTC_DM_BINARY) || MCRTC_ALWAYS_BCD) {
- BIN_TO_BCD(real_seconds);
- BIN_TO_BCD(real_minutes);
- }
- CMOS_MCRTC_WRITE(real_seconds,MCRTC_SECONDS);
- CMOS_MCRTC_WRITE(real_minutes,MCRTC_MINUTES);
- } else
- retval = -1;
-
- /* The following flags have to be released exactly in this order,
- * otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and quartz) will not reset the oscillator and will not
- * update precisely 500 ms later. You won't find this mentioned in
- * the Dallas Semiconductor data sheets, but who believes data
- * sheets anyway ... -- Markus Kuhn
- */
- CMOS_MCRTC_WRITE(save_control, MCRTC_CONTROL);
- CMOS_MCRTC_WRITE(save_freq_select, MCRTC_FREQ_SELECT);
-
- return retval;
-#endif
-}
-
-/* last time the cmos clock got updated */
-static long last_rtc_update = 0;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static inline void timer_interrupt(int irq, void *dev, struct pt_regs * regs)
-{
- static int timeints = 0;
-
- do_timer(regs);
-
- /*
- * If we have an externally synchronized Linux clock, then update
- * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
- * called as close as possible to 500 ms before the new second starts.
- */
- if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
- xtime.tv_usec > 500000 - (tick >> 1) &&
- xtime.tv_usec < 500000 + (tick >> 1))
- if (set_rtc_mmss(xtime.tv_sec) == 0)
- last_rtc_update = xtime.tv_sec;
- else
- last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-
-
- /* use hard disk LED as a heartbeat instead -- much more useful
- -- Cort */
- switch(timeints)
- {
- /* act like an actual heart beat -- ie thump-thump-pause... */
- case 0:
- case 20:
- hard_disk_LED(1);
- break;
- case 7:
- case 27:
- hard_disk_LED(0);
- break;
- case 100:
- timeints = -1;
- break;
- }
- timeints++;
-}
-
-/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
- * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
- * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
- *
- * [For the Julian calendar (which was used in Russia before 1917,
- * Britain & colonies before 1752, anywhere else before 1582,
- * and is still in use by some communities) leave out the
- * -year/100+year/400 terms, and add 10.]
- *
- * This algorithm was first published by Gauss (I think).
- *
- * WARNING: this function will overflow on 2106-02-07 06:28:16 on
- * machines were long is 32-bit! (However, as time_t is signed, we
- * will already get problems at other places on 2038-01-19 03:14:08)
- */
-static inline unsigned long mktime(unsigned int year, unsigned int mon,
- unsigned int day, unsigned int hour,
- unsigned int min, unsigned int sec)
-{
- if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
- mon += 12; /* Puts Feb last since it has leap day */
- year -= 1;
- }
- return (((
- (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
- year*365 - 719499
- )*24 + hour /* now have hours */
- )*60 + min /* now have minutes */
- )*60 + sec; /* finally seconds */
-}
-
-unsigned long get_cmos_time(void)
-{
- unsigned int year, mon, day, hour, min, sec;
- int i;
-
- if (_Processor == _PROC_IBM)
- {
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_MCRTC_READ(MCRTC_SECONDS);
- min = CMOS_MCRTC_READ(MCRTC_MINUTES);
- hour = CMOS_MCRTC_READ(MCRTC_HOURS);
- day = CMOS_MCRTC_READ(MCRTC_DAY_OF_MONTH);
- mon = CMOS_MCRTC_READ(MCRTC_MONTH);
- year = CMOS_MCRTC_READ(MCRTC_YEAR);
- } while (sec != CMOS_MCRTC_READ(MCRTC_SECONDS));
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- } else
- if (_Processor == _PROC_Be)
- {
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_MCRTC_READ(MCRTC_SECONDS);
- min = CMOS_MCRTC_READ(MCRTC_MINUTES);
- hour = CMOS_MCRTC_READ(MCRTC_HOURS);
- day = CMOS_MCRTC_READ(MCRTC_DAY_OF_MONTH);
- mon = CMOS_MCRTC_READ(MCRTC_MONTH);
- year = CMOS_MCRTC_READ(MCRTC_YEAR);
- } while (sec != CMOS_MCRTC_READ(MCRTC_SECONDS));
- } else
- { /* Motorola PowerStack etc. */
- do { /* Isn't this overkill ? UIP above should guarantee consistency */
- sec = CMOS_READ(RTC_SECONDS);
- min = CMOS_READ(RTC_MINUTES);
- hour = CMOS_READ(RTC_HOURS);
- day = CMOS_READ(RTC_DAY_OF_MONTH);
- mon = CMOS_READ(RTC_MONTH);
- year = CMOS_READ(RTC_YEAR);
- } while (sec != CMOS_READ(RTC_SECONDS));
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
- }
-#if 0
-printk("CMOS TOD - M/D/Y H:M:S = %d/%d/%d %d:%02d:%02d\n", mon, day, year, hour, min, sec);
-#endif
- if ((year += 1900) < 1970)
- year += 100;
- return mktime(year, mon, day, hour, min, sec);
-}
-
-void time_init(void)
-{
- void (*irq_handler)(int, struct pt_regs *);
- xtime.tv_sec = get_cmos_time();
- xtime.tv_usec = 0;
-
- /* If we have the CPU hardware time counters, use them */
- irq_handler = timer_interrupt;
- if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0)
- panic("Could not allocate timer IRQ!");
-}
-
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index a637e0acb..84ce1c5ca 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -20,14 +20,14 @@
#include <linux/malloc.h>
#include <linux/user.h>
#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
#include <asm/pgtable.h>
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/io.h>
-#include <asm/ppc_machine.h>
-
/*
* Trap & Exception support
*/
@@ -40,122 +40,98 @@ trap_init(void)
void
_exception(int signr, struct pt_regs *regs)
{
- /* dump_regs(regs);*/
- force_sig(signr, current);
- if (!user_mode(regs))
- {
- printk("Failure in kernel at PC: %x, MSR: %x\n", regs->nip, regs->msr);
- while (1) ;
- }
+ if (!user_mode(regs))
+ {
+ show_regs(regs);
+ print_backtrace(regs->gpr[1]);
+ panic("Exception in kernel pc %x signal %d",regs->nip,signr);
+ }
+ force_sig(signr, current);
}
MachineCheckException(struct pt_regs *regs)
{
- printk("Machine check at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);
- _exception(SIGSEGV, regs);
-}
-
-ProgramCheckException(struct pt_regs *regs)
-{
-#if 0
- printk("Program check at PC: %x[%x], SR: %x\n",
- regs->nip, va_to_phys(regs->nip), regs->msr);
- #endif
- if (current->flags & PF_PTRACED)
- {
- _exception(SIGTRAP, regs);
- } else
- {
- _exception(SIGILL, regs);
- }
+ if ( !user_mode(regs) )
+ {
+ printk("Machine check in kernel mode.\n");
+ printk("Caused by (from msr): ");
+ printk("regs %08x ",regs);
+ switch( regs->msr & 0x0000F000)
+ {
+ case (1<<12) :
+ printk("Machine check signal - probably due to mm fault\n"
+ "with mmu off\n");
+ break;
+ case (1<<13) :
+ printk("Transfer error ack signal\n");
+ break;
+ case (1<<14) :
+ printk("Data parity signal\n");
+ break;
+ case (1<<15) :
+ printk("Address parity signal\n");
+ break;
+ default:
+ printk("Unknown values in msr\n");
+ }
+ show_regs(regs);
+ print_backtrace(regs->gpr[1]);
+ panic("");
+ }
+ _exception(SIGSEGV, regs);
}
-SingleStepException(struct pt_regs *regs)
+void
+UnknownException(struct pt_regs *regs)
{
- regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
+ printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
_exception(SIGTRAP, regs);
}
-FloatingPointCheckException(struct pt_regs *regs)
+void
+InstructionBreakpoint(struct pt_regs *regs)
{
- /* if fpu already on -- then exception was generated by an error */
- if ( (unsigned long)(regs->msr) & (unsigned long)MSR_FP )
- {
- _exception(SIGFPE, regs);
- return 0;
- }
-
-#if 0
- printk("fpu off -- turning on: %s pc %x fpscr %x msr %x ksp %x r1 %x\n",
- current->comm,regs->nip,regs->fpcsr,regs->msr,regs,regs->gpr[1]);
+#ifdef CONFIG_XMON
+ if (xmon_iabr_match(regs))
+ return;
#endif
-
- /* if the fpu is off then turn it on and return */
- regs->msr |= MSR_FP;
- current->tss.fp_used++;
- /* tells return_from_int to restore fp regs since fp was turned on
- see head.S -- Cort */
- return MSR_FP;
+ _exception(SIGTRAP, regs);
}
-AlignmentException(struct pt_regs *regs)
+void
+RunModeException(struct pt_regs *regs)
{
-/* printk("Alignment error at PC: %x, SR: %x\n", regs->nip, regs->msr);
- dump_regs(regs);
- printk("Alignment error at PC: %x[%x], SR: %x\n", regs->nip, va_to_phys(regs->nip), regs->msr);*/
- _exception(SIGBUS, regs);
+ _exception(SIGTRAP, regs);
}
+ProgramCheckException(struct pt_regs *regs)
+{
+ if (current->flags & PF_PTRACED)
+ _exception(SIGTRAP, regs);
+ else
+ _exception(SIGILL, regs);
+}
-/* see CHECK_STACK macro in head.S for argument definitions */
-bad_stack(unsigned int r3, unsigned int r4, unsigned int r5, unsigned int r6)
+SingleStepException(struct pt_regs *regs)
{
- /* r6 (was r1) kernel stack pointer */
- /* r5 (was r2) kernel stack page */
- /* r4 kernel stack magic */
- /* r3 stack magic or ksp masked to page boundary */
- printk("bad_stack(): Kernel stack bad.\n");
- printk("ksp %x kpage %x stack magic %x r3 %x\n",
- r6,r5,r4,r3);
- printk("current: %s/%d\n",
- current->comm,current->pid);
- while(1);
+ regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
+ _exception(SIGTRAP, regs);
}
-dump_regs(struct pt_regs *regs)
+AlignmentException(struct pt_regs *regs)
{
- int i;
- printk("NIP: %08X, MSR: %08X, XER: %08X, LR: %08X, FRAME: %08X\n", regs->nip, regs->msr, regs->xer, regs->link, regs);
-#if 0
- printk("HASH = %08X/%08X, MISS = %08X/%08X, CMP = %08X/%08X\n", regs->hash1, regs->hash2, regs->imiss, regs->dmiss, regs->icmp, regs->dcmp);
-#endif
- printk("TASK = %x[%d] '%s'\n", current, current->pid, current->comm);
- for (i = 0; i < 32; i++)
- {
- if ((i % 8) == 0)
- {
- printk("GPR%02d: ", i);
- }
- printk("%08X ", regs->gpr[i]);
- if ((i % 8) == 7)
- {
- printk("\n");
- }
- }
-#if 0
- if (regs->nip >= 0x1000)
- dump_buf(regs->nip-32, 64);
- dump_buf((regs->nip&0x0FFFFFFF)|KERNELBASE, 32);
-#endif
+ _exception(SIGBUS, regs);
}
trace_syscall(struct pt_regs *regs)
{
static int count;
- printk("Task: %08X(%d), PC: %08X/%08X, Syscall: %3d, Result: %s%d\n", current, current->pid, regs->nip, regs->link, regs->gpr[0], regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
+ printk("Task: %08X(%d), PC: %08X/%08X, Syscall: %3d, Result: %s%d\n",
+ current, current->pid, regs->nip, regs->link, regs->gpr[0],
+ regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
if (++count == 20)
{
count = 0;
}
}
-
diff --git a/arch/ppc/kernel/usercpy.c b/arch/ppc/kernel/usercpy.c
index 7ef0f2280..e69de29bb 100644
--- a/arch/ppc/kernel/usercpy.c
+++ b/arch/ppc/kernel/usercpy.c
@@ -1,116 +0,0 @@
-#include <linux/types.h>
-#include <asm/string.h>
-#include <asm/errno.h>
-#include <linux/sched.h>
-
-/*
- * bad data accesses from these functions should be handled specially
- * since they are to user areas and may or may not be valid.
- * on error -EFAULT should be returned. -- Cort
- */
-int __copy_tofrom_user_failure(void)
-{
- current->tss.excount = 0;
- return -EFAULT;
-}
-
-int __copy_tofrom_user(unsigned long to, unsigned long from, int size)
-{
- /* setup exception handling stuff */
- current->tss.excount++;
- current->tss.expc = (unsigned long )__copy_tofrom_user_failure;
-
- if (memcpy( (void *)to, (void *)from, (size_t) size) == -EFAULT )
- {
- /* take down exception handler stuff */
- current->tss.excount = 0;
- return -EFAULT;
- }
- current->tss.excount = 0;
- return 0; /* successful return */
-}
-
-/* Just like strncpy except in the return value:
- *
- * -EFAULT if an exception occurs before the terminator is copied.
- * N if the buffer filled.
- *
- * Otherwise the length of the string is returned.
- */
-asmlinkage int __strncpy_from_user_failure(void)
-{
- current->tss.excount = 0;
- return -EFAULT;
-}
-
-int __strncpy_from_user(unsigned long dest, unsigned long src, int count)
-{
- int i = 0;
- /* setup exception handling stuff */
- current->tss.excount++;
- current->tss.expc = (unsigned long )__strncpy_from_user_failure;
-
- while ( i != count )
- {
- *(char *)(dest+i) = *(char *)(src+i);
- if ( *(char *)(src+i) == 0 )
- {
- return i;
- }
- i++;
- }
- *(char *)(dest+i) = (char)0;
- /* take down exception handler stuff */
- current->tss.excount = 0;
- return i;
-}
-
-int __clear_user_failure(void)
-{
- current->tss.excount = 0;
- return -EFAULT;
-}
-int __clear_user(unsigned long addr, int size)
-{
- /* setup exception handling stuff */
- current->tss.excount++;
- current->tss.expc = (unsigned long )__clear_user_failure;
-
- if ((int)memset((void *)addr,(int)0, (__kernel_size_t)size) == -EFAULT )
- {
- /* take down exception handler stuff */
- current->tss.excount = 0;
- return -EFAULT;
- }
- /* take down exception handler stuff */
- current->tss.excount = 0;
- return size;
-}
-
-/*
- * Return the length of the string including the NUL terminator
- * (strlen+1) or zero if an error occured.
- */
-size_t strlen_user_failure(void)
-{
- current->tss.excount = 0;
- return -EFAULT;
-}
-size_t strlen_user(char * s)
-{
- size_t i;
- /* setup exception handling stuff */
- current->tss.excount++;
- current->tss.expc = (unsigned long )strlen_user_failure;
-
- i = strlen(s)+1;
-
- if ( i == -EFAULT)
- return -EFAULT;
-
- /* take down exception handler stuff */
- current->tss.excount = 0;
-
- return(i);
-}
-
diff --git a/arch/ppc/ld.script b/arch/ppc/ld.script
index 319292840..ab5b070db 100644
--- a/arch/ppc/ld.script
+++ b/arch/ppc/ld.script
@@ -31,12 +31,16 @@ SECTIONS
.text :
{
*(.text)
- *(.rodata)
- *(.rodata1)
+ *(.fixup)
*(.got1)
}
_etext = .;
PROVIDE (etext = .);
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
@@ -45,31 +49,33 @@ SECTIONS
.data :
{
*(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt) *(.got)
+ *(.dynamic)
CONSTRUCTORS
}
- .data1 : { *(.data1) }
- .got : { *(.got.plt) *(.got) }
- .dynamic : { *(.dynamic) }
- /* We want the small data sections together, so single-instruction offsets
- can access them all, and initialized data all before uninitialized, so
- we can shorten the on-disk segment size. */
- .sdata : { *(.sdata) }
_edata = .;
+/*
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+*/
+ __bss_start = .; /* BSS */
PROVIDE (edata = .);
__bss_start = .;
- .sbss : { *(.sbss) *(.scommon) }
.bss :
{
+ *(.sbss) *(.scommon)
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
- /* These are needed for ELF backends which have not yet been
- converted to the new style linker. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- /* These must appear regardless of . */
}
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index baace0862..68b33f047 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -1,12 +1,38 @@
-#
-# Makefile for i386-specific library files..
-#
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+.s.o:
+ $(AS) $(ASFLAGS) -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+.S.s:
+ $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s
+.S.o:
+ $(CPP) $(CFLAGS) -D__ASSEMBLY__ $< -o $*.s
+ $(AS) $(ASFLAGS) -o $*.o $*.s
+ rm $*.s
+
+HOST_CC = gcc
L_TARGET = lib.o
-L_OBJS = checksum.o cksum_support.o
-CC = gcc -I$(TOPDIR)/include
+L_OBJS = checksum.o cksum_support.o string.o
${L_TARGET}: $(L_OBJS)
$(LD) -r -o ${L_TARGET} $(L_OBJS)
+
fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
+
+dep:
+ $(CPP) -M *.S *.c > .depend
+
+modules:
+
+dummy:
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/arch/ppc/mm/Makefile b/arch/ppc/mm/Makefile
index ac6ef0213..13aeab6ca 100644
--- a/arch/ppc/mm/Makefile
+++ b/arch/ppc/mm/Makefile
@@ -14,7 +14,7 @@
.c.s:
$(CC) $(CFLAGS) -S $<
-OBJS = fault.o init.o
+OBJS = fault.o init.o extable.o
mm.o: $(OBJS)
$(LD) -r -o mm.o $(OBJS)
@@ -22,9 +22,9 @@ mm.o: $(OBJS)
modules:
dep:
- $(CPP) -M *.c > .depend
-
+
fastdep:
+ $(TOPDIR)/scripts/mkdep *.[Sch] > .depend
#
# include a dependency file if one exists
diff --git a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
index 7104d6bbb..fea722780 100644
--- a/arch/ppc/mm/fault.c
+++ b/arch/ppc/mm/fault.c
@@ -1,9 +1,14 @@
/*
- * ARCH/ppc/mm/fault.c
+ * arch/ppc/mm/fault.c
*
* Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
* Ported to PPC by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified by Cort Dougan and Paul Mackerras.
+ *
+ * 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/config.h>
@@ -17,132 +22,151 @@
#include <linux/ptrace.h>
#include <linux/mman.h>
#include <linux/mm.h>
+#include <linux/interrupt.h>
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
-extern void die_if_kernel(char *, struct pt_regs *, long);
-extern void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
-void new_page_fault(unsigned long address, unsigned long code, unsigned long text,
- struct pt_regs *regs);
-
+#ifdef CONFIG_PMAC
+extern void (*xmon_fault_handler)(void);
+#endif
-#undef SHOW_FAULTS
-#undef NOISY_INSTRFAULT
-#undef NOISY_DATAFAULT
+/* the linux norm for the function name is show_regs() so
+ make it call dump_regs() on the mac -- Cort */
+#ifdef CONFIG_PMAC
+#define show_regs dump_regs
+#endif
-unsigned int probingmem = 0;
-#define NEWMM 1
+extern void die_if_kernel(char *, struct pt_regs *, long);
+void bad_page_fault(struct pt_regs *, unsigned long);
+void do_page_fault(struct pt_regs *, unsigned long, unsigned long);
+void print_pte(struct _PTE);
-void new_page_fault(unsigned long address, unsigned long ppc_code,
- unsigned long text, struct pt_regs *regs)
+void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code)
{
- struct vm_area_struct * vma;
- struct mm_struct *mm = current->mm;
-
- int intel_code = 0;
- pgd_t *dir;
- pmd_t *pmd;
- pte_t *pte;
-
- /*
- * bit 0 == 0 means no page found, 1 means protection fault
- * bit 1 == 0 means read, 1 means write
- * bit 2 == 0 means kernel, 1 means user-mode
- */
- if (user_mode(regs)) intel_code |= 0x04;
- if (!text && (ppc_code & 0x02000000)) intel_code |= 0x02; /* Load/store */
- if (!text && (ppc_code & 0x08000000))
- {
- intel_code |= 0x01; /* prot viol */
- goto do_page;
- }
-
- dir = pgd_offset(mm, address & PAGE_MASK);
- if (dir)
- {
- pmd = pmd_offset(dir, address & PAGE_MASK);
- if (pmd && pmd_present(*pmd))
- {
- pte = pte_offset(pmd, address & PAGE_MASK);
- if (pte && pte_present(*pte))
- {
- MMU_hash_page(&current->tss, address & PAGE_MASK, pte);
- return;
- }
- }
- }
-
+ struct task_struct *tsk = current;
+ extern unsigned _end[];
+ struct vm_area_struct * vma;
+ struct mm_struct *mm = current->mm;
+ pgd_t *dir;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ /*printk("do_page_fault() %s/%d addr %x nip %x regs %x error %x\n",
+ current->comm,current->pid,address,regs->nip,regs,error_code);*/
+#ifdef CONFIG_PMAC
+ if (xmon_fault_handler && regs->trap == 0x300) {
+ xmon_fault_handler();
+ return;
+ }
+#endif
+ if (in_interrupt()) {
+ static int complained;
+ if (complained < 20) {
+ ++complained;
+ printk("page fault in interrupt handler, addr=%lx\n",
+ address);
+ show_regs(regs);
+ }
+ }
+ if (current == NULL)
+ goto bad_area;
+
do_page:
- down(&mm->mmap_sem);
- vma = find_vma(current->mm, address);
- if (!vma)
- goto bad_area;
- if (vma->vm_start <= address)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
- if (expand_stack(vma, address))
- goto bad_area;
+ down(&mm->mmap_sem);
+ vma = find_vma(tsk->mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, address))
+ goto bad_area;
good_area:
- /* a write */
- if (intel_code & 2) {
- if (!(vma->vm_flags & VM_WRITE))
- {
- goto bad_area;
- }
- /* a read */
- } else {
- /* protection fault */
- if (intel_code & 1)
- {
- printk("prot fault\n");
- goto bad_area;
- }
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- {
- printk("no read or exec\n");
- goto bad_area;
- }
- }
- handle_mm_fault(vma, address, intel_code & 2);
- up(&mm->mmap_sem); flush_page(address); /* Flush & Invalidate cache - note: address is OK now */
- return;
+ if (error_code & 0xb5700000)
+ /* an error such as lwarx to I/O controller space,
+ address matching DABR, eciwx, etc. */
+ goto bad_area;
+
+ /* a write */
+ if (error_code & 0x02000000) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ /* a read */
+ } else {
+ /* protection fault */
+ if ( error_code & 0x08000000 )
+ goto bad_area;
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+ handle_mm_fault(current, vma, address, error_code & 0x02000000);
+ up(&mm->mmap_sem);
+ /*printk("do_page_fault() return %s/%d addr %x msr %x\n",
+ current->comm,current->pid,address,regs->msr);*/
+ /* not needed since flush_page_to_ram() works */
+#if 0
+ flush_page(address);
+#endif
+ return;
bad_area:
- up(&mm->mmap_sem);
+ up(&current->mm->mmap_sem);
+ bad_page_fault(regs, address);
+}
+
+
+void
+bad_page_fault(struct pt_regs *regs, unsigned long address)
+{
+ extern unsigned int probingmem;
+ struct task_struct *tsk = current;
+ unsigned long fixup;
+
+
+ /* Are we prepared to handle this fault? */
+ if ((fixup = search_exception_table(regs->nip)) != 0) {
+ if ( user_mode(regs) )
+ printk("Exception from user mode\n");
+#if 0
+ printk(KERN_DEBUG "Exception at %lx (%lx)\n", regs->nip, fixup);
+#endif
+ regs->nip = fixup;
+ return;
+ }
- /* Did we have an exception handler installed? */
- if(current->tss.excount != 0) {
- if(user_mode(regs)) {
- printk("Exception signalled from user mode!\n");
- } else {
-#if 0
- printk("Exception from kernel mode. pc %x expc %x count %d\n",
- regs->nip,current->tss.expc,current->tss.excount);
-#endif
- current->tss.excount = 0;
- regs->gpr[3] = -EFAULT;
- regs->nip = current->tss.expc;
- return;
- }
- }
+ if ( user_mode(regs) )
+ {
+ force_sig(SIGSEGV, tsk);
+ return;
+ }
- if (user_mode(regs))
- {
- force_sig(SIGSEGV, current);
- return;
- }
- panic("KERNEL access of bad area PC %x address %x vm_flags %x\n",
- regs->nip,address,vma->vm_flags);
+bad_kernel_access:
+ /* make sure it's not a bootup probe test */
+ if ( probingmem )
+ {
+ probingmem = 0;
+ return;
+ }
+ /* kernel has accessed a bad area */
+ show_regs(regs);
+ print_backtrace( regs->gpr[1] );
+#ifdef CONFIG_PMAC
+ xmon(regs);
+#endif
+ panic("kernel access of bad area\n pc %x address %X tsk %s/%d",
+ regs->nip,address,tsk->comm,tsk->pid);
}
-va_to_phys(unsigned long address)
+unsigned long va_to_phys(unsigned long address)
{
pgd_t *dir;
pmd_t *pmd;
pte_t *pte;
+
dir = pgd_offset(current->mm, address & PAGE_MASK);
if (dir)
{
@@ -165,8 +189,28 @@ va_to_phys(unsigned long address)
return (0);
}
-inline void
-update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t _pte)
+void print_pte(struct _PTE p)
{
- MMU_hash_page(&current->tss, address & PAGE_MASK, (pte *)&_pte);
+ printk(
+"%08x %08x vsid: %06x h: %01x api: %02x rpn: %05x rcwimg: %d%d%d%d%d%d pp: %02x\n",
+ *((unsigned long *)(&p)), *((long *)&p+1),
+ p.vsid, p.h, p.api, p.rpn,
+ p.r,p.c,p.w,p.i,p.m,p.g,p.pp);
+}
+
+/*
+ * Search the hw hash table for a mapping to the given physical
+ * address. -- Cort
+ */
+unsigned long htab_phys_to_va(unsigned long address)
+{
+ extern PTE *Hash, *Hash_end;
+ PTE *ptr;
+
+ for ( ptr = Hash ; ptr < Hash_end ; ptr++ )
+ {
+ if ( ptr->rpn == (address>>12) )
+ printk("phys %08X -> va ???\n",
+ address);
+ }
}
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index ee2381dba..d46975996 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -1,9 +1,21 @@
/*
* arch/ppc/mm/init.c
*
- * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
- * Ported to PPC by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * PowerPC version
+ * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ * Modifications by Paul Mackerras (PowerMac) (paulus@cs.anu.edu.au)
+ * and Cort Dougan (PReP) (cort@cs.nmt.edu)
+ * Copyright (C) 1996 Paul Mackerras
+ *
+ * Derived from "arch/i386/mm/init.c"
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ *
+ * 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/config.h>
@@ -18,57 +30,354 @@
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/swap.h>
+#include <linux/stddef.h>
+#ifdef CONFIG_PMAC
+#include <asm/prom.h>
+#endif
+#include <asm/io.h>
+#include <asm/mmu_context.h>
#include <asm/pgtable.h>
+#include <asm/mmu.h>
+#ifdef CONFIG_PREP
#include <asm/residual.h>
+#endif
-extern pgd_t swapper_pg_dir[1024];
-extern unsigned long empty_zero_page[1024];
+int next_mmu_context;
+extern pgd_t swapper_pg_dir[];
+extern char _start[], _end[];
+extern char etext[], _stext[];
+/* References to section boundaries */
+extern char __init_begin, __init_end;
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
-void flush_hash_table(void);
+extern unsigned long *find_end_of_memory(void);
-#undef HASHSTATS
+#undef MAP_RAM_WITH_SEGREGS 1
-unsigned long _SDR1; /* Hardware SDR1 image */
-PTE *Hash;
-int Hash_size, Hash_mask;
+#ifdef CONFIG_PMAC
+void *find_mem_piece(unsigned, unsigned);
+static void mapin_ram(void);
+static void inherit_prom_translations(void);
+#endif
+#ifdef CONFIG_PREP
+inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va);
+int inline MMU_hash_page(struct task_struct *,unsigned long,pte *);
+#endif
+
+static void hash_init(void);
+static void *MMU_get_page(void);
+void map_page(struct thread_struct *, unsigned long va,
+ unsigned long pa, int flags);
+
+PTE *Hash, *Hash_end;
+unsigned long Hash_size, Hash_mask;
unsigned long *end_of_DRAM;
-int cache_is_copyback = 1;
-int kernel_pages_are_copyback = 1;
-/* Note: these need to be in 'data' so they live over the boot */
-unsigned char *BeBox_IO_page = 0;
-unsigned long isBeBox[2] = {0, 0};
+int mem_init_done;
+#ifdef CONFIG_PREP
#ifdef HASHSTATS
-extern unsigned long *hashhits;
-#endif
-
+extern unsigned long evicts;
+#endif /* HASHSTATS */
+/*
+ * these are used to setup the initial page tables
+ * They can waste up to an entire page since the
+ * I'll fix this shortly -- Cort
+ */
+#define MAX_MMU_PAGES 16
+unsigned int probingmem = 0;
+unsigned int mmu_pages_count = 0;
+char mmu_pages[(MAX_MMU_PAGES+1)*PAGE_SIZE];
+unsigned long _TotalMemory;
+#endif /* CONFIG_PREP */
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+unsigned long empty_bad_page_table;
pte_t * __bad_pagetable(void)
{
- panic("__bad_pagetable");
+ memset((void *)empty_bad_page_table, 0, PAGE_SIZE);
+ return (pte_t *) empty_bad_page_table;
}
+unsigned long empty_bad_page;
+
pte_t __bad_page(void)
{
- panic("__bad_page");
+ memset((void *)empty_bad_page, 0, PAGE_SIZE);
+ return pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
+}
+
+#ifdef CONFIG_PMAC
+#define MAX_MEM_REGIONS 32
+phandle memory_pkg;
+
+struct mem_pieces {
+ int n_regions;
+ struct reg_property regions[MAX_MEM_REGIONS];
+};
+
+struct mem_pieces phys_mem;
+struct mem_pieces phys_avail;
+struct mem_pieces prom_mem;
+
+static void get_mem_prop(char *, struct mem_pieces *);
+static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int);
+static void print_mem_pieces(struct mem_pieces *);
+
+unsigned long avail_start;
+int prom_trashed;
+
+/*
+ * Read in a property describing some pieces of memory.
+ */
+static void
+get_mem_prop(char *name, struct mem_pieces *mp)
+{
+ int s, i;
+
+ s = (int) call_prom("getprop", 4, 1, memory_pkg, name,
+ mp->regions, sizeof(mp->regions));
+ if (s < sizeof(mp->regions[0])) {
+ printk("getprop /memory %s returned %d\n", name, s);
+ abort();
+ }
+ mp->n_regions = s / sizeof(mp->regions[0]);
+
+ /*
+ * Make sure the pieces are sorted.
+ */
+ for (i = 1; i < mp->n_regions; ++i) {
+ unsigned long a, s;
+ int j;
+
+ a = mp->regions[i].address;
+ s = mp->regions[i].size;
+ for (j = i - 1; j >= 0; --j) {
+ if (a >= mp->regions[j].address)
+ break;
+ mp->regions[j+1] = mp->regions[j];
+ }
+ mp->regions[j+1].address = a;
+ mp->regions[j+1].size = s;
+ }
+}
+
+/*
+ * Remove some memory from an array of pieces
+ */
+static void
+remove_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size,
+ int must_exist)
+{
+ int i, j;
+ unsigned end, rs, re;
+ struct reg_property *rp;
+
+ end = start + size;
+ for (i = 0, rp = mp->regions; i < mp->n_regions; ++i, ++rp) {
+ if (end > rp->address && start < rp->address + rp->size)
+ break;
+ }
+ if (i >= mp->n_regions) {
+ if (must_exist)
+ printk("remove_mem_piece: [%x,%x) not in any region\n",
+ start, end);
+ return;
+ }
+ for (; i < mp->n_regions && end > rp->address; ++i, ++rp) {
+ rs = rp->address;
+ re = rs + rp->size;
+ if (must_exist && (start < rs || end > re)) {
+ printk("remove_mem_piece: bad overlap [%x,%x) with",
+ start, end);
+ print_mem_pieces(mp);
+ must_exist = 0;
+ }
+ if (start > rs) {
+ rp->size = start - rs;
+ if (end < re) {
+ /* need to split this entry */
+ if (mp->n_regions >= MAX_MEM_REGIONS)
+ panic("eek... mem_pieces overflow");
+ for (j = mp->n_regions; j > i + 1; --j)
+ mp->regions[j] = mp->regions[j-1];
+ ++mp->n_regions;
+ rp[1].address = end;
+ rp[1].size = re - end;
+ }
+ } else {
+ if (end < re) {
+ rp->address = end;
+ rp->size = re - end;
+ } else {
+ /* need to delete this entry */
+ for (j = i; j < mp->n_regions - 1; ++j)
+ mp->regions[j] = mp->regions[j+1];
+ --mp->n_regions;
+ --i;
+ --rp;
+ }
+ }
+ }
+}
+
+static void
+print_mem_pieces(struct mem_pieces *mp)
+{
+ int i;
+
+ for (i = 0; i < mp->n_regions; ++i)
+ printk(" [%x, %x)", mp->regions[i].address,
+ mp->regions[i].address + mp->regions[i].size);
+ printk("\n");
+}
+
+void *
+find_mem_piece(unsigned size, unsigned align)
+{
+ int i;
+ unsigned a, e;
+ struct mem_pieces *mp = &phys_avail;
+
+ for (i = 0; i < mp->n_regions; ++i) {
+ a = mp->regions[i].address;
+ e = a + mp->regions[i].size;
+ a = (a + align - 1) & -align;
+ if (a + size <= e) {
+ remove_mem_piece(mp, a, size, 1);
+ return __va(a);
+ }
+ }
+ printk("Couldn't find %u bytes at %u alignment\n", size, align);
+ abort();
+ return NULL;
+}
+
+/*
+ * Collect information about RAM and which pieces are already in use.
+ * At this point, we have the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long *find_end_of_memory(void)
+{
+ unsigned long a, total;
+ unsigned long h, kstart, ksize;
+ extern char _stext[], _end[];
+ int i;
+
+ memory_pkg = call_prom("finddevice", 1, 1, "/memory");
+ if (memory_pkg == (void *) -1)
+ panic("can't find memory package");
+
+ /*
+ * Find out where physical memory is, and check that it
+ * starts at 0 and is contiguous. It seems that RAM is
+ * always physically contiguous on Power Macintoshes,
+ * because MacOS can't cope if it isn't.
+ */
+ get_mem_prop("reg", &phys_mem);
+ if (phys_mem.n_regions == 0)
+ panic("No RAM??");
+ a = phys_mem.regions[0].address;
+ if (a != 0)
+ panic("RAM doesn't start at physical address 0");
+ total = phys_mem.regions[0].size;
+ for (i = 1; i < phys_mem.n_regions; ++i) {
+ a = phys_mem.regions[i].address;
+ if (a != total) {
+ printk("RAM starting at 0x%lx is not contiguous\n", a);
+ printk("Using RAM from 0 to 0x%lx\n", total-1);
+ phys_mem.n_regions = i;
+ break;
+ }
+ total += phys_mem.regions[i].size;
+ }
+
+ /* record which bits the prom is using */
+ get_mem_prop("available", &phys_avail);
+ prom_mem = phys_mem;
+ for (i = 0; i < phys_avail.n_regions; ++i)
+ remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
+ phys_avail.regions[i].size, 1);
+
+ /*
+ * phys_avail records memory we can use now.
+ * prom_mem records memory allocated by the prom that we
+ * don't want to use now, but we'll reclaim later.
+ * Make sure the kernel text/data/bss is in neither.
+ */
+ kstart = __pa(_stext); /* should be 0 */
+ ksize = PAGE_ALIGN(_end - _stext);
+ remove_mem_piece(&phys_avail, kstart, ksize, 0);
+ remove_mem_piece(&prom_mem, kstart, ksize, 0);
+
+ /*
+ * Allow 64k of hash table for every 16MB of memory,
+ * up to a maximum of 2MB.
+ */
+ for (h = 64<<10; h < total / 256 && h < 2<<20; h *= 2)
+ ;
+ Hash_size = h;
+ Hash_mask = (h >> 6) - 1;
+
+ /* Find some memory for the hash table. */
+ Hash = find_mem_piece(Hash_size, Hash_size);
+ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
+ total >> 20, Hash_size >> 10, Hash);
+
+ return __va(total);
+}
+
+/*
+ * Find some memory for setup_arch to return.
+ * We use the last chunk of available memory as the area
+ * that setup_arch returns, making sure that there are at
+ * least 32 pages unused before this for MMU_get_page to use.
+ */
+unsigned long find_available_memory(void)
+{
+ int i;
+ unsigned long a, free;
+ unsigned long start, end;
+
+ free = 0;
+ for (i = 0; i < phys_avail.n_regions - 1; ++i) {
+ start = phys_avail.regions[i].address;
+ end = start + phys_avail.regions[i].size;
+ free += (end & PAGE_MASK) - PAGE_ALIGN(start);
+ }
+ a = PAGE_ALIGN(phys_avail.regions[i].address);
+ if (free < 32 * PAGE_SIZE)
+ a += 32 * PAGE_SIZE - free;
+ avail_start = (unsigned long) __va(a);
+ return avail_start;
}
+#endif /* CONFIG_PMAC */
void show_mem(void)
{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0;
struct task_struct *p;
- unsigned long i,free = 0,total = 0,reserved = 0;
- unsigned long shared = 0;
- PTE *ptr;
- unsigned long full = 0, overflow = 0;
- unsigned int ti;
printk("Mem-info:\n");
show_free_areas();
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
- i = MAP_NR(high_memory);
+ i = max_mapnr;
while (i-- > 0) {
total++;
if (PageReserved(mem_map+i))
@@ -78,105 +387,185 @@ void show_mem(void)
else
shared += atomic_read(&mem_map[i].count) - 1;
}
- printk("%lu pages of RAM\n",total);
- printk("%lu free pages\n",free);
- printk("%lu reserved pages\n",reserved);
- printk("%lu pages shared\n",shared);
+ printk("%d pages of RAM\n",total);
+ printk("%d free pages\n",free);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
#endif
-#ifdef HASHSTATS
- printk("Hash Hits %u entries (buckets)\n",(Hash_size/sizeof(struct _PTE))/8);
- for ( i = 0; i < (Hash_size/sizeof(struct _PTE))/8; i++ ) {
- if ( hashhits[i] >= 20 )
- printk("[%lu] \t %lu\n", i,hashhits[i]);
- }
-#endif
-
- for ( ptr = Hash ; ptr <= Hash+Hash_size ; ptr++) {
- if (ptr->v) {
- full++;
- if (ptr->h == 1)
- overflow++;
- }
- }
- printk("Hash Table: %dkB Buckets: %dk PTEs: %d/%d (%%%d full) %d overflowed\n",
- Hash_size>>10, (Hash_size/(sizeof(PTE)*8)) >> 10,
- full,Hash_size/sizeof(PTE),
- (full*100)/(Hash_size/sizeof(PTE)),
- overflow);
- printk(" Task context vsid0\n");
- read_lock(&tasklist_lock);
- for_each_task(p) {
- printk("%5d %8x %8x\n",
- p->pid,p->mm->context,
- ((SEGREG *)p->tss.segs)[0].vsid);
+ printk("%-8s %3s %3s %8s %8s %8s %9s %8s\n", "Process", "Pid", "Cnt",
+ "Ctx", "Ctx<<4", "Last Sys", "pc", "task");
+ for_each_task(p)
+ {
+ printk("%-8.8s %3d %3d %8d %8d %8d %c%08x %08x",
+ p->comm,p->pid,
+ p->mm->count,p->mm->context,
+ p->mm->context<<4, p->tss.last_syscall,
+ user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
+ p);
+ if ( p == current )
+ printk(" current");
+ printk("\n");
}
- read_unlock(&tasklist_lock);
}
extern unsigned long free_area_init(unsigned long, unsigned long);
+/*
+ * paging_init() sets up the page tables - in fact we've already done this.
+ */
unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
{
- return free_area_init(start_mem, end_mem);
+ /*
+ * Grab some memory for bad_page and bad_pagetable to use.
+ */
+ empty_bad_page = start_mem;
+ empty_bad_page_table = start_mem + PAGE_SIZE;
+ start_mem += 2 * PAGE_SIZE;
+
+ /* note: free_area_init uses its second argument
+ to size the mem_map array. */
+ start_mem = free_area_init(start_mem, end_mem);
+ return start_mem;
}
void mem_init(unsigned long start_mem, unsigned long end_mem)
{
- int codepages = 0;
- int datapages = 0;
- unsigned long tmp;
- extern int etext;
+ unsigned long addr;
+#ifdef CONFIG_PMAC
+ int i;
+ unsigned long lim;
+#endif
+ int codepages = 0;
+ int datapages = 0;
+ int initpages = 0;
+
+ end_mem &= PAGE_MASK;
+ high_memory = (void *) end_mem;
+ num_physpages = max_mapnr = MAP_NR(high_memory);
- end_mem &= PAGE_MASK;
- high_memory = (void *)end_mem;
- max_mapnr = MAP_NR(end_mem);
- /* clear the zero-page */
- memset(empty_zero_page, 0, PAGE_SIZE);
+ /* clear the zero-page */
+ memset(empty_zero_page, 0, PAGE_SIZE);
/* mark usable pages in the mem_map[] */
- start_mem = PAGE_ALIGN(start_mem);
+ start_mem = PAGE_ALIGN(start_mem);
+
+#ifdef CONFIG_PMAC
+ remove_mem_piece(&phys_avail, __pa(avail_start),
+ start_mem - avail_start, 1);
+
+ for (a = KERNELBASE ; a < end_mem; a += PAGE_SIZE)
+ set_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+
+ for (i = 0; i < phys_avail.n_regions; ++i) {
+ a = (unsigned long) __va(phys_avail.regions[i].address);
+ lim = a + phys_avail.regions[i].size;
+ a = PAGE_ALIGN(a);
+ for (; a < lim; a += PAGE_SIZE) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+ mem_map[MAP_NR(a)].count = 1;
+ free_page(a);
+ }
+ }
+ phys_avail.n_regions = 0;
- for (tmp = KERNELBASE ; tmp < (long)high_memory ; tmp += PAGE_SIZE)
- {
- if (tmp < start_mem)
+ /* free the prom's memory */
+ for (i = 0; i < prom_mem.n_regions; ++i) {
+ a = (unsigned long) __va(prom_mem.regions[i].address);
+ lim = a + prom_mem.regions[i].size;
+ a = PAGE_ALIGN(a);
+ for (; a < lim; a += PAGE_SIZE) {
+ clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+ mem_map[MAP_NR(a)].count = 1;
+ free_page(a);
+ }
+ }
+ prom_trashed = 1;
+#endif /* CONFIG_PMAC */
+
+#ifdef CONFIG_PREP
+ /* mark mem used by kernel as reserved, mark other unreserved */
+ for (addr = PAGE_OFFSET ; addr < end_mem; addr += PAGE_SIZE)
{
- set_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
- if (tmp < (unsigned long) &etext)
- {
- codepages++;
- } else
- {
- datapages++;
- }
- continue;
- }
- clear_bit(PG_reserved, &mem_map[MAP_NR(tmp)].flags);
- atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
- free_page(tmp);
- }
- tmp = nr_free_pages << PAGE_SHIFT;
- printk("Memory: %luk/%luk available (%dk kernel code, %dk data)\n",
- tmp >> 10,
- ((int)high_memory - (int)KERNELBASE) >> 10,
- codepages << (PAGE_SHIFT-10),
- datapages << (PAGE_SHIFT-10));
- /* invalidate();*/
- return;
+ /* skip hash table gap */
+ if ( (addr > (ulong)_end) && (addr < (ulong)Hash))
+ continue;
+ if ( addr < (ulong) /*Hash_end*/ start_mem )
+ set_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
+ else
+ clear_bit(PG_reserved, &mem_map[MAP_NR(addr)].flags);
+ }
+
+ for (addr = PAGE_OFFSET; addr < end_mem; addr += PAGE_SIZE) {
+ if(PageReserved(mem_map + MAP_NR(addr))) {
+ if (addr < (ulong) etext)
+ codepages++;
+ /*else if((addr >= (unsigned long)&__init_begin && addr < (unsigned long)&__init_end))
+ initpages++;*/
+ else if (addr < (ulong) start_mem)
+ datapages++;
+ continue;
+ }
+ atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (!initrd_start ||
+ (addr < initrd_start || addr >= initrd_end))
+#endif /* CONFIG_BLK_DEV_INITRD */
+ free_page(addr);
+ }
+
+#endif /* CONFIG_PREP */
+ printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
+ (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
+ codepages << (PAGE_SHIFT-10),
+ datapages << (PAGE_SHIFT-10),
+ initpages << (PAGE_SHIFT-10),
+ PAGE_OFFSET, end_mem);
+ mem_init_done = 1;
}
+/*
+ * this should reclaim gap between _end[] and hash table
+ * as well as unused mmu_pages[] on prep systems.
+ * When I get around to it, I'll put initialization functions
+ * (called only at boot) in their own .section and free that -- Cort
+ */
void free_initmem(void)
{
- /* To be written */
+ unsigned long addr;
+ unsigned long a;
+ unsigned long num_freed_pages = 0;
+
+ /* free unused mmu_pages[] */
+ a = PAGE_ALIGN( (unsigned long) mmu_pages) + (mmu_pages_count*PAGE_SIZE);
+ for ( ; a < PAGE_ALIGN((unsigned long)mmu_pages)+(MAX_MMU_PAGES*PAGE_SIZE); a += PAGE_SIZE )
+ {
+ clear_bit( PG_reserved, &mem_map[MAP_NR(a)].flags );
+ atomic_set(&mem_map[MAP_NR(a)].count, 1);
+ free_page(a);
+ num_freed_pages++;
+ }
+
+#if 0
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ num_freed_pages++;
+ mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+ mem_map[MAP_NR(addr)].count = 1;
+ free_page(addr);
+ }
+#endif
+ printk ("Freeing unused kernel memory: %dk freed\n",
+ (num_freed_pages * PAGE_SIZE) >> 10);
}
void si_meminfo(struct sysinfo *val)
{
int i;
- i = ((int)high_memory & 0x00FFFFFF) >> PAGE_SHIFT;
+ i = max_mapnr;
val->totalram = 0;
val->sharedram = 0;
val->freeram = nr_free_pages << PAGE_SHIFT;
@@ -187,526 +576,637 @@ void si_meminfo(struct sysinfo *val)
val->totalram++;
if (!atomic_read(&mem_map[i].count))
continue;
- val->sharedram += atomic_read(&mem_map[i].count) - 1;
+ val->sharedram += atomic_read(&mem_map[i].count)-1;
}
val->totalram <<= PAGE_SHIFT;
val->sharedram <<= PAGE_SHIFT;
return;
}
+/* Kernel MMU setup & lowest level hardware support */
+
+unsigned long _SDR1; /* Hardware SDR1 image */
+
+#ifdef CONFIG_PREP
+
BAT BAT0 =
- {
- {
- 0x80000000>>17, /* bepi */
- BL_256M, /* bl */
- 1, /* vs -- supervisor mode valid */
- 1, /* vp -- user mode valid */
- },
- {
- 0x80000000>>17, /* brpn */
- 1, /* write-through */
- 1, /* cache-inhibited */
- 0, /* memory coherence */
- 1, /* guarded */
- BPP_RW /* protection */
- }
- };
+{
+ {
+ 0x80000000>>17, /* bepi */
+ BL_256M, /* bl */
+ 1, /* vs -- supervisor mode valid */
+ 1, /* vp -- user mode valid */
+ },
+ {
+ 0x80000000>>17, /* brpn */
+ 1, /* write-through */
+ 1, /* cache-inhibited */
+ 0, /* memory coherence */
+ 1, /* guarded */
+ BPP_RW /* protection */
+ }
+};
BAT BAT1 =
- {
- {
- 0xC0000000>>17, /* bepi */
- BL_256M, /* bl */
- 1, /* vs */
- 1, /* vp */
- },
- {
- 0xC0000000>>17, /* brpn */
- 1, /* w */
- 1, /* i (cache disabled) */
- 0, /* m */
- 1, /* g */
- BPP_RW /* pp */
- }
- };
+{
+ {
+ 0xC0000000>>17, /* bepi */
+ BL_256M, /* bl */
+ 1, /* vs */
+ 1, /* vp */
+ },
+ {
+ 0xC0000000>>17, /* brpn */
+ 1, /* w */
+ 1, /* i (cache disabled) */
+ 0, /* m */
+ 1, /* g */
+ BPP_RW /* pp */
+ }
+};
BAT BAT2 =
- {
- {
- 0x90000000>>17, /* bepi */
- BL_256M, /* this gets set to amount of phys ram */
- 1, /* vs */
- 0, /* vp */
- },
- {
- 0x00000000>>17, /* brpn */
- 0, /* w */
- 0, /* i */
- 0, /* m */
- 0, /* g */
- BPP_RW /* pp */
- }
- };
+{
+ {
+ 0x90000000>>17, /* bepi */
+ BL_256M, /* this gets set to amount of phys ram */
+ 1, /* vs */
+ 0, /* vp */
+ },
+ {
+ 0x00000000>>17, /* brpn */
+ 0, /* w */
+ 0, /* i */
+ 1, /* m */
+ 0, /* g */
+ BPP_RW /* pp */
+ }
+};
BAT BAT3 =
- {
- {
- 0x00000000>>17, /* bepi */
- BL_256M, /* bl */
- 0, /* vs */
- 0, /* vp */
- },
- {
- 0x00000000>>17, /* brpn */
- 1, /* w */
- 1, /* i (cache disabled) */
- 0, /* m */
- 0, /* g */
- BPP_RW /* pp */
- }
- };
-BAT TMP_BAT2 =
- { /* 0x9XXXXXXX -> 0x0XXXXXXX */
- {
- 0x90000000>>17, /* bepi */
- BL_256M, /* bl */
- 1, /* vs */
- 1, /* vp */
- },
- {
- 0x00000000>>17, /* brpn */
- 1, /* w */
- 0, /* i (cache enabled) */
- 0, /* m */
- 0, /* g */
- BPP_RW /* pp */
- }
- };
-
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/*
- * This code is called to create a minimal mapped environment.
- * It is called with the MMU on, but with only a BAT register
- * set up to cover the code/data. After this routine runs,
- * the BAT mapping is withdrawn and all mappings must be complete.
- */
+{
+ {
+ 0x00000000>>17, /* bepi */
+ BL_256M, /* bl */
+ 0, /* vs */
+ 0, /* vp */
+ },
+ {
+ 0x00000000>>17, /* brpn */
+ 0, /* w */
+ 0, /* i (cache disabled) */
+ 1, /* m */
+ 0, /* g */
+ BPP_RW /* pp */
+ }
+};
+P601_BAT BAT0_601 =
+{
+ {
+ 0x80000000>>17, /* bepi */
+ 1,1,0, /* wim */
+ 1, 0, /* vs, vp */
+ BPP_RW, /* pp */
+ },
+ {
+ 0x80000000>>17, /* brpn */
+ 1, /* v */
+ BL_8M, /* bl */
+ }
+};
+P601_BAT BAT1_601 =
+{
+ {
+ 0xC0000000>>17, /* bepi */
+ 1,1,0, /* wim */
+ 1, 0, /* vs, vp */
+ BPP_RW, /* pp */
+ },
+ {
+ 0xC0000000>>17, /* brpn */
+ 1, /* v */
+ BL_8M, /* bl */
+ }
+};
+P601_BAT BAT2_601 =
+{
+ {
+ 0x90000000>>17, /* bepi */
+ 0,0,0, /* wim */
+ 1, 0, /* vs, vp */
+ BPP_RW, /* pp */
+ },
+ {
+ 0x00000000>>17, /* brpn */
+ 1, /* v */
+ BL_8M, /* bl */
+ }
+};
-extern char _start[], _end[];
-
-void MMU_init(void)
+P601_BAT BAT3_601 =
{
- extern RESIDUAL res;
- extern unsigned long resptr;
- int i, p;
- SEGREG *segs;
-
- /* copy residual data */
- if ( resptr )
- memcpy( &res, (void *)(resptr+KERNELBASE), sizeof(RESIDUAL) );
- else
- bzero( &res, sizeof(RESIDUAL) ); /* clearing bss probably clears this but... */
-
- end_of_DRAM = (unsigned long *)find_end_of_memory();
- _SDR1 = ((unsigned long)Hash - KERNELBASE) | Hash_mask;
-#if 0
- printk("Hash %08x\n",(unsigned long)Hash);
- printk("Hash_mask %08x\n",Hash_mask);
- printk("Hash_size %08x\n",Hash_size);
- printk("SDR1 %08x\n",_SDR1);
-#endif
- /* Segment registers */
- segs = (SEGREG *)init_task.tss.segs;
- for (i = 0; i < 16; i++)
{
- segs[i].ks = 0;
- segs[i].kp = 1;
-#if 1
- if ( i < 8 )
- segs[i].vsid = i+10000;
- else
-#else
- if ( i < 8 )
- segs[i].vsid = i<<5;
-#endif
- segs[i].vsid = i;
+ 0x90800000>>17, /* bepi */
+ 0,0,0, /* wim */
+ 1, 0, /* vs, vp */
+ BPP_RW, /* pp */
+ },
+ {
+ 0x00800000>>17, /* brpn */
+ 1, /* v */
+ BL_8M, /* bl */
}
-
-
-
- /* Hard map in any special local resources */
- if (isBeBox[0])
- {
- /* Map in one page for the BeBox motherboard I/O */
- end_of_DRAM = (unsigned long *)((unsigned long)end_of_DRAM - PAGE_SIZE);
-#if 0
- BeBox_IO_page = (unsigned char *)0x7FFFF000;
-#endif
- BeBox_IO_page = (unsigned char *)end_of_DRAM;
- MMU_disable_cache_for_page(&init_task.tss, BeBox_IO_page);
- }
-}
+};
/*
- * Insert(create) a hardware page table entry
+ * This finds the amount of physical ram and does necessary
+ * setup for prep. This is pretty architecture specific so
+ * this will likely stay seperate from the pmac.
+ * -- Cort
*/
-int inline MMU_hash_page(struct thread_struct *tss, unsigned long va, pte *pg)
-{
- int hash, page_index, segment, i, h, _h, api, vsid, perms;
- PTE *_pte, *empty, *slot;
- PTE *slot0, *slot1;
- extern char _etext;
- page_index = ((int)va & 0x0FFFF000) >> 12;
- segment = (unsigned int)va >> 28;
- api = page_index >> 10;
- vsid = ((SEGREG *)tss->segs)[segment].vsid;
- empty = slot = (PTE *)NULL;
-
- if ( (va <= _etext) && (va >= KERNELBASE))
- {
- printk("MMU_hash_page: called on kernel page mapped with bats va %x\n",
- va);
- }
+unsigned long *find_end_of_memory(void)
+{
+ extern RESIDUAL res;
+ extern unsigned long resptr;
+ int i, p;
+ unsigned long h;
- /* check first hash bucket */
- h = 0;
- hash = page_index ^ vsid;
- hash &= 0x3FF | (Hash_mask << 10);
- hash *= 8; /* 8 entries in each bucket */
- _pte = &Hash[hash];
- slot0 = _pte;
- for (i = 0; i < 8; i++, _pte++)
- {
- if (_pte->v && _pte->vsid == vsid && _pte->h == h && _pte->api == api)
- {
- slot = _pte;
- goto found_it;
- }
- if ((empty == NULL) && (!_pte->v))
+ /* copy residual data */
+ if ( resptr )
+ memcpy( &res, (void *)(resptr+KERNELBASE), sizeof(RESIDUAL) );
+ else
+ /* clearing bss probably clears this but... */
+ memset( &res, sizeof(RESIDUAL), 0 );
+ _TotalMemory = res.TotalMemory;
+
+ /* this really has nothing to do with the mmu_init() but is
+ necessary for early setup -- Cort */
+ if (!strncmp(res.VitalProductData.PrintableModel,"IBM",3))
{
- empty = _pte;
- _h = h;
+ _machine = _MACH_IBM;
}
- }
-
- /* check second hash bucket */
- h = 1;
- hash = page_index ^ vsid;
- hash = ~hash;
- hash &= 0x3FF | (Hash_mask << 10);
- hash *= 8; /* 8 entries in each bucket */
- _pte = &Hash[hash];
- slot1 = _pte;
- for (i = 0; i < 8; i++, _pte++)
- {
- if (_pte->v && _pte->vsid == vsid && _pte->h == h && _pte->api == api)
+ else
+ _machine = _MACH_Motorola;
+
+ /* setup the hash table */
+ if (_TotalMemory == 0 )
{
- slot = _pte;
- goto found_it;
+ /*
+ * I need a way to probe the amount of memory if the residual
+ * data doesn't contain it. -- Cort
+ */
+ printk("Ramsize from residual data was 0 -- Probing for value\n");
+ _TotalMemory = 0x03000000;
+ printk("Ramsize default to be %dM\n", _TotalMemory>>20);
}
- if ((empty == NULL) && (!_pte->v))
+
+#if 0
+ /* linux has trouble with > 64M ram -- Cort */
+ if ( _TotalMemory > 0x04000000 /* 64M */ )
{
- empty = _pte;
- _h = h;
+ printk("Only using first 64M of ram.\n");
+ _TotalMemory = 0x04000000;
}
- }
+#endif
+
+ /* setup the bat2 mapping to cover physical ram */
+ BAT2.batu.bl = 0x1; /* 256k mapping */
+ for ( h = 256*1024 /* 256k */ ; (h <= _TotalMemory) && (h <= 256*1024*1024);
+ h *= 2 )
+ BAT2.batu.bl = (BAT2.batu.bl << 1) | BAT2.batu.bl;
+ /*
+ * Allow 64k of hash table for every 16MB of memory,
+ * up to a maximum of 2MB.
+ */
+ for (h = 64<<10; h < _TotalMemory / 256 && h < 2<<20; h *= 2)
+ ;
+ Hash_size = h;
+ Hash_mask = (h >> 6) - 1;
+
+ /* align htab on a Hash_size boundry above _end[] */
+ Hash = (PTE *)_ALIGN( (unsigned long)&_end, Hash_size);
+ memset(Hash, Hash_size, 0 );
- if (empty == (PTE *)NULL)
- {
-#if 1
- printk("Both hash buckets full! va %x vsid %x current %s (%d)\n",
- va,vsid,current->comm,current->pid);
-#endif
- slot = slot1;
- h = 1;
- }
- else
- {
- slot = empty;
- h = _h;
- }
-found_it:
-#ifdef HASHSTATS
- hashhits[hash]++;
-#endif
- _tlbie(va); /* Clear TLB */
- /* Fill in table */
- slot->v = 1;
- slot->vsid = vsid;
- slot->h = h;
- slot->api = api;
- if (((pg->page_num << 12) & 0xF0000000) == KERNELBASE)
+ /*
+ * if this is a 601, we can only map sizes of 8M with the BAT's
+ * so we have to map what we can't map with the bats with the segregs
+ * head.S will copy in the appropriate BAT's according to the processor
+ * since the 601_BAT{2,3} structures are already setup to map
+ * the first 16M correctly
+ * -- Cort
+ */
+#ifndef MAP_RAM_WITH_SEGREGS /* don't need to do it twice */
+ if ( _get_PVR() == 1 )
{
- slot->rpn = pg->page_num - (KERNELBASE>>12);
- } else
- {
- slot->rpn = pg->page_num;
- }
- slot->r = 0;
- slot->c = 0;
- slot->i = 0;
- slot->g = 0;
- if (cache_is_copyback)
- {
- if (kernel_pages_are_copyback || (pg->flags & _PAGE_USER) || (va < (unsigned long)&_etext))
- { /* All User & Kernel TEXT pages are copy-back */
- slot->w = 0;
- slot->m = 1;
- } else
- { /* Kernel DATA pages are write-thru */
- slot->w = 1;
- slot->m = 0;
- }
- } else
- {
- slot->w = 1;
- slot->m = 0;
- }
- if (pg->flags & _PAGE_USER)
+ /* map in rest of ram with seg regs */
+ if ( _TotalMemory > 0x01000000 /* 16M */)
+ {
+ for (i = KERNELBASE+0x01000000;
+ i < KERNELBASE+_TotalMemory; i += PAGE_SIZE)
+ map_page(&init_task.tss, i, __pa(i),
+ _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED);
+ }
+ }
+#endif /* MAP_RAM_WITH_SEGREGS */
+
+#ifdef MAP_RAM_WITH_SEGREGS
+ /* turn off bat mapping kernel since being done with segregs */
+ memset(&BAT2, sizeof(BAT2), 0);
+ memset(&BAT2_601, sizeof(BAT2), 0); /* in case we're on a 601 */
+ memset(&BAT3_601, sizeof(BAT2), 0);
+ /* map all of ram for kernel with segregs */
+ for (i = KERNELBASE; i < KERNELBASE+_TotalMemory; i += PAGE_SIZE)
{
- if (pg->flags & _PAGE_RW)
- { /* Read/write page */
- perms = PP_RWRW;
- } else
- { /* Read only page */
- perms = PP_RWRX;
- perms = PP_RXRX;
- }
- } else
- { /* Kernel pages */
- perms = PP_RWRW;
- perms = PP_RWXX;
- }
- slot->pp = perms;
- return (0);
+ if ( i < (unsigned long)etext )
+ map_page(&init_task.tss, i, __pa(i),
+ _PAGE_PRESENT/*| _PAGE_RW*/|_PAGE_DIRTY|_PAGE_ACCESSED);
+ else
+ map_page(&init_task.tss, i, __pa(i),
+ _PAGE_PRESENT| _PAGE_RW|_PAGE_DIRTY|_PAGE_ACCESSED);
+ }
+#endif /* MAP_RAM_WITH_SEGREGS */
+
+ printk("Total memory = %ldMB; using %ldkB for hash table (at %p)\n",
+ _TotalMemory >> 20, Hash_size >> 10, Hash);
+ return ((unsigned long *)_TotalMemory);
}
+#endif /* CONFIG_PREP */
+
+#ifdef CONFIG_PMAC
/*
- * Disable cache for a particular page
+ * Map in all of physical memory starting at KERNELBASE.
*/
-MMU_disable_cache_for_page(struct thread_struct *tss, unsigned long va)
+extern int n_mem_regions;
+extern struct reg_property mem_regions[];
+
+#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+
+static void mapin_ram()
{
- int hash, page_index, segment, i, h, _h, api, vsid, perms;
- PTE *_pte, *empty, *slot;
- PTE *slot0, *slot1;
- extern char _etext;
- page_index = ((int)va & 0x0FFFF000) >> 12;
- segment = (unsigned int)va >> 28;
- api = page_index >> 10;
- vsid = ((SEGREG *)tss->segs)[segment].vsid;
- empty = slot = (PTE *)NULL;
- for (_h = 0; _h < 2; _h++)
- {
- hash = page_index ^ vsid;
- if (_h)
- {
- hash = ~hash; /* Secondary hash uses ones-complement */
- }
- hash &= 0x3FF | (Hash_mask << 10);
- hash *= 8; /* Eight entries / hash bucket */
- _pte = &Hash[hash];
- /* Save slot addresses in case we have to purge */
- if (_h)
- {
- slot1 = _pte;
- } else
- {
- slot0 = _pte;
- }
- for (i = 0; i < 8; i++, _pte++)
- {
- if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
- { /* Found it! */
- h = _h;
- slot = _pte;
- goto found_it;
- }
- if ((empty == (PTE *)NULL) && !_pte->v)
- {
- h = _h;
- empty = _pte;
- }
- }
+ int i;
+ unsigned long v, p, s, f;
+
+ v = KERNELBASE;
+ for (i = 0; i < phys_mem.n_regions; ++i) {
+ p = phys_mem.regions[i].address;
+ for (s = 0; s < phys_mem.regions[i].size; s += PAGE_SIZE) {
+ f = _PAGE_PRESENT | _PAGE_ACCESSED;
+ if ((char *) v < _stext || (char *) v >= etext)
+ f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+ map_page(&init_task.tss, v, p, f);
+ v += PAGE_SIZE;
+ p += PAGE_SIZE;
}
-found_it:
- _tlbie(va); /* Clear TLB */
- slot->i = 1;
- slot->m = 0;
+ }
}
+#define MAX_PROM_TRANSLATIONS 64
-/*
- * invalidate a hardware hash table pte
- */
-inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va)
+static struct translation_property prom_translations[MAX_PROM_TRANSLATIONS];
+int n_translations;
+phandle mmu_pkg;
+extern ihandle prom_chosen;
+
+static void inherit_prom_translations()
{
- int hash, page_index, segment, i, h, _h, api, vsid, perms;
- PTE *_pte, *slot;
- int flags = 0;
- page_index = ((int)va & 0x0FFFF000) >> 12;
- segment = (unsigned int)va >> 28;
- api = page_index >> 10;
- vsid = mm->context | segment;
- for (_h = 0; _h < 2; _h++)
- {
- hash = page_index ^ vsid;
- if (_h)
- {
- hash = ~hash; /* Secondary hash uses ones-complement */
- }
- hash &= 0x3FF | (Hash_mask << 10);
- hash *= 8; /* Eight entries / hash bucket */
- _pte = &Hash[hash];
- for (i = 0; i < 8; i++, _pte++)
- {
- if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
- { /* Found it! */
- _tlbie(va); /* Clear TLB */
- if (_pte->r) flags |= _PAGE_ACCESSED;
- if (_pte->c) flags |= _PAGE_DIRTY;
- _pte->v = 0;
- return (flags);
- }
+ int s, i, f;
+ unsigned long v, p, n;
+ struct translation_property *tp;
+ ihandle mmu_inst;
+
+ if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",
+ &mmu_inst, sizeof(mmu_inst)) != sizeof(mmu_inst))
+ panic("couldn't get /chosen mmu property");
+ mmu_pkg = call_prom("instance-to-package", 1, 1, mmu_inst);
+ if (mmu_pkg == (phandle) -1)
+ panic("couldn't get mmu package");
+ s = (int) call_prom("getprop", 4, 1, mmu_pkg, "translations",
+ &prom_translations, sizeof(prom_translations));
+ if (s < sizeof(prom_translations[0]))
+ panic("couldn't get mmu translations property");
+ n_translations = s / sizeof(prom_translations[0]);
+
+ for (tp = prom_translations, i = 0; i < n_translations; ++i, ++tp) {
+ /* ignore stuff mapped down low */
+ if (tp->virt < 0x10000000)
+ continue;
+ /* map PPC mmu flags to linux mm flags */
+ f = (tp->flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU
+ | _PAGE_COHERENT | _PAGE_GUARDED))
+ | pgprot_val(PAGE_KERNEL);
+ /* add these pages to the mappings */
+ v = tp->virt;
+ p = tp->phys;
+ n = tp->size;
+ for (; n != 0; n -= PAGE_SIZE) {
+ map_page(&init_task.tss, v, p, f);
+ v += PAGE_SIZE;
+ p += PAGE_SIZE;
}
}
- _tlbie(va);
- return (flags);
}
+#endif
-
-inline void
-flush_cache_all(void)
+/*
+ * Initialize the hash table and patch the instructions in head.S.
+ */
+static void hash_init(void)
{
+ int Hash_bits;
+
+ extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
+ hash_page_patch_C[];
+
+ memset(Hash, 0, Hash_size);
+ Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
+
+ /*
+ * Patch up the instructions in head.S:hash_page
+ */
+ Hash_bits = ffz(~Hash_size) - 6;
+ hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
+ | (__pa(Hash) >> 16);
+ hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
+ | ((26 - Hash_bits) << 6);
+ if (Hash_bits > 16)
+ Hash_bits = 16;
+ hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
+ | ((26 - Hash_bits) << 6);
+ hash_page_patch_B[0] = (hash_page_patch_B[0] & ~0xffff)
+ | (Hash_mask >> 10);
+ hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
+ | (Hash_mask >> 10);
+
+ /*
+ * Ensure that the locations we've patched have been written
+ * out from the data cache and invalidated in the instruction
+ * cache, on those machines with split caches.
+ */
+ store_cache_range((unsigned long) hash_page_patch_A,
+ (unsigned long) (hash_page_patch_C + 1));
}
-inline void
-flush_cache_mm(struct mm_struct *mm)
+
+
+/*
+ * Do very early mm setup such as finding the size of memory
+ * and setting up the hash table.
+ * A lot of this is prep/pmac specific but a lot of it could
+ * still be merged.
+ * -- Cort
+ */
+void
+MMU_init(void)
{
-}
-inline void
-flush_cache_page(struct vm_area_struct *vma, long va)
+ end_of_DRAM = find_end_of_memory();
+ hash_init();
+ _SDR1 = __pa(Hash) | (Hash_mask >> 10);
+#ifdef CONFIG_PMAC
+ /* Force initial page tables */
+ /* this done by INIT_TSS in processor.h on prep -- Cort */
+ init_task.tss.pg_tables = (unsigned long *)swapper_pg_dir;
+
+ /* Map in all of RAM starting at KERNELBASE */
+ mapin_ram();
+ /* Copy mappings from the prom */
+ inherit_prom_translations();
+#endif /* CONFIG_PMAC */
+}
+
+static void *
+MMU_get_page()
{
-}
-inline void
-flush_cache_range(struct mm_struct *mm, unsigned long va_start, unsigned long va_end)
+ void *p;
+
+ if (mem_init_done) {
+ p = (void *) __get_free_page(GFP_KERNEL);
+ if (p == 0)
+ panic("couldn't get a page in MMU_get_page");
+ } else {
+#ifdef CONFIG_PREP
+ mmu_pages_count++;
+ if ( mmu_pages_count > MAX_MMU_PAGES )
+ printk("out of mmu pages!\n");
+ p = (pte *)(PAGE_ALIGN((unsigned long)mmu_pages)+
+ (mmu_pages_count+PAGE_SIZE));
+#endif
+#ifdef CONFIG_PMAC
+ p = find_mem_piece(PAGE_SIZE, PAGE_SIZE);
+#endif
+ }
+ memset(p, 0, PAGE_SIZE);
+ return p;
+}
+
+#ifdef CONFIG_PMAC
+void *
+ioremap(unsigned long addr, unsigned long size)
{
-}
+ unsigned long p, end = addr + size;
+
+ for (p = addr & PAGE_MASK; p < end; p += PAGE_SIZE)
+ map_page(&init_task.tss, p, p, pgprot_val(PAGE_KERNEL_CI) | _PAGE_GUARDED);
+ return (void *) addr;
+}
+#endif
-inline void
-cache_mode(char *str, int *ints)
+void
+map_page(struct thread_struct *tss, unsigned long va,
+ unsigned long pa, int flags)
{
- cache_is_copyback = ints[0];
+ pmd_t *pd;
+ pte_t *pg;
+
+ if (tss->pg_tables == NULL) {
+ /* Allocate upper level page map */
+ tss->pg_tables = (unsigned long *) MMU_get_page();
+ }
+ /* Use upper 10 bits of VA to index the first level map */
+ pd = (pmd_t *) (tss->pg_tables + (va >> PGDIR_SHIFT));
+ if (pmd_none(*pd)) {
+ /* Need to allocate second-level table */
+ pg = (pte_t *) MMU_get_page();
+ pmd_val(*pd) = (unsigned long) pg;
+ }
+ /* Use middle 10 bits of VA to index the second-level map */
+ pg = pte_offset(pd, va);
+ set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
+ /*flush_hash_page(va >> 28, va);*/
+ flush_hash_page(0, va);
}
/*
* TLB flushing:
*
- * - flush_tlb() flushes the current mm struct TLBs
* - flush_tlb_all() flushes all processes TLBs
* - flush_tlb_mm(mm) flushes the specified mm context TLB's
* - flush_tlb_page(vma, vmaddr) flushes one page
* - flush_tlb_range(mm, start, end) flushes a range of pages
*
* since the hardware hash table functions as an extension of the
- * tlb as far as the linux tables are concerned, flush them too.
+ * tlb as far as the linux tables are concerned, flush it too.
* -- Cort
*/
-inline void
-flush_tlb(void)
-{
- PTE *ptep;
- int context = current->mm->context;
- struct vm_area_struct *v;
- unsigned int i;
-
- v = current->mm->mmap;
- /* for every virtual memory address in the current context -- flush
- the hash table */
- while ( v != NULL )
- {
- for ( i = v->vm_start ; i <= v->vm_end; i += PAGE_SIZE)
- {
- MMU_invalidate_page(v->vm_mm,i);
- }
- v = v->vm_next;
- }
-
- _tlbia();
-}
-
-/* flush all tlb/hash table entries except for kernels
-
- although the kernel is mapped with the bats, it's dynamic areas
- obtained via kmalloc are mapped by the seg regs
- -- Cort
- */
-inline void
+/*
+ * Flush all tlb/hash table entries except for the kernel's.
+ * We use the fact that only kernel mappings use VSIDs 0 - 15.
+ */
+void
flush_tlb_all(void)
{
- PTE *ptep;
-
- /* flush hash table */
- for ( ptep = Hash ; ptep < (PTE *)((unsigned long)Hash+Hash_size) ; ptep++ )
- {
- /* if not kernel vsids 0-7 (vsid greater than that for process 0)*/
- if ( (ptep->vsid > 7 ) && (ptep->v))
- {
- ptep->v = 0;
- }
- }
+ struct task_struct *tsk;
- _tlbia();
+ read_lock(&tasklist_lock);
+ for_each_task(tsk) {
+ if (tsk->mm)
+ tsk->mm->context = NO_CONTEXT;
+ }
+ read_unlock(&tasklist_lock);
+ get_mmu_context(current);
+ set_context(current->mm->context);
}
-inline void
+
+/*
+ * Flush all the (user) entries for the address space described
+ * by mm. We can't rely on mm->mmap describing all the entries
+ * that might be in the hash table.
+ */
+void
flush_tlb_mm(struct mm_struct *mm)
{
- PTE *ptep;
- int context = mm->context;
- struct vm_area_struct *v;
- unsigned int i;
-
- v = mm->mmap;
- while ( v != NULL )
- {
- for ( i = v->vm_start ; i <= v->vm_end; i += PAGE_SIZE)
- {
- MMU_invalidate_page(v->vm_mm,i);
- }
- v = v->vm_next;
- }
-
- _tlbia();
+ mm->context = NO_CONTEXT;
+ if (mm == current->mm) {
+ get_mmu_context(current);
+ /* done by get_mmu_context() now -- Cort */
+ /*set_context(current->mm->context);*/
+ }
}
-inline void
-flush_tlb_page(struct vm_area_struct *vma, long vmaddr)
+void
+flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
{
- MMU_invalidate_page(vma->vm_mm,vmaddr);
+ unsigned vsid;
+
+ if ( vmaddr < TASK_SIZE) {
+ /*vsid = (vma->vm_mm->context << 4) | (vmaddr >> 28);*/
+ flush_hash_page(vma->vm_mm->context/*vsid*/, vmaddr);
+ /* this is needed on prep at the moment -- don't know why
+ -- Cort*/
+ MMU_invalidate_page(vma->vm_mm,vmaddr);
+ }
+ else
+ {
+ /*printk("flush_tlb_page() vmaddr > TASK_SIZE %08x\n", vmaddr);*/
+ }
}
-/* for each page addr in the range, call mmu_invalidat_page()
+/* for each page addr in the range, call MMU_invalidate_page()
if the range is very large and the hash table is small it might be faster to
do a search of the hash table and just invalidate pages that are in the range
but that's for study later.
-- Cort
*/
-inline void
-flush_tlb_range(struct mm_struct *mm, long start, long end)
+void
+flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
{
- long i;
- for ( i = PAGE_ALIGN(start-PAGE_SIZE) ; i < PAGE_ALIGN(end) ; i += PAGE_SIZE)
- {
- MMU_invalidate_page(mm,i);
- }
+ start &= PAGE_MASK;
+ for (; start < end && start < TASK_SIZE; start += PAGE_SIZE)
+ {
+ /*flush_hash_page(VSID_FROM_CONTEXT( start>>28, mm->context),
+ start );*/
+ flush_hash_page(mm->context, start);
+ /* this is needed on prep at the moment -- don't know why
+ -- Cort*/
+ MMU_invalidate_page(mm,start);
+ }
}
-inline void
-flush_page_to_ram(unsigned long page)
+/*
+ * The context counter has overflowed.
+ * We set mm->context to NO_CONTEXT for all mm's in the system.
+ * We assume we can get to all mm's by looking as tsk->mm for
+ * all tasks in the system.
+ */
+void
+mmu_context_overflow(void)
+{
+ struct task_struct *tsk;
+ int nr;
+
+ printk(KERN_INFO "mmu_context_overflow\n");
+ for (nr = 0; nr < NR_TASKS; ++nr) {
+ tsk = task[nr];
+ if (tsk && tsk->mm)
+ tsk->mm->context = NO_CONTEXT;
+ }
+ flush_hash_segments(0x10, 0xffffff);
+ _tlbia();
+ next_mmu_context = 0;
+}
+
+#ifdef CONFIG_PREP
+/*
+ * it's not a simple matter to get rid of these and switch to the
+ * ones paul is using. it will take some time and thought -- Cort
+ */
+inline void MMU_invalidate_page(struct mm_struct *mm, unsigned long va)
{
+ int hash, page_index, segment, i, h, _h, api, vsid, perms;
+ PTE *_pte, *slot;
+ int flags = 0;
+ page_index = ((int)va & 0x0FFFF000) >> 12;
+ segment = (unsigned int)va >> 28;
+ api = page_index >> 10;
+ vsid = VSID_FROM_CONTEXT(segment,mm->context);
+ for (_h = 0; _h < 2; _h++)
+ {
+ hash = page_index ^ vsid;
+ if (_h)
+ {
+ hash = ~hash; /* Secondary hash uses ones-complement */
+ }
+ hash &= 0x3FF | (Hash_mask /*<< 10*/);
+ hash *= 8; /* Eight entries / hash bucket */
+ _pte = &Hash[hash];
+ for (i = 0; i < 8; i++, _pte++)
+ {
+ if (_pte->v && _pte->vsid == vsid && _pte->h == _h && _pte->api == api)
+ { /* Found it! */
+ _tlbie(va); /* Clear TLB */
+ if (_pte->r) flags |= _PAGE_ACCESSED;
+ if (_pte->c) flags |= _PAGE_DIRTY;
+ _pte->v = 0;
+ return /*(flags)*/;
+ }
+ }
+ }
+ _tlbie(va);
+ return /*(flags)*/;
+}
+#endif
+
+#include <asm/mmu.h>
+void print_mm_info(void)
+{
+ struct _SEGREG s;
+ long a;
+ struct _BATU bu;
+ struct _BATL bl;
+ unsigned long i;
+
+ for ( i = 0x70000000 ; i <= 0x90000000 ; i+= 0x10000000 )
+ {
+ a = get_SR(i);
+ memcpy(&s,&a,4);
+ printk("sr %2d t:%1d ks:%d kp:%d n:%d vsid:%x %x\n",
+ i>>28, s.t, s.ks, s.kp, s.n, s.vsid, a);
+ }
+
+ asm("mfspr %0,532; mfspr %1, 533\n" : "=r" (bu), "=r" (bl));
+ printk("bat2 bepi: %0x vs: %1x vp: %1x wimg: %x%x%x%x pp: %1x\n",
+ bu.bepi<<17, bu.vs, bu.vp, bl.w, bl.i, bl.m, bl.g, bl.pp);
}
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 9d64ee85d..80e114585 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -42,7 +42,7 @@ SUN_FB_CGFOURTEEN=y
SUN_FB_BWTWO=y
SUN_FB_LEO=y
TADPOLE_FB_WEITEK=y
-#SUN_FB_CREATOR is not set
+SUN_FB_CREATOR=y
#
# Misc Linux/SPARC drivers
@@ -180,15 +180,12 @@ CONFIG_MYRI_SBUS=m
# Filesystems
#
CONFIG_QUOTA=y
-# CONFIG_DCACHE_PRELOAD is not set
-# CONFIG_OMIRR is not set
-# CONFIG_TRANS_NAMES is not set
CONFIG_MINIX_FS=m
CONFIG_EXT2_FS=y
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
-CONFIG_UMSDOS_FS=m
+# CONFIG_UMSDOS_FS is not set
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 5d0ea0840..f60ecbe9c 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.80 1997/07/17 02:20:22 davem Exp $
+/* $Id: sys_sunos.c,v 1.81 1997/07/20 05:59:31 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -842,8 +842,9 @@ asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
linux_nfs_mount.acdirmin = sunos_mount->acdirmin;
linux_nfs_mount.acdirmax = sunos_mount->acdirmax;
- if (getname (sunos_mount->hostname, &the_name))
- return -EFAULT;
+ the_name = getname(sunos_mount->hostname);
+ if(IS_ERR(the_name))
+ return PTR_ERR(the_name);
strncpy (linux_nfs_mount.hostname, the_name, 254);
linux_nfs_mount.hostname [255] = 0;
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 3b9970551..ad9aa8953 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.148 1997/06/24 15:48:02 jj Exp $
+/* $Id: srmmu.c,v 1.149 1997/07/20 05:59:34 davem Exp $
* srmmu.c: SRMMU specific routines for memory management.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -2214,7 +2214,8 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
{
if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
struct vm_area_struct *vmaring;
- struct inode *inode;
+ struct dentry *dentry;
+ struct inode *inode = NULL;
unsigned long flags, offset, vaddr, start;
int alias_found = 0;
pgd_t *pgdp;
@@ -2223,7 +2224,9 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
save_and_cli(flags);
- inode = vma->vm_inode;
+ dentry = vma->vm_dentry;
+ if(dentry)
+ inode = dentry->d_inode;
if (!inode)
goto done;
offset = (address & PAGE_MASK) - vma->vm_start;
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c
index a0ffc10ed..7ffca1033 100644
--- a/arch/sparc/mm/sun4c.c
+++ b/arch/sparc/mm/sun4c.c
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.148 1997/05/18 21:11:19 davem Exp $
+/* $Id: sun4c.c,v 1.149 1997/07/20 05:59:38 davem Exp $
* sun4c.c: Doing in software what should be done in hardware.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -2435,11 +2435,14 @@ static pgd_t *sun4c_pgd_alloc(void)
*/
static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte)
{
- struct inode *inode;
+ struct dentry *dentry;
+ struct inode *inode = NULL;
pgd_t *pgdp;
pte_t *ptep;
- inode = vma->vm_inode;
+ dentry = vma->vm_dentry;
+ if(dentry)
+ inode = dentry->d_inode;
if(inode) {
unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
struct vm_area_struct *vmaring = inode->i_mmap;
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 92a003853..c9c92b987 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -160,14 +160,11 @@ CONFIG_MYRI_SBUS=m
# Filesystems
#
# CONFIG_QUOTA is not set
-# CONFIG_DCACHE_PRELOAD is not set
-# CONFIG_OMIRR is not set
-# CONFIG_TRANS_NAMES is not set
CONFIG_MINIX_FS=m
CONFIG_EXT2_FS=y
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
+# CONFIG_VFAT_FS is not set
# CONFIG_UMSDOS_FS is not set
CONFIG_PROC_FS=y
CONFIG_NFS_FS=y
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile
index 9e9013735..aecb9fd47 100644
--- a/arch/sparc64/kernel/Makefile
+++ b/arch/sparc64/kernel/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.28 1997/07/05 09:52:20 davem Exp $
+# $Id: Makefile,v 1.30 1997/07/24 14:48:04 davem Exp $
# Makefile for the linux kernel.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -7,12 +7,24 @@
#
# Note 2! The CFLAGS definitions are now in the main makefile...
+ifdef SMP
+
+.S.s:
+ $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
+
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
+
+else
+
.S.s:
$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
.S.o:
$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
+endif
+
all: kernel.o head.o init_task.o
O_TARGET := kernel.o
@@ -22,6 +34,10 @@ O_OBJS := process.o setup.o cpu.o idprom.o \
unaligned.o sys_sunos32.o sunos_ioctl32.o
OX_OBJS := sparc64_ksyms.o
+ifdef SMP
+O_OBJS += smp.o trampoline.o
+endif
+
ifdef CONFIG_SPARC32_COMPAT
O_OBJS += sys32.o sys_sparc32.o signal32.o ioctl32.o
endif
@@ -36,7 +52,7 @@ endif
head.o: head.S ttable.S itlb_miss.S dtlb_miss.S dtlb_prot.S etrap.S rtrap.S \
winfixup.S entry.S
- $(CC) -D__ASSEMBLY__ -ansi -c $*.S -o $*.o
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $*.S -o $*.o
#
# This is just to get the dependencies...
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c
index 6c3ff9174..00e5f2722 100644
--- a/arch/sparc64/kernel/auxio.c
+++ b/arch/sparc64/kernel/auxio.c
@@ -4,6 +4,9 @@
*/
#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
#include <linux/init.h>
#include <asm/oplib.h>
#include <asm/io.h>
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
index d6cdf9162..2c96a83e9 100644
--- a/arch/sparc64/kernel/cpu.c
+++ b/arch/sparc64/kernel/cpu.c
@@ -6,6 +6,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
#include <asm/asi.h>
#include <asm/system.h>
#include <asm/fpumacro.h>
@@ -56,12 +58,7 @@ __initfunc(void cpu_probe(void))
long ver, fpu_vers;
long fprs;
-#ifndef __SMP__
- cpuid = 0;
-#else
-#error SMP not supported on sparc64 yet
- /* cpuid = get_cpuid(); */
-#endif
+ cpuid = smp_processor_id();
fprs = fprs_read ();
fprs_write (FPRS_FEF);
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 5e6705896..9327058a8 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -13,7 +13,7 @@
#include <asm/system.h>
#include <asm/smp.h>
-struct prom_cpuinfo linux_cpus[NCPUS];
+struct prom_cpuinfo linux_cpus[NR_CPUS];
int linux_num_cpus = 0;
extern void cpu_probe(void);
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index a410cfe80..425c2d873 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.50 1997/07/15 16:53:00 davem Exp $
+/* $Id: entry.S,v 1.51 1997/07/24 12:15:04 davem Exp $
* arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points.
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -206,7 +206,7 @@ fpdis_exit:
* flushing very quickly.
*/
.align 32
- .globl do_ivec
+ .globl do_ivec, do_ivec_return
do_ivec:
ldxa [%g0] ASI_INTR_RECEIVE, %g1
andcc %g1, 0x20, %g0
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index b7a0f312d..81eb45e42 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.13 1997/07/17 02:20:38 davem Exp $
+/* $Id: ioctl32.c,v 1.14 1997/07/17 06:21:12 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -30,6 +30,7 @@
#include <asm/kbio.h>
#include <asm/vuid_event.h>
#include <asm/rtc.h>
+#include <asm/openpromio.h>
/* As gcc will warn about casting u32 to some ptr, we have to cast it to
* unsigned long first, and that's what is A() for.
@@ -697,6 +698,22 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case RTCGET:
case RTCSET:
+ /* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have
+ * embedded pointers in the arg which we'd need to clean up...
+ */
+ case OPROMGETOPT:
+ case OPROMSETOPT:
+ case OPROMNXTOPT:
+ case OPROMSETOPT2:
+ case OPROMNEXT:
+ case OPROMCHILD:
+ case OPROMGETPROP:
+ case OPROMNXTPROP:
+ case OPROMU2P:
+ case OPROMGETCONS:
+ case OPROMGETFBNAME:
+ case OPROMGETBOOTARGS:
+
/* Socket level stuff */
case FIOSETOWN:
case SIOCSPGRP:
diff --git a/arch/sparc64/kernel/ioport.c b/arch/sparc64/kernel/ioport.c
index 390c33517..7d1580b39 100644
--- a/arch/sparc64/kernel/ioport.c
+++ b/arch/sparc64/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.10 1997/06/30 09:24:02 jj Exp $
+/* $Id: ioport.c,v 1.11 1997/07/22 06:14:04 davem Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -83,7 +83,7 @@ void sparc_free_io (void *virtual, int len)
unsigned long vaddr = (unsigned long) virtual & PAGE_MASK;
unsigned long plen = (((unsigned long)virtual & ~PAGE_MASK) + len + PAGE_SIZE-1) & PAGE_MASK;
- if (virtual >= PAGE_OFFSET + 0x10000000000UL)
+ if (((unsigned long)virtual) >= PAGE_OFFSET + 0x10000000000UL)
return;
release_region(vaddr, plen);
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index c4e7f0e74..f76c27c57 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.16 1997/07/11 03:03:08 davem Exp $
+/* $Id: irq.c,v 1.19 1997/07/24 12:15:04 davem Exp $
* irq.c: UltraSparc IRQ handling/init/registry.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -23,6 +23,7 @@
#include <asm/iommu.h>
#include <asm/upa.h>
#include <asm/oplib.h>
+#include <asm/timer.h>
#include <asm/smp.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
@@ -76,7 +77,7 @@ int get_irq_list(char *buf)
}
/* INO number to Sparc PIL level. */
-static unsigned char ino_to_pil[] = {
+unsigned char ino_to_pil[] = {
0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 0 */
0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 1 */
0, 1, 2, 3, 5, 7, 8, 9, /* SBUS slot 2 */
@@ -391,7 +392,116 @@ int __sparc64_bh_counter = 0;
#define irq_exit(cpu, irq) (local_irq_count[cpu]--)
#else
-#error SMP not supported on sparc64 just yet
+
+atomic_t __sparc64_bh_counter = ATOMIC_INIT(0);
+
+/* Who has global_irq_lock. */
+unsigned char global_irq_holder = NO_PROC_ID;
+
+/* This protects IRQ's. */
+spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
+
+/* This protects BH software state (masks, things like that). */
+spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
+
+/* Global IRQ locking depth. */
+atomic_t global_irq_count = ATOMIC_INIT(0);
+
+static inline void wait_on_irq(int cpu)
+{
+ int local_count = local_irq_count[cpu];
+
+ while(local_count != atomic_read(&global_irq_count)) {
+ atomic_sub(local_count, &global_irq_count);
+ spin_unlock(&global_irq_lock);
+ for(;;) {
+ if (atomic_read(&global_irq_count))
+ continue;
+ if (*((unsigned char *)&global_irq_lock))
+ continue;
+ if (spin_trylock(&global_irq_lock))
+ break;
+ }
+ atomic_add(local_count, &global_irq_count);
+ }
+}
+
+static inline void get_irqlock(int cpu)
+{
+ if (!spin_trylock(&global_irq_lock)) {
+ if ((unsigned char) cpu == global_irq_holder)
+ return;
+ do {
+ barrier();
+ } while (!spin_trylock(&global_irq_lock));
+ }
+ wait_on_irq(cpu);
+ global_irq_holder = cpu;
+}
+
+void __global_cli(void)
+{
+ int cpu = smp_processor_id();
+
+ __cli();
+ get_irqlock(cpu);
+}
+
+void __global_sti(void)
+{
+ release_irqlock(smp_processor_id());
+ __sti();
+}
+
+unsigned long __global_save_flags(void)
+{
+ return global_irq_holder == (unsigned char) smp_processor_id();
+}
+
+void __global_restore_flags(unsigned long flags)
+{
+ if (flags & 1) {
+ __global_cli();
+ } else {
+ if (global_irq_holder == (unsigned char) smp_processor_id()) {
+ global_irq_holder = NO_PROC_ID;
+ spin_unlock(&global_irq_lock);
+ }
+ if (!(flags & 2))
+ __sti();
+ }
+}
+
+void irq_enter(int cpu, int irq)
+{
+ hardirq_enter(cpu);
+ barrier();
+ while (*((unsigned char *)&global_irq_lock)) {
+ if ((unsigned char) cpu == global_irq_holder)
+ printk("irq_enter: Frosted Lucky Charms, "
+ "they're magically delicious!\n");
+ barrier();
+ }
+}
+
+void irq_exit(int cpu, int irq)
+{
+ hardirq_exit(cpu);
+ release_irqlock(cpu);
+}
+
+void synchronize_irq(void)
+{
+ int cpu = smp_processor_id();
+ int local_count = local_irq_count[cpu];
+ unsigned long flags;
+
+ if (local_count != atomic_read(&global_irq_count)) {
+ save_and_cli(flags);
+ restore_flags(flags);
+ }
+}
+
#endif /* __SMP__ */
void report_spurious_ivec(struct pt_regs *regs)
@@ -432,9 +542,7 @@ void handler_irq(int irq, struct pt_regs *regs)
struct irqaction *action;
int cpu = smp_processor_id();
- /* XXX */
- if(irq != 14)
- clear_softint(1 << irq);
+ clear_softint(1 << irq);
irq_enter(cpu, irq);
action = *(irq + irq_action);
@@ -575,53 +683,46 @@ int probe_irq_off(unsigned long mask)
return 0;
}
-/* XXX This is a hack, make it per-cpu so that SMP port will work correctly
- * XXX with mixed MHZ Ultras in the machine. -DaveM
- */
-static unsigned long cpu_cfreq;
-static unsigned long tick_offset;
+struct sun5_timer *linux_timers = NULL;
-/* XXX This doesn't belong here, just do this cruft in the timer.c handler code. */
-static void timer_handler(int irq, void *dev_id, struct pt_regs *regs)
+/* This is called from sbus_init() to get the jiffies timer going.
+ * We need to call this after there exists a valid SBus_chain so
+ * that the IMAP/ICLR registers can be accessed.
+ *
+ * XXX That is because the whole startup sequence is broken. I will
+ * XXX fix it all up very soon. -DaveM
+ */
+void init_timers(void (*cfunc)(int, void *, struct pt_regs *))
{
- if (!(get_softint () & 1)) {
- /* Just to be sure... */
- clear_softint(1 << 14);
- printk("Spurious level14 at %016lx\n", regs->tpc);
- return;
- } else {
- unsigned long compare, tick;
-
- do {
- extern void timer_interrupt(int, void *, struct pt_regs *);
-
- timer_interrupt(irq, dev_id, regs);
-
- /* Acknowledge INT_TIMER */
- clear_softint(1 << 0);
+ struct linux_prom64_registers pregs[3];
+ u32 pirqs[2];
+ int node, err;
- /* Set up for next timer tick. */
- __asm__ __volatile__("rd %%tick_cmpr, %0\n\t"
- "add %0, %2, %0\n\t"
- "wr %0, 0x0, %%tick_cmpr\n\t"
- "rd %%tick, %1"
- : "=&r" (compare), "=r" (tick)
- : "r" (tick_offset));
- } while(tick >= compare);
+ node = prom_finddevice("/counter-timer");
+ if(node == 0) {
+ prom_printf("init_timers: Cannot find counter-timer PROM node.\n");
+ prom_halt();
}
-}
+ err = prom_getproperty(node, "reg", (char *)&pregs[0], sizeof(pregs));
+ if(err == -1) {
+ prom_printf("init_timers: Cannot obtain 'reg' for counter-timer.\n");
+ prom_halt();
+ }
+ err = prom_getproperty(node, "interrupts", (char *)&pirqs[0], sizeof(pirqs));
+ if(err == -1) {
+ prom_printf("init_timers: Cannot obtain 'interrupts' "
+ "for counter-timer.\n");
+ prom_halt();
+ }
+ linux_timers = (struct sun5_timer *) __va(pregs[0].phys_addr);
-/* This is called from time_init() to get the jiffies timer going. */
-void init_timers(void (*cfunc)(int, void *, struct pt_regs *))
-{
- int node, err;
+ /* Shut it up first. */
+ linux_timers->limit0 = 0;
+
+ /* Register IRQ handler. */
+ err = request_irq(pirqs[0] & 0x3f, /* XXX Fix this for big Enterprise XXX */
+ cfunc, (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL);
- /* XXX FIX this for SMP -JJ */
- node = linux_cpus [0].prom_node;
- cpu_cfreq = prom_getint(node, "clock-frequency");
- tick_offset = cpu_cfreq / HZ;
- err = request_irq(14, timer_handler, (SA_INTERRUPT|SA_STATIC_ALLOC),
- "timer", NULL);
if(err) {
prom_printf("Serious problem, cannot register timer interrupt\n");
prom_halt();
@@ -630,27 +731,33 @@ void init_timers(void (*cfunc)(int, void *, struct pt_regs *))
save_and_cli(flags);
- __asm__ __volatile__("wr %0, 0x0, %%tick_cmpr\n\t"
- "wrpr %%g0, 0x0, %%tick"
- : /* No outputs */
- : "r" (tick_offset));
-
- clear_softint (get_softint ());
+ /* Set things up so user can access tick register for profiling
+ * purposes.
+ */
+ __asm__ __volatile__("
+ sethi %%hi(0x80000000), %%g1
+ sllx %%g1, 32, %%g1
+ rd %%tick, %%g2
+ add %%g2, 6, %%g2
+ andn %%g2, %%g1, %%g2
+ wrpr %%g2, 0, %%tick
+" : /* no outputs */
+ : /* no inputs */
+ : "g1", "g2");
+
+ linux_timers->limit0 =
+ (SUN5_LIMIT_ENABLE | SUN5_LIMIT_ZRESTART | SUN5_LIMIT_TOZERO |
+ (SUN5_HZ_TO_LIMIT(HZ) & SUN5_LIMIT_CMASK));
restore_flags(flags);
}
+
sti();
}
-/* We use this nowhere else, so only define it's layout here. */
-struct sun5_timer {
- volatile u32 count0, _unused0;
- volatile u32 limit0, _unused1;
- volatile u32 count1, _unused2;
- volatile u32 limit1, _unused3;
-} *prom_timers;
+struct sun5_timer *prom_timers;
-static u32 prom_limit0, prom_limit1;
+static u64 prom_limit0, prom_limit1;
static void map_prom_timers(void)
{
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 89f63f78f..afd5af8d0 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.29 1997/07/17 02:20:40 davem Exp $
+/* $Id: process.c,v 1.31 1997/07/24 12:15:05 davem Exp $
* arch/sparc64/kernel/process.c
*
* Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -50,9 +50,12 @@ asmlinkage int sys_idle(void)
return -EPERM;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
- for (;;)
+ for (;;) {
+ run_task_queue(&tq_scheduler);
schedule();
+ }
return 0;
}
@@ -61,42 +64,27 @@ asmlinkage int sys_idle(void)
/*
* the idle loop on a UltraMultiPenguin...
*/
-asmlinkage int sys_idle(void)
+asmlinkage int cpu_idle(void)
{
- if (current->pid != 0)
- return -EPERM;
-
- /* endless idle loop with no priority at all */
- current->counter = -100;
- schedule();
- return 0;
+ current->priority = -100;
+ while(1) {
+ if(tq_scheduler) {
+ lock_kernel();
+ run_task_queue(&tq_scheduler);
+ unlock_kernel();
+ }
+ current->counter = -100;
+ schedule();
+ }
}
-/* This is being executed in task 0 'user space'. */
-int cpu_idle(void *unused)
+asmlinkage int sys_idle(void)
{
- volatile int *spap = &smp_process_available;
- volatile int cval;
+ if(current->pid != 0)
+ return -EPERM;
- while(1) {
- if(0==*spap)
- continue;
- cli();
- /* Acquire exclusive access. */
- while((cval = smp_swap(spap, -1)) == -1)
- while(*spap == -1)
- ;
- if (0==cval) {
- /* ho hum, release it. */
- *spap = 0;
- sti();
- continue;
- }
- /* Something interesting happened, whee... */
- *spap = (cval - 1);
- sti();
- idle();
- }
+ cpu_idle();
+ return 0;
}
#endif
@@ -467,7 +455,11 @@ void fault_in_user_windows(struct pt_regs *regs)
* allocate the task_struct and kernel stack in
* do_fork().
*/
+#ifdef __SMP__
+extern void ret_from_smpfork(void);
+#else
extern void ret_from_syscall(void);
+#endif
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
struct task_struct *p, struct pt_regs *regs)
@@ -485,7 +477,11 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
child_trap_frame = ((char *)p) + stack_offset;
memcpy(child_trap_frame, (((struct reg_window *)regs)-1), tframe_size);
p->tss.ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;
+#ifdef __SMP__
+ p->tss.kpc = ((unsigned long) ret_from_smpfork) - 0x8;
+#else
p->tss.kpc = ((unsigned long) ret_from_syscall) - 0x8;
+#endif
p->tss.kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct reg_window));
p->tss.cwp = regs->u_regs[UREG_G0];
if(regs->tstate & TSTATE_PRIV) {
@@ -495,6 +491,10 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
p->tss.ctx = 0;
p->tss.kregs->u_regs[UREG_G6] = (unsigned long) p;
} else {
+ if(current->tss.flags & SPARC_FLAG_32BIT) {
+ sp &= 0x00000000ffffffff;
+ regs->u_regs[UREG_FP] &= 0x00000000ffffffff;
+ }
p->tss.kregs->u_regs[UREG_FP] = sp;
p->tss.flags &= ~SPARC_FLAG_KTHREAD;
p->tss.current_ds = USER_DS;
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 680baf7de..7eb47e976 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.10 1997/07/08 11:07:47 jj Exp $
+/* $Id: setup.c,v 1.11 1997/07/24 12:15:05 davem Exp $
* linux/arch/sparc64/kernel/setup.c
*
* Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu)
@@ -405,11 +405,7 @@ extern char *mmu_info(void);
int get_cpuinfo(char *buffer)
{
-#ifndef __SMP__
- int cpuid=0;
-#else
-#error SMP not supported on sparc64 yet
-#endif
+ int cpuid=smp_processor_id();
return sprintf(buffer, "cpu\t\t: %s\n"
"fpu\t\t: %s\n"
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 88d7a8ecf..77ccf40a0 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -3,6 +3,26 @@
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/tasks.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/oplib.h>
+#include <asm/spinlock.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
@@ -13,8 +33,9 @@ volatile int smp_processors_ready = 0;
unsigned long cpu_present_map = 0;
int smp_num_cpus = 1;
int smp_threads_ready = 0;
+volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
-struct cpuinfo_sparc64 cpu_data[NR_CPUS];
+struct cpuinfo_sparc cpu_data[NR_CPUS];
static unsigned char boot_cpu_id = 0;
static int smp_activated = 0;
@@ -52,11 +73,11 @@ void smp_store_cpu_info(int id)
void smp_commence(void)
{
- local_flush_cache_all();
- local_flush_tlb_all();
+ flush_cache_all();
+ flush_tlb_all();
smp_commenced = 1;
- local_flush_cache_all();
- local_flush_tlb_all();
+ flush_cache_all();
+ flush_tlb_all();
}
static void smp_setup_percpu_timer(void);
@@ -67,8 +88,8 @@ void smp_callin(void)
{
int cpuid = hard_smp_processor_id();
- local_flush_cache_all();
- local_flush_tlb_all();
+ flush_cache_all();
+ flush_tlb_all();
smp_setup_percpu_timer();
@@ -76,7 +97,7 @@ void smp_callin(void)
smp_store_cpu_info(cpuid);
callin_flag = 1;
__asm__ __volatile__("membar #Sync\n\t"
- "flush %g6" : : : "memory");
+ "flush %%g6" : : : "memory");
while(!task[cpuid])
barrier();
@@ -103,11 +124,18 @@ int start_secondary(void *unused)
return cpu_idle(NULL);
}
+void cpu_panic(void)
+{
+ printk("CPU[%d]: Returns from cpu_idle!\n", smp_processor_id());
+ panic("SMP bolixed\n");
+}
+
extern struct prom_cpuinfo linux_cpus[NR_CPUS];
+extern unsigned long sparc64_cpu_startup;
void smp_boot_cpus(void)
{
- int cpucount = 0, i, first, prev;
+ int cpucount = 0, i;
printk("Entering UltraSMPenguin Mode...\n");
__sti();
@@ -133,15 +161,15 @@ void smp_boot_cpus(void)
continue;
if(cpu_present_map & (1 << i)) {
- extern unsigned long sparc64_cpu_startup;
- unsigned long entry = (unsigned long)&sparc_cpu_startup;
struct task_struct *p;
int timeout;
kernel_thread(start_secondary, NULL, CLONE_PID);
p = task[++cpucount];
p->processor = i;
- prom_startcpu(linux_cpus[i].prom_node, entry, i);
+ prom_startcpu(linux_cpus[i].prom_node,
+ ((unsigned long)&sparc64_cpu_startup),
+ ((unsigned long)p));
for(timeout = 0; timeout < 5000000; timeout++) {
if(cpu_callin_map[i])
break;
@@ -190,49 +218,46 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait)
barrier();
}
-/* XXX Make it fast later. */
+static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, int cpu)
+{
+ u64 result, target = (cpu_number_map[cpu] << 14) | 0x70;
+
+ __asm__ __volatile__("
+ wrpr %0, %1, %%pstate
+ wr %%g0, %2, %%asi
+ stxa %3, [0x40] %%asi
+ stxa %4, [0x50] %%asi
+ stxa %5, [0x60] %%asi
+ stxa %%g0, [%6] %%asi
+ membar #Sync"
+ : /* No outputs */
+ : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
+ "r" (data0), "r" (data1), "r" (data2), "r" (target));
+
+ /* NOTE: PSTATE_IE is still clear. */
+ do {
+ __asm__ __volatile__("ldxa [%%g0] %1, %0"
+ : "=r" (result)
+ : "i" (ASI_INTR_DISPATCH_STAT));
+ } while(result & 0x1);
+ __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
+ : : "r" (pstate));
+ if(result & 0x2)
+ panic("Penguin NACK's master!");
+}
+
void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2)
{
if(smp_processors_ready) {
- unsigned long mask;
- u64 data0 = (((unsigned long)ctx)<<32 |
- (((unsigned long)func) & 0xffffffff));
- u64 pstate;
+ unsigned long mask = (cpu_present_map & ~(1<<smp_processor_id()));
+ u64 pstate, data0 = (((u64)ctx)<<32 | (((u64)func) & 0xffffffff));
int i, ncpus = smp_num_cpus;
__asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate));
- mask = (cpu_present_map & ~(1 << smp_processor_id()));
for(i = 0; i < ncpus; i++) {
- if(mask & (1 << i)) {
- u64 target = mid<<14 | 0x70;
- u64 result;
-
- __asm__ __volatile__("
- wrpr %0, %1, %%pstate
- wrpr %%g0, %2, %%asi
- stxa %3, [0x40] %%asi
- stxa %4, [0x50] %%asi
- stxa %5, [0x60] %%asi
- stxa %%g0, [%6] %7
- membar #Sync"
- : /* No outputs */
- : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W),
- "r" (data0), "r" (data1), "r" (data2),
- "r" (target), "i" (ASI_UDB_INTR_W));
-
- /* NOTE: PSTATE_IE is still clear. */
- do {
- __asm__ __volatile__("ldxa [%%g0] %1, %0",
- : "=r" (result)
- : "i" (ASI_INTR_DISPATCH_STAT));
- } while(result & 0x1);
- __asm__ __volatile__("wrpr %0, 0x0, %%pstate"
- : : "r" (pstate));
- if(result & 0x2)
- panic("Penguin NACK's master!");
- }
+ if(mask & (1 << i))
+ xcall_deliver(data0, data1, data2, pstate, i);
}
-
/* NOTE: Caller runs local copy on master. */
}
}
@@ -246,17 +271,19 @@ extern unsigned long xcall_flush_cache_all;
void smp_flush_cache_all(void)
{
smp_cross_call(&xcall_flush_cache_all, 0, 0, 0);
+ __flush_cache_all();
}
void smp_flush_tlb_all(void)
{
smp_cross_call(&xcall_flush_tlb_all, 0, 0, 0);
+ __flush_tlb_all();
}
void smp_flush_tlb_mm(struct mm_struct *mm)
{
u32 ctx = mm->context & 0x1fff;
- if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+ if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
smp_cross_call(&xcall_flush_tlb_mm, ctx, 0, 0);
__flush_tlb_mm(ctx);
}
@@ -265,7 +292,7 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
unsigned long end)
{
u32 ctx = mm->context & 0x1fff;
- if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+ if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
smp_cross_call(&xcall_flush_tlb_range, ctx, start, end);
__flush_tlb_range(ctx, start, end);
}
@@ -275,7 +302,7 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
struct mm_struct *mm = vma->vm_mm;
u32 ctx = mm->context & 0x1fff;
- if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+ if(mm->cpu_vm_mask != (1UL << smp_processor_id()))
smp_cross_call(&xcall_flush_tlb_page, ctx, page, 0);
__flush_tlb_page(ctx, page);
}
@@ -308,12 +335,12 @@ extern void update_one_process(struct task_struct *p, unsigned long ticks,
void smp_percpu_timer_interrupt(struct pt_regs *regs)
{
int cpu = smp_processor_id();
+ int user = user_mode(regs);
- clear_profile_irq(cpu);
- if(!user_mode(regs))
- sparc_do_profile(regs->pc);
+ /* XXX clear_profile_irq(cpu); */
+ if(!user)
+ sparc64_do_profile(regs->tpc);
if(!--prof_counter[cpu]) {
- int user = user_mode(regs);
if(current->pid) {
update_one_process(current, 1, user, !user);
if(--current->counter < 0) {
@@ -344,4 +371,5 @@ static void smp_setup_percpu_timer(void)
int setup_profiling_timer(unsigned int multiplier)
{
/* XXX implement me */
+ return 0;
}
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index ad40a5fb5..df6a1c05e 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.3 1997/06/17 13:25:29 jj Exp $
+/* $Id: time.c,v 1.5 1997/07/23 11:32:06 davem Exp $
* time.c: UltraSparc timer and TOD clock support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -20,6 +20,7 @@
#include <asm/oplib.h>
#include <asm/mostek.h>
+#include <asm/timer.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -35,11 +36,17 @@ static int set_rtc_mmss(unsigned long);
* NOTE: On SUN5 systems the ticker interrupt comes in using 2
* interrupts, one at level14 and one with softint bit 0.
*/
-void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+extern struct sun5_timer *linux_timers;
+
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
/* last time the cmos clock got updated */
static long last_rtc_update=0;
+ __asm__ __volatile__("ldx [%0], %%g0"
+ : /* no outputs */
+ : "r" (&((linux_timers)->limit0)));
+
do_timer(regs);
/* Determine when to update the Mostek clock. */
@@ -239,14 +246,12 @@ __initfunc(static void clock_probe(void))
__initfunc(void time_init(void))
{
- extern void init_timers(void (*func)(int, void *, struct pt_regs *));
unsigned int year, mon, day, hour, min, sec;
struct mostek48t02 *mregs;
do_get_fast_time = do_gettimeofday;
clock_probe();
- init_timers(timer_interrupt);
mregs = mstk48t02_regs;
if(!mregs) {
@@ -266,6 +271,13 @@ __initfunc(void time_init(void))
mregs->creg &= ~MSTK_CREG_READ;
}
+extern void init_timers(void (*func)(int, void *, struct pt_regs *));
+
+__initfunc(void sun4u_start_timers(void))
+{
+ init_timers(timer_interrupt);
+}
+
static __inline__ unsigned long do_gettimeoffset(void)
{
unsigned long offset = 0;
@@ -286,16 +298,39 @@ static __inline__ unsigned long do_gettimeoffset(void)
void do_gettimeofday(struct timeval *tv)
{
- unsigned long flags;
-
- save_and_cli(flags);
- *tv = xtime;
- tv->tv_usec += do_gettimeoffset();
- if(tv->tv_usec >= 1000000) {
- tv->tv_usec -= 1000000;
- tv->tv_sec++;
- }
- restore_flags(flags);
+ /* Load doubles must be used on xtime so that what we get
+ * is guarenteed to be atomic, this is why we can run this
+ * with interrupts on full blast. Don't touch this... -DaveM
+ */
+ __asm__ __volatile__("
+ sethi %hi(linux_timers), %o1
+ sethi %hi(xtime), %g2
+ ldx [%o1 + %lo(linux_timers)], %g3
+1: ldd [%g2 + %lo(xtime)], %o4
+ ldx [%g3], %o1
+ ldd [%g2 + %lo(xtime)], %o2
+ xor %o4, %o2, %o2
+ xor %o5, %o3, %o3
+ orcc %o2, %o3, %g0
+ bne,pn %icc, 1b
+ cmp %o1, 0
+ bge,pt %icc, 1f
+ sethi %hi(tick), %o3
+ ld [%o3 + %lo(tick)], %o3
+ sethi %hi(0x1fffff), %o2
+ or %o2, %lo(0x1fffff), %o2
+ add %o5, %o3, %o5
+ and %o1, %o2, %o1
+1: add %o5, %o1, %o5
+ sethi %hi(1000000), %o2
+ or %o2, %lo(1000000), %o2
+ cmp %o5, %o2
+ bl,a,pn %icc, 1f
+ st %o4, [%o0 + 0x0]
+ add %o4, 0x1, %o4
+ sub %o5, %o2, %o5
+ st %o4, [%o0 + 0x0]
+1: st %o5, [%o0 + 0x4]");
}
void do_settimeofday(struct timeval *tv)
diff --git a/arch/sparc64/lib/locks.S b/arch/sparc64/lib/locks.S
index a1154cb6d..74054f63a 100644
--- a/arch/sparc64/lib/locks.S
+++ b/arch/sparc64/lib/locks.S
@@ -1,77 +1,77 @@
-/* $Id: locks.S,v 1.2 1997/03/10 12:28:02 jj Exp $
+/* $Id: locks.S,v 1.3 1997/07/22 05:51:42 davem Exp $
* locks.S: SMP low-level lock primitives on Sparc64.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
+#include <asm/asm_offsets.h>
#include <asm/ptrace.h>
+#include <asm/smp.h>
.text
- .align 4
-
- .globl __spinlock_waitfor
-__spinlock_waitfor:
-1: orcc %g2, 0x0, %g0
- bne 1b
- ldub [%g1], %g2
- ldstub [%g1], %g2
- jmpl %o7 - 12, %g0
- mov %g5, %o7
-
- .globl ___become_idt
-___become_idt:
-#if 0 /* Don't know how to do this on the Ultra yet... */
-#endif
- jmpl %o7 + 8, %g0
- mov %g5, %o7
+ .align 32
___lk_busy_spin:
- orcc %g2, 0, %g0
- bne ___lk_busy_spin
- ldub [%g1 + 0], %g2
- b 1f
- ldstub [%g1 + 0], %g2
+ orcc %g2, 0, %g0
+ bne,pt %icc, ___lk_busy_spin
+ ldub [%g1 + 0], %g2
+ b,pt %xcc, 1f
+ ldstub [%g1 + 0], %g2
- .globl ___lock_kernel
+ .globl ___lock_kernel
___lock_kernel:
- addcc %g2, -1, %g2
- rdpr %pil, %g3
- bcs,a 9f
- st %g2, [%g6 + AOFF_task_lock_depth]
- wrpr 15, %pil
- ldstub [%g1 + 0], %g2
-1: orcc %g2, 0, %g0
- bne,a ___lk_busy_spin
- ldub [%g1 + 0], %g2
- ldub [%g1 + 2], %g2
- cmp %g2, %g5
- be 2f
- stb %g5, [%g1 + 1]
- stb %g5, [%g1 + 2]
-#ifdef __SMP__
- /* XXX Figure out how to become interrupt receiver in SMP system. */
-#endif
-2: mov -1, %g2
- st %g2, [%g6 + AOFF_task_lock_depth]
- wrpr %g3, %pil
-9: jmpl %o7 + 0x8, %g0
- mov %g5, %o7
+ addcc %g2, -1, %g2
+ rdpr %pil, %g3
+ bcs,a,pn %icc, 9f
+ st %g2, [%g6 + AOFF_task_lock_depth]
+ wrpr %g0, 15, %pil
+ ldstub [%g1 + 0], %g2
+1: brnz,a,pn %g2, ___lk_busy_spin
+ ldub [%g1 + 0], %g2
+ lduw [%g6 + AOFF_task_processor], %g2
+ membar #LoadLoad | #LoadStore
+ stb %g2, [%g1 + 1]
+2: mov -1, %g2
+ st %g2, [%g6 + AOFF_task_lock_depth]
+ wrpr %g3, 0, %pil
+9: jmpl %o7 + 0x8, %g0
+ mov %g5, %o7
+
+ .globl ___lock_reacquire_kernel
+___lock_reacquire_kernel:
+ rdpr %pil, %g3
+ wrpr %g0, 15, %pil
+ st %g2, [%g6 + AOFF_task_lock_depth]
+ ldstub [%g1 + 0], %g2
+1: brz,pt %g2, 3f
+ ldub [%g1 + 0], %g2
+2: brnz,a,pt %g2, 2b
+ ldub [%g1 + 0], %g2
+ b,pt %xcc, 1b
+ ldstub [%g1 + 0], %g2
+3: lduw [%g6 + AOFF_task_processor], %g2
+ membar #LoadLoad | #LoadStore
+ stb %g2, [%g1 + 1]
+ wrpr %g3, 0, %pil
+ jmpl %o7 + 0x8, %g0
+ mov %g5, %o7
#undef NO_PROC_ID
#define NO_PROC_ID 0xff
- .globl ___unlock_kernel
+ .globl ___unlock_kernel
___unlock_kernel:
- addcc %g2, 1, %g2
- rdpr %pil, %g3
- bne,a 1f
- st %g2, [%g6 + AOFF_task_lock_depth]
- wrpr 15, %pil
- mov NO_PROC_ID, %g2
- stb %g2, [%g1 + 1]
- stb %g0, [%g1 + 0]
- st %g0, [%g6 + AOFF_task_lock_depth]
- wrpr %g3, %pil
-1: jmpl %o7 + 0x8, %g0
- mov %g5, %o7
+ addcc %g2, 1, %g2
+ rdpr %pil, %g3
+ bne,a,pn %icc, 1f
+ stw %g2, [%g6 + AOFF_task_lock_depth]
+ wrpr 15, %pil
+ mov NO_PROC_ID, %g2
+ stb %g2, [%g1 + 1]
+ membar #StoreStore | #LoadStore
+ stb %g0, [%g1 + 0]
+ stw %g0, [%g6 + AOFF_task_lock_depth]
+ wrpr %g3, 0, %pil
+1: jmpl %o7 + 0x8, %g0
+ mov %g5, %o7
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
index dddf3153b..72f4fa079 100644
--- a/arch/sparc64/mm/Makefile
+++ b/arch/sparc64/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 1997/06/27 14:53:38 jj Exp $
+# $Id: Makefile,v 1.4 1997/07/24 12:15:08 davem Exp $
# Makefile for the linux Sparc64-specific parts of the memory manager.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -7,12 +7,24 @@
#
# Note 2! The CFLAGS definition is now in the main makefile...
+ifdef SMP
+
+.S.s:
+ $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
+
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
+
+else
+
.S.s:
$(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
.S.o:
$(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
+endif
+
O_TARGET := mm.o
O_OBJS := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index a8d903b25..386c8540f 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.39 1997/07/07 02:50:57 davem Exp $
+/* $Id: init.c,v 1.40 1997/07/24 16:48:27 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -431,8 +431,17 @@ void prom_reload_locked(void)
membar("#Sync");
}
+void __flush_cache_all(void)
+{
+ unsigned long va;
+
+ flushw_all();
+ for(va = 0; va < (PAGE_SIZE << 1); va += 32)
+ spitfire_put_icache_tag(va, 0x0);
+}
+
/* If not locked, zap it. */
-void flush_tlb_all(void)
+void __flush_tlb_all(void)
{
unsigned long flags;
int i;
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index b11903a25..18f9a363d 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -1,10 +1,11 @@
-/* $Id: ultra.S,v 1.1 1997/07/18 06:26:55 ralf Exp $
+/* $Id: ultra.S,v 1.9 1997/07/24 12:15:08 davem Exp $
* ultra.S: Don't expand these all over the place...
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
*/
#include <asm/asi.h>
+#include <asm/pgtable.h>
#include <asm/spitfire.h>
/* All callers check mm->context != NO_CONTEXT for us. */
diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c
index a4aea63b8..40b33da4b 100644
--- a/arch/sparc64/prom/console.c
+++ b/arch/sparc64/prom/console.c
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.6 1997/03/18 17:59:59 jj Exp $
+/* $Id: console.c,v 1.7 1997/07/19 08:28:29 ecd Exp $
* console.c: Routines that deal with sending and receiving IO
* to/from the current console device using the PROM.
*
@@ -88,6 +88,7 @@ prom_query_input_device()
if(strncmp(propb, "serial", sizeof("serial")))
return PROMDEV_I_UNK;
/* FIXME: Is there any better way how to find out? */
+ memset(propb, 0, sizeof(propb));
st_p = prom_finddevice ("/options");
prom_getproperty(st_p, "input-device", propb, sizeof(propb));
if (strncmp (propb, "tty", 3) || !propb[3] || propb[4])
@@ -116,6 +117,7 @@ prom_query_output_device()
if(strncmp("serial", propb, sizeof("serial")))
return PROMDEV_O_UNK;
/* FIXME: Is there any better way how to find out? */
+ memset(propb, 0, sizeof(propb));
st_p = prom_finddevice ("/options");
prom_getproperty(st_p, "output-device", propb, sizeof(propb));
if (strncmp (propb, "tty", 3) || !propb[3] || propb[4])
diff --git a/arch/sparc64/prom/misc.c b/arch/sparc64/prom/misc.c
index 8b738fd41..9720f1a70 100644
--- a/arch/sparc64/prom/misc.c
+++ b/arch/sparc64/prom/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.8 1997/07/14 23:45:28 davem Exp $
+/* $Id: misc.c,v 1.9 1997/07/24 12:15:11 davem Exp $
* misc.c: Miscellaneous prom functions that don't belong
* anywhere else.
*
@@ -135,7 +135,7 @@ void prom_set_trap_table(unsigned long tba)
}
#ifdef __SMP__
-void prom_start_cpu(int cpunode, unsigned long pc, unsigned long o0)
+void prom_startcpu(int cpunode, unsigned long pc, unsigned long o0)
{
p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, o0);
}
diff --git a/arch/sparc64/prom/p1275.c b/arch/sparc64/prom/p1275.c
index 18de40deb..0703b5cd7 100644
--- a/arch/sparc64/prom/p1275.c
+++ b/arch/sparc64/prom/p1275.c
@@ -1,4 +1,4 @@
-/* $Id: p1275.c,v 1.10 1997/06/27 04:18:30 davem Exp $
+/* $Id: p1275.c,v 1.11 1997/07/24 12:15:11 davem Exp $
* p1275.c: Sun IEEE 1275 PROM low level interface routines
*
* Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -6,6 +6,8 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
#include <linux/string.h>
#include <asm/openprom.h>