summaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Makefile74
-rw-r--r--arch/alpha/boot/Makefile53
-rw-r--r--arch/alpha/boot/head.S76
-rw-r--r--arch/alpha/boot/main.c217
-rw-r--r--arch/alpha/boot/tools/build.c173
-rw-r--r--arch/alpha/config.in95
-rw-r--r--arch/alpha/kernel/Makefile47
-rw-r--r--arch/alpha/kernel/bios32.c478
-rw-r--r--arch/alpha/kernel/entry.S554
-rw-r--r--arch/alpha/kernel/head.S97
-rw-r--r--arch/alpha/kernel/irq.c414
-rw-r--r--arch/alpha/kernel/lca.c304
-rw-r--r--arch/alpha/kernel/osf_sys.c494
-rw-r--r--arch/alpha/kernel/process.c186
-rw-r--r--arch/alpha/kernel/setup.c172
-rw-r--r--arch/alpha/kernel/signal.c319
-rw-r--r--arch/alpha/kernel/traps.c159
-rw-r--r--arch/alpha/lib/Makefile38
-rw-r--r--arch/alpha/lib/divide.S160
-rw-r--r--arch/alpha/lib/io.c98
-rw-r--r--arch/alpha/lib/memcpy.c74
-rw-r--r--arch/alpha/lib/memset.c44
-rw-r--r--arch/alpha/mm/Makefile32
-rw-r--r--arch/alpha/mm/fault.c100
-rw-r--r--arch/alpha/mm/init.c204
25 files changed, 4550 insertions, 112 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index 35800431a..beff9f4ed 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -8,70 +8,28 @@
# Copyright (C) 1994 by Linus Torvalds
#
-AS =as
-LD =ld
-HOSTCC =gcc -I$(TOPDIR)/include
-CC =gcc -D__KERNEL__ -I$(TOPDIR)/include
-MAKE =make
-CPP =$(CC) -E
-AR =ar
-STRIP =strip
+NM := nm -B
-zBoot/zSystem: zBoot/*.c zBoot/*.S tools/zSystem
- $(MAKE) -C zBoot
+LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
+CFLAGS := $(CFLAGS) -mno-fp-regs
-zImage: $(CONFIGURE) boot/bootsect boot/setup zBoot/zSystem tools/build
- tools/build boot/bootsect boot/setup zBoot/zSystem $(ROOT_DEV) > zImage
- sync
+HEAD := arch/alpha/kernel/head.o
-zdisk: zImage
- dd bs=8192 if=zImage of=/dev/fd0
+SUBDIRS := $(SUBDIRS) arch/alpha/kernel arch/alpha/mm arch/alpha/lib
+ARCHIVES := arch/alpha/kernel/kernel.o arch/alpha/mm/mm.o $(ARCHIVES)
+LIBS := $(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a
-zlilo: $(CONFIGURE) zImage
- if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
- if [ -f $(INSTALL_PATH)/zSystem.map ]; then mv $(INSTALL_PATH)/zSystem.map $(INSTALL_PATH)/zSystem.old; fi
- cat zImage > $(INSTALL_PATH)/vmlinuz
- cp zSystem.map $(INSTALL_PATH)/
- if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-tools/system: boot/head.o init/main.o tools/version.o linuxsubdirs
- $(LD) $(LOWLDFLAGS) boot/head.o init/main.o tools/version.o \
- $(ARCHIVES) \
- $(FILESYSTEMS) \
- $(DRIVERS) \
- $(LIBS) \
- -o tools/system
- nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
- sort > System.map
-
-boot/setup.o: boot/setup.s
- $(AS) -o $@ $<
-
-boot/setup.s: boot/setup.S $(CONFIGURE) include/linux/config.h Makefile
- $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
-
-boot/bootsect.s: boot/bootsect.S $(CONFIGURE) include/linux/config.h Makefile
- $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
-
-tools/zSystem: boot/head.o init/main.o tools/version.o linuxsubdirs
- $(LD) $(HIGHLDFLAGS) boot/head.o init/main.o tools/version.o \
- $(ARCHIVES) \
- $(FILESYSTEMS) \
- $(DRIVERS) \
- $(LIBS) \
- -o tools/zSystem
- nm tools/zSystem | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | \
- sort > zSystem.map
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
#
-# Leave these dummy entries for now to tell people that they are going away..
+# my boot writes directly to a specific disk partition, I doubt most
+# people will want to do that without changes..
#
-lilo:
- @echo
- @echo Uncompressed kernel images no longer supported. Use
- @echo \"make zlilo\" instead.
- @echo
- @exit 1
+msb my-special-boot:
+ @$(MAKEBOOT) msb
archclean:
- rm -f boot/bootsect boot/setup
+ @$(MAKEBOOT) clean
+
+archdep:
+ @$(MAKEBOOT) dep
diff --git a/arch/alpha/boot/Makefile b/arch/alpha/boot/Makefile
new file mode 100644
index 000000000..b05047c2a
--- /dev/null
+++ b/arch/alpha/boot/Makefile
@@ -0,0 +1,53 @@
+#
+# arch/alpha/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.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+.c.s:
+ $(CC) $(CFLAGS) -S -o $*.s $<
+.s.o:
+ $(AS) -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c -o $*.o $<
+.S.s:
+ $(CC) -D__ASSEMBLY__ -traditional -E -o $*.o $<
+.S.o:
+ $(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
+
+OBJECTS = head.o main.o
+
+all: tools/lxboot tools/bootlx vmlinux
+ @echo run mkfloppy on machine with floppy drive
+
+msb: tools/lxboot tools/bootlx vmlinux
+ ( cat tools/lxboot tools/bootlx vmlinux ) > /dev/rz0a
+ disklabel -rw rz0 'linux' tools/lxboot tools/bootlx
+
+vmlinux: tools/build $(TOPDIR)/vmlinux
+ tools/build -v $(TOPDIR)/vmlinux > vmlinux
+
+tools/lxboot: tools/build
+ tools/build > tools/lxboot
+
+tools/bootlx: bootloader tools/build
+ tools/build -vb bootloader > tools/bootlx
+
+tools/build: tools/build.c
+ $(HOSTCC) tools/build.c -o tools/build
+
+bootloader: $(OBJECTS)
+ $(LD) -non_shared -T 0x20000000 -N \
+ $(OBJECTS) \
+ $(LIBS) \
+ -o bootloader || \
+ (rm -f bootloader && exit 1)
+
+clean:
+ rm -f vmlinux bootloader tools/build tools/bootlx tools/lxboot
+
+dep:
diff --git a/arch/alpha/boot/head.S b/arch/alpha/boot/head.S
index 03a2a9010..efca165e6 100644
--- a/arch/alpha/boot/head.S
+++ b/arch/alpha/boot/head.S
@@ -1,44 +1,23 @@
/*
- * alpha/head.S
+ * arch/alpha/boot/head.S
*
- * initial boot stuff..
+ * initial bootloader stuff..
*/
#include <asm/system.h>
#define halt .long PAL_halt
-/*
- * NOTE! The console bootstrap will load us at 0x20000000, but this image
- * is linked to run at START_ADDR, so the first thing we do is to move
- * ourself up to the right address.. We'd better be position-independent
- * at that stage :-)
- */
.set noreorder
.globl __start
.ent __start
__start:
bis $31,$31,$31
- br $1,$200
- .long START_ADDR, START_ADDR >> 32 /* strange bug in the assembler.. duh */
- .long START_SIZE, START_SIZE >> 32
-$200: ldq $30,0($1) /* new stack - below this */
- lda $2,-8($1) /* __start */
- bis $30,$30,$3 /* new address */
- subq $3,$2,$6 /* difference */
- ldq $4,8($1) /* size */
-$201: subq $4,8,$4
- ldq $5,0($2)
- addq $2,8,$2
- stq $5,0($3)
- addq $3,8,$3
- bne $4,$201
- br $1,$202
-$202: addq $1,$6,$1
- addq $1,12,$1 /* $203 in the new address space */
- jmp $31,($1),$203
-$203: br $27,$100
-$100: ldgp $29,0($27)
+ br 1f
+ /* room for the initial PCB, which comes here */
+ .quad 0,0,0,0,0,0,0,0
+1: br $27,2f
+2: ldgp $29,0($27)
lda $27,start_kernel
jsr $26,($27),start_kernel
halt
@@ -109,3 +88,44 @@ switch_to_osf_pal:
__do_swppal:
.long PAL_swppal
.end switch_to_osf_pal
+
+.globl dispatch
+.ent dispatch
+dispatch:
+ subq $30,80,$30
+ stq $26,0($30)
+ stq $29,8($30)
+
+ stq $8,16($30)
+ stq $9,24($30)
+ stq $10,32($30)
+ stq $11,40($30)
+ stq $12,48($30)
+ stq $13,56($30)
+ stq $14,64($30)
+ stq $15,72($30)
+
+ lda $1,0x10000000 /* hwrpb */
+ ldq $2,0xc0($1) /* crb offset */
+ addq $2,$1,$2 /* crb */
+ ldq $27,0($2) /* dispatch procedure value */
+
+ ldq $2,8($27) /* dispatch call address */
+ jsr $26,($2) /* call it (weird VMS call seq) */
+
+ ldq $26,0($30)
+ ldq $29,8($30)
+
+ ldq $8,16($30)
+ ldq $9,24($30)
+ ldq $10,32($30)
+ ldq $11,40($30)
+ ldq $12,48($30)
+ ldq $13,56($30)
+ ldq $14,64($30)
+ ldq $15,72($30)
+
+ addq $30,80,$30
+ ret $31,($26)
+.end dispatch
+
diff --git a/arch/alpha/boot/main.c b/arch/alpha/boot/main.c
new file mode 100644
index 000000000..d122eb6f6
--- /dev/null
+++ b/arch/alpha/boot/main.c
@@ -0,0 +1,217 @@
+/*
+ * arch/alpha/boot/main.c
+ *
+ * Copyright (C) 1994, 1995 Linus Torvalds
+ *
+ * This file is the bootloader for the Linux/AXP kernel
+ */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/version.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/console.h>
+#include <asm/hwrpb.h>
+
+#include <stdarg.h>
+
+extern int vsprintf(char *, const char *, va_list);
+extern unsigned long switch_to_osf_pal(unsigned long nr,
+ struct pcb_struct * pcb_va, struct pcb_struct * pcb_pa,
+ unsigned long vptb, unsigned long *kstk);
+
+int printk(const char * fmt, ...)
+{
+ va_list args;
+ int i;
+ static char buf[1024];
+
+ va_start(args, fmt);
+ i = vsprintf(buf, fmt, args);
+ va_end(args);
+ puts(buf,i);
+ return i;
+}
+
+#define hwrpb (*INIT_HWRPB)
+
+/*
+ * Find a physical address of a virtual object..
+ *
+ * This is easy using the virtual page table address.
+ */
+struct pcb_struct * find_pa(unsigned long *vptb, struct pcb_struct * pcb)
+{
+ unsigned long address = (unsigned long) pcb;
+ unsigned long result;
+
+ result = vptb[address >> 13];
+ result >>= 32;
+ result <<= 13;
+ result |= address & 0x1fff;
+ return (struct pcb_struct *) result;
+}
+
+/*
+ * This function moves into OSF/1 pal-code, and has a temporary
+ * PCB for that. The kernel proper should replace this PCB with
+ * the real one as soon as possible.
+ *
+ * The page table muckery in here depends on the fact that the boot
+ * code has the L1 page table identity-map itself in the second PTE
+ * in the L1 page table. Thus the L1-page is virtually addressable
+ * itself (through three levels) at virtual address 0x200802000.
+ *
+ * As we don't want it there anyway, we also move the L1 self-map
+ * up as high as we can, so that the last entry in the L1 page table
+ * maps the page tables.
+ *
+ * As a result, the OSF/1 pal-code will instead use a virtual page table
+ * map located at 0xffffffe00000000.
+ */
+#define pcb_va ((struct pcb_struct *) 0x20000000)
+#define old_vptb (0x0000000200000000UL)
+#define new_vptb (0xfffffffe00000000UL)
+void pal_init(void)
+{
+ unsigned long i, rev, sum;
+ unsigned long *L1, *l;
+ struct percpu_struct * percpu;
+ struct pcb_struct * pcb_pa;
+
+ /* Find the level 1 page table and duplicate it in high memory */
+ L1 = (unsigned long *) 0x200802000UL; /* (1<<33 | 1<<23 | 1<<13) */
+ L1[1023] = L1[1];
+
+ percpu = (struct percpu_struct *) (hwrpb.processor_offset + (unsigned long) &hwrpb),
+
+ pcb_va->ksp = 0;
+ pcb_va->usp = 0;
+ pcb_va->ptbr = L1[1] >> 32;
+ pcb_va->asn = 0;
+ pcb_va->pcc = 0;
+ pcb_va->unique = 0;
+ pcb_va->flags = 1;
+ pcb_pa = find_pa((unsigned long *) old_vptb, pcb_va);
+ printk("Switching to OSF PAL-code .. ");
+ /*
+ * a0 = 2 (OSF)
+ * a1 = return address, but we give the asm the virtual addr of the PCB
+ * a2 = physical addr of PCB
+ * a3 = new virtual page table pointer
+ * a4 = KSP (but we give it 0, asm sets it)
+ */
+ i = switch_to_osf_pal(
+ 2,
+ pcb_va,
+ pcb_pa,
+ new_vptb,
+ 0);
+ if (i) {
+ printk("failed, code %ld\n", i);
+ halt();
+ }
+ rev = percpu->pal_revision = percpu->palcode_avail[2];
+
+ hwrpb.vptb = new_vptb;
+
+ /* update checksum: */
+ sum = 0;
+ for (l = (unsigned long *) &hwrpb; l < (unsigned long *) &hwrpb.chksum; ++l)
+ sum += *l;
+ hwrpb.chksum = sum;
+
+ printk("Ok (rev %lx)\n", rev);
+ /* remove the old virtual page-table mapping */
+ L1[1] = 0;
+ invalidate_all();
+}
+
+extern int _end;
+
+static inline long openboot(void)
+{
+ char bootdev[256];
+ long result;
+
+ result = dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
+ if (result < 0)
+ return result;
+ return dispatch(CCB_OPEN, bootdev, result & 255);
+}
+
+static inline long close(long dev)
+{
+ return dispatch(CCB_CLOSE, dev);
+}
+
+static inline long load(long dev, unsigned long addr, unsigned long count)
+{
+ char bootfile[256];
+ long result;
+
+ result = dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
+ if (result < 0)
+ return result;
+ result &= 255;
+ bootfile[result] = '\0';
+ if (result)
+ printk("Boot file specification (%s) not implemented\n", bootfile);
+ return dispatch(CCB_READ, dev, count, addr, BOOT_SIZE/512 + 1);
+}
+
+/*
+ * Start the kernel.
+ */
+static void runkernel(void)
+{
+ __asm__ __volatile__(
+ "bis %1,%1,$30\n\t"
+ "bis %0,%0,$26\n\t"
+ "ret ($26)"
+ : /* no outputs: it doesn't even return */
+ : "r" (START_ADDR),
+ "r" (PAGE_SIZE + INIT_STACK));
+}
+
+void start_kernel(void)
+{
+ long i;
+ long dev;
+ int nbytes;
+ char envval[256];
+
+ printk("Linux/AXP bootloader for Linux " UTS_RELEASE "\n");
+ if (hwrpb.pagesize != 8192) {
+ printk("Expected 8kB pages, got %ldkB\n", hwrpb.pagesize >> 10);
+ return;
+ }
+ pal_init();
+ dev = openboot();
+ if (dev < 0) {
+ printk("Unable to open boot device: %016lx\n", dev);
+ return;
+ }
+ dev &= 0xffffffff;
+ printk("Loading vmlinux ...");
+ i = load(dev, START_ADDR, START_SIZE);
+ close(dev);
+ if (i != START_SIZE) {
+ printk("Failed (%lx)\n", i);
+ return;
+ }
+
+ nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
+ envval, sizeof(envval));
+ if (nbytes > 0) {
+ envval[nbytes] = '\0';
+ strcpy((char*)ZERO_PGE, envval);
+ }
+
+ printk(" Ok\nNow booting the kernel\n");
+ runkernel();
+ for (i = 0 ; i < 0x100000000 ; i++)
+ /* nothing */;
+ halt();
+}
diff --git a/arch/alpha/boot/tools/build.c b/arch/alpha/boot/tools/build.c
new file mode 100644
index 000000000..040655a54
--- /dev/null
+++ b/arch/alpha/boot/tools/build.c
@@ -0,0 +1,173 @@
+/*
+ * arch/alpha/boot/tools/build.c
+ *
+ * Build a bootable image from the vmlinux binary
+ */
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+
+#include <asm/system.h>
+
+#define MAXSECT 10
+#define MAXBUF 8192
+
+int verbose = 0;
+int pad = 0;
+char * program = "tools/build";
+char buffer[MAXBUF];
+unsigned long bootblock[64];
+struct filehdr fhdr;
+struct aouthdr ahdr;
+struct scnhdr shdr[MAXSECT];
+
+char * usage = "'build [-b] system > secondary' or 'build > primary'";
+
+static void die(char * str)
+{
+ fprintf(stderr,"%s: %s\n", program, str);
+ exit(1);
+}
+
+static int comp(struct scnhdr * a, struct scnhdr * b)
+{
+ return a->s_vaddr - b->s_vaddr;
+}
+
+int main(int argc, char ** argv)
+{
+ int fd, i;
+ unsigned long tmp, start;
+ unsigned long system_start, system_size;
+ char * infile = NULL;
+
+ system_start = START_ADDR;
+ system_size = START_SIZE;
+ if (argc) {
+ program = *(argv++);
+ argc--;
+ }
+ while (argc > 0) {
+ if (**argv == '-') {
+ while (*++*argv) {
+ switch (**argv) {
+ case 'b':
+ system_start = BOOT_ADDR;
+ system_size = BOOT_SIZE;
+ pad = 1;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ die(usage);
+ }
+ }
+ } else if (infile)
+ die(usage);
+ else
+ infile = *argv;
+ argv++;
+ argc--;
+ }
+ if (!infile) {
+ memcpy(bootblock, "Linux Test", 10);
+ bootblock[60] = BOOT_SIZE / 512; /* count */
+ bootblock[61] = 1; /* starting LBM */
+ bootblock[62] = 0; /* flags */
+ tmp = 0;
+ for (i = 0 ; i < 63 ; i++)
+ tmp += bootblock[i];
+ bootblock[63] = tmp;
+ if (write(1, (char *) bootblock, 512) != 512) {
+ perror("bbwrite");
+ exit(1);
+ }
+ return 0;
+ }
+ fd = open(infile, O_RDONLY);
+ if (fd < 0) {
+ perror(infile);
+ exit(1);
+ }
+ if (read(fd, &fhdr, sizeof(struct filehdr)) != sizeof(struct filehdr))
+ die("unable to read file header");
+ if (fhdr.f_nscns > MAXSECT)
+ die("Too many sections");
+ if (fhdr.f_opthdr != AOUTHSZ)
+ die("optional header doesn't look like a.out");
+ if (read(fd, &ahdr, sizeof(struct aouthdr)) != sizeof(struct aouthdr))
+ die("unable to read a.out header");
+ for (i = 0 ; i < fhdr.f_nscns ; i++) {
+ if (read(fd, i+shdr, sizeof(struct scnhdr)) != sizeof(struct scnhdr))
+ die("unable to read section header");
+ if (shdr[i].s_paddr != shdr[i].s_vaddr)
+ die("unable to handle different phys/virt addresses");
+ if (shdr[i].s_relptr)
+ die("Unable to handle relocation info");
+ if (verbose) {
+ fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n",
+ i, shdr[i].s_name,
+ shdr[i].s_vaddr,
+ shdr[i].s_vaddr + shdr[i].s_size,
+ shdr[i].s_scnptr);
+ }
+ }
+ qsort(shdr, fhdr.f_nscns, sizeof(shdr[1]), comp);
+ start = system_start;
+ for (i = 0 ; i < fhdr.f_nscns ; i++) {
+ unsigned long size, offset;
+ memset(buffer, 0, MAXBUF);
+ if (!strcmp(shdr[i].s_name, ".comment"))
+ continue;
+ if (shdr[i].s_vaddr != start)
+ die("Unordered or badly placed segments");
+ size = shdr[i].s_size;
+ start += size;
+ offset = shdr[i].s_scnptr;
+ if (lseek(fd, offset, SEEK_SET) != offset)
+ die("Unable to seek in in-file");
+ while (size > 0) {
+ unsigned long num = size;
+ if (num > MAXBUF)
+ num = MAXBUF;
+ if (offset)
+ if (read(fd, buffer, num) != num)
+ die("partial read");
+ if (write(1, buffer, num) != num)
+ die("partial write");
+ size -= num;
+ }
+ if (verbose) {
+ fprintf(stderr, "section %d (%.8s):\t%lx - %lx (at %x)\n",
+ i, shdr[i].s_name,
+ shdr[i].s_vaddr,
+ shdr[i].s_vaddr + shdr[i].s_size,
+ shdr[i].s_scnptr);
+ }
+ }
+ if (start > system_start + system_size) {
+ fprintf(stderr, "Boot image too large\n");
+ exit(1);
+ }
+ if (pad) {
+ unsigned long count = (system_start + system_size) - start;
+ memset(buffer, 0, MAXBUF);
+ while (count > 0) {
+ int i = MAXBUF;
+ if (i > count)
+ i = count;
+ i = write(1, buffer, i);
+ if (i <= 0) {
+ perror("pad write");
+ exit(1);
+ }
+ count -= i;
+ }
+ }
+
+ return 0;
+}
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index fef727364..8906e8c8c 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -5,17 +5,38 @@
comment 'General setup'
-bool 'Normal harddisk support' CONFIG_BLK_DEV_HD n
+bool 'Normal floppy disk support' CONFIG_BLK_DEV_FD y
+bool 'Normal (MFM/RLL) disk and IDE disk/cdrom support' CONFIG_ST506 n
+if [ "$CONFIG_ST506" = "y" ]; then
+ comment 'Please see drivers/block/README.ide for help/info on IDE drives'
+ bool ' Use old (reliable) disk-only driver for primary i/f' CONFIG_BLK_DEV_HD n
+ if [ "$CONFIG_BLK_DEV_HD" = "y" ]; then
+ bool ' Include new IDE driver for secondary i/f support' CONFIG_BLK_DEV_IDE n
+ else
+ bool ' Use new IDE driver for primary/secondary i/f' CONFIG_BLK_DEV_IDE y
+ fi
+ if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
+ bool ' Include support for IDE/ATAPI CDROMs' CONFIG_BLK_DEV_IDECD n
+ fi
+fi
+
bool 'XT harddisk support' CONFIG_BLK_DEV_XD n
bool 'Networking support' CONFIG_NET y
-bool 'System V IPC' CONFIG_SYSVIPC y
+bool 'PCI alpha motherboard' CONFIG_PCI n
+bool 'System V IPC' CONFIG_SYSVIPC n
bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
+comment 'Loadable module support'
+bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS n
+
if [ "$CONFIG_NET" = "y" ]; then
comment 'Networking options'
bool 'TCP/IP networking' CONFIG_INET y
-if [ "$CONFIG_INET" "=" "y" ]; then
+if [ "$CONFIG_INET" = "y" ]; then
bool 'IP forwarding/gatewaying' CONFIG_IP_FORWARD n
+bool 'IP multicasting' CONFIG_IP_MULTICAST n
+bool 'IP firewalling' CONFIG_IP_FIREWALL n
+bool 'IP accounting' CONFIG_IP_ACCT n
comment '(it is safe to leave these untouched)'
bool 'PC/TCP compatibility mode' CONFIG_INET_PCTCP n
bool 'Reverse ARP' CONFIG_INET_RARP n
@@ -23,6 +44,7 @@ bool 'Assume subnets are local' CONFIG_INET_SNARL y
bool 'Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF n
fi
bool 'The IPX protocol' CONFIG_IPX n
+#bool 'Appletalk DDP' CONFIG_ATALK n
#bool 'Amateur Radio AX.25 Level 2' CONFIG_AX25 n
fi
@@ -38,10 +60,10 @@ else
comment 'SCSI support type (disk, tape, CDrom)'
-bool 'Scsi disk support' CONFIG_BLK_DEV_SD y
-bool 'Scsi tape support' CONFIG_CHR_DEV_ST n
-bool 'Scsi CDROM support' CONFIG_BLK_DEV_SR n
-bool 'Scsi generic support' CONFIG_CHR_DEV_SG n
+bool 'SCSI disk support' CONFIG_BLK_DEV_SD y
+bool 'SCSI tape support' CONFIG_CHR_DEV_ST n
+bool 'SCSI CDROM support' CONFIG_BLK_DEV_SR y
+bool 'SCSI generic support' CONFIG_CHR_DEV_SG n
comment 'SCSI low-level drivers'
@@ -50,18 +72,21 @@ bool 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 n
bool 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 y
bool 'Adaptec AHA274X/284X support' CONFIG_SCSI_AHA274X n
bool 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC n
+bool 'EATA-DMA (DPT,NEC&ATT for ISA,EISA,PCI) support' CONFIG_SCSI_EATA_DMA n
bool 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F n
bool 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN n
bool 'Generic NCR5380 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 n
-bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n
-bool 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 n
+if [ "$CONFIG_PCI" = "y" ]; then
+ bool 'NCR53c7,8xx SCSI support' CONFIG_SCSI_NCR53C7xx n
+fi
+bool 'Always IN2000 SCSI support (test release)' CONFIG_SCSI_IN2000 n
bool 'PAS16 SCSI support' CONFIG_SCSI_PAS16 n
bool 'QLOGIC SCSI support' CONFIG_SCSI_QLOGIC n
bool 'Seagate ST-02 and Future Domain TMC-8xx SCSI support' CONFIG_SCSI_SEAGATE n
bool 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 n
bool 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR n
bool '7000FASST SCSI support' CONFIG_SCSI_7000FASST n
-bool 'EISA EATA support' CONFIG_SCSI_EATA n
+#bool 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA n
#bool 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG n
fi
@@ -79,18 +104,19 @@ else
bool 'Dummy net driver support' CONFIG_DUMMY n
bool 'SLIP (serial line) support' CONFIG_SLIP n
if [ "$CONFIG_SLIP" = "y" ]; then
- bool ' CSLIP compressed headers' SL_COMPRESSED y
+ bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
+ bool ' 16 channels instead of 4' SL_SLIP_LOTS n
# bool ' SLIP debugging on' SL_DUMP y
fi
bool 'PPP (point-to-point) support' CONFIG_PPP n
bool 'PLIP (parallel port) support' CONFIG_PLIP n
-bool 'Load balancing support (experimental)' CONFIG_SLAVE_BALANCING n
bool 'Do you want to be offered ALPHA test drivers' CONFIG_NET_ALPHA n
bool 'Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC n
if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then
bool 'WD80*3 support' CONFIG_WD80x3 n
bool 'SMC Ultra support' CONFIG_ULTRA n
fi
+bool 'AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE n
bool '3COM cards' CONFIG_NET_VENDOR_3COM n
if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
bool '3c501 support' CONFIG_EL1 n
@@ -101,42 +127,53 @@ if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
fi
bool '3c509/3c579 support' CONFIG_EL3 y
fi
-bool 'Other ISA cards' CONFIG_NET_ISA y
+bool 'Other ISA cards' CONFIG_NET_ISA n
if [ "$CONFIG_NET_ISA" = "y" ]; then
- bool 'AT1500 and NE2100 (LANCE and PCnet-ISA) support' CONFIG_LANCE n
- bool 'Cabletron E21xx support (not recommended)' CONFIG_E2100 n
+ bool 'Cabletron E21xx support' CONFIG_E2100 n
bool 'DEPCA support' CONFIG_DEPCA y
bool 'EtherWorks 3 support' CONFIG_EWRK3 n
if [ "$CONFIG_NET_ALPHA" = "y" ]; then
- bool 'EtherExpress support' CONFIG_EEXPRESS n
+ bool 'Arcnet support' CONFIG_ARCNET n
bool 'AT1700 support' CONFIG_AT1700 n
+# bool 'EtherExpressPro support' CONFIG_EEXPRESS_PRO n
+ bool 'EtherExpress support' CONFIG_EEXPRESS n
bool 'NI5210 support' CONFIG_NI52 n
bool 'NI6510 support' CONFIG_NI65 n
+ bool 'WaveLAN support' CONFIG_WAVELAN n
fi
- bool 'HP PCLAN support' CONFIG_HPLAN n
- bool 'HP PCLAN PLUS support' CONFIG_HPLAN_PLUS n
+ bool 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS n
+ bool 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN n
bool 'NE2000/NE1000 support' CONFIG_NE2000 n
bool 'SK_G16 support' CONFIG_SK_G16 n
fi
-bool 'EISA and on board controllers' CONFIG_NET_EISA n
+bool 'EISA, VLB, PCI and on board controllers' CONFIG_NET_EISA n
+if [ "$CONFIG_NET_EISA" = "y" ]; then
if [ "$CONFIG_NET_ALPHA" = "y" ]; then
bool 'Ansel Communications EISA 3200 support' CONFIG_AC3200 n
fi
bool 'Apricot Xen-II on board ethernet' CONFIG_APRICOT n
+ bool 'DE425, DE434, DE435 support' CONFIG_DE4X5 n
+# bool 'DEC 21040 PCI support' CONFIG_DEC_ELCP n
+# bool 'LPL T100V 100Mbs support' CONFIG_LPL_T100 n
+# bool 'PCnet32 (32 bit VLB and PCI LANCE) support' CONFIG_PCNET32 n
+ bool 'Zenith Z-Note support' CONFIG_ZNET y
+fi
bool 'Pocket and portable adaptors' CONFIG_NET_POCKET n
if [ "$CONFIG_NET_POCKET" = "y" ]; then
+ bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
bool 'D-Link DE620 pocket adaptor support' CONFIG_DE620 n
- bool 'AT-LAN-TEC/RealTek pocket adaptor support' CONFIG_ATP n
- bool 'Zenith Z-Note support' CONFIG_ZNET n
+# bool 'Silicom pocket adaptor support' CONFIG_SILICOM_PEA n
+# bool 'WaveLAN PCMCIA support' CONFIG_WaveLAN n
+# bool '3 Com 3c589 PCMCIA support' CONFIG_3C589 n
fi
fi
fi
-comment 'CD-ROM drivers'
+comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
bool 'Sony CDU31A/CDU33A CDROM driver support' CONFIG_CDU31A n
-bool 'Mitsumi CDROM driver support' CONFIG_MCD n
+bool 'Mitsumi (not IDE/ATAPI) CDROM driver support' CONFIG_MCD n
bool 'Matsushita/Panasonic CDROM driver support' CONFIG_SBPCD n
if [ "$CONFIG_SBPCD" = "y" ]; then
bool 'Matsushita/Panasonic second CDROM controller support' CONFIG_SBPCD2 n
@@ -147,6 +184,8 @@ if [ "$CONFIG_SBPCD" = "y" ]; then
fi
fi
fi
+bool 'Aztech/Orchid/Okano/Wearnes (non IDE) CDROM support' CONFIG_AZTCD n
+bool 'Sony CDU535 CDROM driver support' CONFIG_CDU535 n
comment 'Filesystems'
@@ -162,7 +201,7 @@ bool '/proc filesystem support' CONFIG_PROC_FS y
if [ "$CONFIG_INET" = "y" ]; then
bool 'NFS filesystem support' CONFIG_NFS_FS y
fi
-if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" ]; then
+if [ "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_CDU31A" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_AZTCD" = "y" -o "$CONFIG_CDU535" = "y" ]; then
bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS y
else
bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
@@ -172,6 +211,7 @@ bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
comment 'character devices'
+bool 'Cyclades async mux support' CONFIG_CYCLADES n
bool 'Parallel printer support' CONFIG_PRINTER n
bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE y
@@ -180,7 +220,7 @@ bool 'C&T 82C710 mouse port support (as on TI Travelmate)' CONFIG_82C710_MOUSE y
fi
bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
-bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION n
+
bool 'QIC-02 tape support' CONFIG_QIC02_TAPE n
if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
@@ -210,6 +250,9 @@ comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
bool 'Kernel profiling support' CONFIG_PROFILE n
+if [ "$CONFIG_PROFILE" = "y" ]; then
+ int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
+fi
if [ "$CONFIG_SCSI" = "y" ]; then
-bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
+bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
fi
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
new file mode 100644
index 000000000..2843d4481
--- /dev/null
+++ b/arch/alpha/kernel/Makefile
@@ -0,0 +1,47 @@
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+.s.o:
+ $(AS) -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+.S.s:
+ $(CPP) -D__ASSEMBLY__ -traditional $< -o $*.s
+.S.o:
+ $(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+
+OBJS = entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
+ lca.o bios32.o
+
+all: kernel.o head.o
+
+head.o: head.s
+
+head.s: head.S $(TOPDIR)/include/asm-alpha/system.h
+ $(CPP) -traditional -o $*.s $<
+
+kernel.o: $(OBJS)
+ $(LD) -r -o kernel.o $(OBJS)
+ sync
+
+dep:
+ $(CPP) -M *.c > .depend
+
+dummy:
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+
diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c
new file mode 100644
index 000000000..37c566fb1
--- /dev/null
+++ b/arch/alpha/kernel/bios32.c
@@ -0,0 +1,478 @@
+#define DEBUG
+/*
+ * bios32.c - PCI BIOS functions for Alpha systems not using BIOS
+ * emulation code.
+ *
+ * Written by Dave Rusling (david.rusling@reo.mts.dec.com)
+ *
+ * Adapted to 64-bit kernel and then rewritten by David Mosberger
+ * (davidm@cs.arizona.edu)
+ *
+ * For more information, please consult
+ *
+ * PCI BIOS Specification Revision
+ * PCI Local Bus Specification
+ * PCI System Design Guide
+ *
+ * PCI Special Interest Group
+ * M/S HF3-15A
+ * 5200 N.E. Elam Young Parkway
+ * Hillsboro, Oregon 97124-6497
+ * +1 (503) 696-2000
+ * +1 (800) 433-5177
+ *
+ * Manuals are $25 each or $50 for all three, plus $7 shipping
+ * within the United States, $35 abroad.
+ */
+#include <linux/config.h>
+
+#ifndef CONFIG_PCI
+
+int pcibios_present(void)
+{
+ return 0;
+}
+
+#else /* CONFIG_PCI */
+
+#include <linux/kernel.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+
+#include <asm/hwrpb.h>
+#include <asm/io.h>
+
+
+#define KB 1024
+#define MB (1024*KB)
+#define GB (1024*MB)
+
+#define MAJOR_REV 0
+#define MINOR_REV 2
+
+/*
+ * Align VAL to ALIGN, which must be a power of two.
+ */
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+
+
+/*
+ * Temporary internal macro. If this 0, then do not write to any of
+ * the PCI registers, merely read them (i.e., use configuration as
+ * determined by SRM). The SRM seem do be doing a less than perfect
+ * job in configuring PCI devices, so for now we do it ourselves.
+ * Reconfiguring PCI devices breaks console (RPB) callbacks, but
+ * those don't work properly with 64 bit addresses anyways.
+ *
+ * The accepted convention seems to be that the console (POST
+ * software) should fully configure boot devices and configure the
+ * interrupt routing of *all* devices. In particular, the base
+ * addresses of non-boot devices need not be initialized. For
+ * example, on the AXPpci33 board, the base address a #9 GXE PCI
+ * graphics card reads as zero (this may, however, be due to a bug in
+ * the graphics card---there have been some rumor that the #9 BIOS
+ * incorrectly resets that address to 0...).
+ */
+#define PCI_MODIFY 1
+
+
+extern struct hwrpb_struct *hwrpb;
+
+
+#if PCI_MODIFY
+
+static unsigned int io_base = 64*KB; /* <64KB are (E)ISA ports */
+static unsigned int mem_base = 16*MB; /* <16MB is ISA memory */
+
+
+/*
+ * Layout memory and I/O for a device:
+ */
+static void layout_dev(struct pci_dev *dev)
+{
+ struct pci_bus *bus;
+ unsigned short cmd;
+ unsigned int base, mask, size, reg;
+
+ bus = dev->bus;
+ pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
+
+ for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
+ /*
+ * Figure out how much space and of what type this
+ * device wants.
+ */
+ pcibios_write_config_dword(bus->number, dev->devfn, reg,
+ 0xffffffff);
+ pcibios_read_config_dword(bus->number, dev->devfn, reg, &base);
+ if (!base) {
+ break; /* done with this device */
+ }
+ /*
+ * We've read the base address register back after
+ * writing all ones and so now we must decode it.
+ */
+ if (base & PCI_BASE_ADDRESS_SPACE_IO) {
+ /*
+ * I/O space base address register.
+ */
+ cmd |= PCI_COMMAND_IO;
+
+ base &= PCI_BASE_ADDRESS_IO_MASK;
+ mask = (~base << 1) | 0x1;
+ size = (mask & base) & 0xffffffff;
+ base = ALIGN(io_base, size);
+ io_base = base + size;
+ pcibios_write_config_dword(bus->number, dev->devfn,
+ reg, base | 0x1);
+ } else {
+ unsigned int type;
+ /*
+ * Memory space base address register.
+ */
+ cmd |= PCI_COMMAND_MEMORY;
+
+ type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+ mask = (~base << 1) | 0x1;
+ size = (mask & base) & 0xffffffff;
+ switch (type) {
+ case PCI_BASE_ADDRESS_MEM_TYPE_32:
+ break;
+
+ case PCI_BASE_ADDRESS_MEM_TYPE_64:
+ printk("bios32 WARNING: "
+ "ignoring 64-bit device in "
+ "slot %d, function %d: \n",
+ PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn));
+ reg += 4; /* skip extra 4 bytes */
+ continue;
+
+ case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+ /*
+ * Allocating memory below 1MB is *very*
+ * tricky, as there may be all kinds of
+ * ISA devices lurking that we don't know
+ * about. For now, we just cross fingers
+ * and hope nobody tries to do this on an
+ * Alpha (or that the console has set it
+ * up properly).
+ */
+ printk("bios32 WARNING: slot %d, function %d "
+ "requests memory below 1MB---don't "
+ "know how to do that.\n",
+ PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn));
+ continue;
+ }
+ /*
+ * The following holds at least for the Low Cost
+ * Alpha implementation of the PCI interface:
+ *
+ * In sparse memory address space, the first
+ * octant (16MB) of every 128MB segment is
+ * aliased to the the very first 16MB of the
+ * address space (i.e., it aliases the ISA
+ * memory address space). Thus, we try to
+ * avoid allocating PCI devices in that range.
+ * Can be allocated in 2nd-7th octant only.
+ * Devices that need more than 112MB of
+ * address space must be accessed through
+ * dense memory space only!
+ */
+ base = ALIGN(mem_base, size);
+ if (size > 7 * 16*MB) {
+ printk("bios32 WARNING: slot %d, function %d "
+ "requests %dB of contiguous address "
+ " space---don't use sparse memory "
+ " accesses on this device!!\n",
+ PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), size);
+ } else {
+ if (((base / 16*MB) & 0x7) == 0) {
+ base &= ~(128*MB - 1);
+ base += 16*MB;
+ base = ALIGN(base, size);
+ }
+ if (base / 128*MB != (base + size) / 128*MB) {
+ base &= ~(128*MB - 1);
+ base += (128 + 16)*MB;
+ base = ALIGN(base, size);
+ }
+ }
+ mem_base = base + size;
+ pcibios_write_config_dword(bus->number, dev->devfn,
+ reg, base);
+ }
+ }
+ /* enable device: */
+ pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
+ cmd | PCI_COMMAND_MASTER);
+}
+
+
+static void layout_bus(struct pci_bus *bus)
+{
+ unsigned int l, tio, bio, tmem, bmem;
+ struct pci_bus *child;
+ struct pci_dev *dev;
+
+ if (!bus->devices && !bus->children)
+ return;
+
+ /*
+ * Align the current bases on appropriate boundaries (4K for
+ * IO and 1MB for memory).
+ */
+ bio = io_base = ALIGN(io_base, 4*KB);
+ bmem = mem_base = ALIGN(mem_base, 1*MB);
+
+ /*
+ * Allocate space to each device:
+ */
+ for (dev = bus->devices; dev; dev = dev->sibling) {
+ if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE) {
+ layout_dev(dev);
+ }
+ }
+ /*
+ * Recursively allocate space for all of the sub-buses:
+ */
+ for (child = bus->children; child; child = child->next) {
+ layout_bus(child);
+ }
+ /*
+ * Align the current bases on 4K and 1MB boundaries:
+ */
+ tio = io_base = ALIGN(io_base, 4*KB);
+ tmem = mem_base = ALIGN(mem_base, 1*MB);
+
+ if (bus->self) {
+ struct pci_dev *bridge = bus->self;
+ /*
+ * Set up the top and bottom of the I/O memory segment
+ * for this bus.
+ */
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ 0x1c, &l);
+ l = l | (bio >> 8) | ((tio - 1) & 0xf000);
+ pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+ 0x1c, l);
+
+ l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
+ pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+ 0x20, l);
+ /*
+ * Turn off downstream PF memory address range:
+ */
+ pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+ 0x24, 0x0000ffff);
+ /*
+ * Tell bridge that there is an ISA bus in the system:
+ */
+ pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+ 0x3c, 0x00040000);
+ /*
+ * Clear status bits, enable I/O (for downstream I/O),
+ * turn on master enable (for upstream I/O), turn on
+ * memory enable (for downstream memory), turn on
+ * master enable (for upstream memory and I/O).
+ */
+ pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
+ 0x4, 0xffff0007);
+ }
+}
+
+#endif /* !PCI_MODIFY */
+
+
+/*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+ unsigned short index, unsigned char *bus,
+ unsigned char *devfn)
+{
+ unsigned int current = 0;
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->vendor == vendor && dev->device == device_id) {
+ if (current == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++current;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_class (unsigned int class_code, unsigned short index,
+ unsigned char *bus, unsigned char *devfn)
+{
+ unsigned int current = 0;
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->class == class_code) {
+ if (current == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++current;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+
+int pcibios_present(void)
+{
+ return 1;
+}
+
+
+unsigned long pcibios_init(unsigned long mem_start,
+ unsigned long mem_end)
+{
+ printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+
+#if !PCI_MODIFY
+ printk("...NOT modifying existing (SRM) PCI configuration\n");
+#endif
+ return mem_start;
+}
+
+
+/*
+ * Fixup configuration for Noname boards (AXPpci33).
+ */
+static void noname_fixup(void)
+{
+ struct pci_dev *dev;
+
+ /*
+ * The Noname board has 5 PCI slots with each of the 4
+ * interrupt pins routed to different pins on the PCI/ISA
+ * bridge (PIRQ0-PIRQ3). I don't have any information yet as
+ * to how INTB, INTC, and INTD get routed (4/12/95,
+ * davidm@cs.arizona.edu).
+ */
+ static const char pirq_tab[5][4] = {
+ { 3, -1, -1, -1}, /* slot 6 (53c810) */
+ {-1, -1, -1, -1}, /* slot 7 (PCI/ISA bridge) */
+ { 2, -1, -1, -1}, /* slot 8 (slot closest to ISA) */
+ { 1, -1, -1, -1}, /* slot 9 (middle slot) */
+ { 0, -1, -1, -1}, /* slot 10 (slot furthest from ISA) */
+ };
+ /*
+ * route_tab selects irq routing in PCI/ISA bridge so that:
+ * PIRQ0 -> irq 15
+ * PIRQ1 -> irq 9
+ * PIRQ2 -> irq 10
+ * PIRQ3 -> irq 11
+ */
+ const unsigned int route_tab = 0x0b0a090f;
+ unsigned char pin;
+ int pirq;
+
+ pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
+
+ /* ensure irq 9, 10, 11, and 15 are level sensitive: */
+ outb((1<<(9-8)) | (1<<(10-8)) | (1<<(11-8)) | (1<<(15-8)), 0x4d1);
+
+ /*
+ * Go through all devices, fixing up irqs as we see fit:
+ */
+ for (dev = pci_devices; dev; dev = dev->next) {
+ dev->irq = 0;
+ if (dev->bus->number != 0 ||
+ PCI_SLOT(dev->devfn) < 6 || PCI_SLOT(dev->devfn) > 10)
+ {
+ printk("noname_set_irq: no dev on bus %d, slot %d!!\n",
+ dev->bus->number, PCI_SLOT(dev->devfn));
+ continue;
+ }
+
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ if (!pin) {
+ if (dev->vendor == PCI_VENDOR_ID_S3 &&
+ (dev->device == PCI_DEVICE_ID_S3_864_1 ||
+ dev->device == PCI_DEVICE_ID_S3_864_2))
+ {
+ pin = 1;
+ } else {
+ continue; /* no interrupt line */
+ }
+ }
+ pirq = pirq_tab[PCI_SLOT(dev->devfn) - 6][pin - 1];
+ if (pirq < 0) {
+ continue;
+ }
+ dev->irq = (route_tab >> (8 * pirq)) & 0xff;
+#if PCI_MODIFY
+ /* tell the device: */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
+#endif
+ }
+
+#if PCI_MODIFY
+ {
+ unsigned char hostid;
+ /*
+ * SRM console version X3.9 seems to reset the SCSI
+ * host-id to 0 no matter what console environment
+ * variable pka0_host_id is set to. Thus, if the
+ * host-id reads out as a zero, we set it to 7. The
+ * SCSI controller is on the motherboard on bus 0,
+ * slot 6
+ */
+ if (pcibios_read_config_byte(0, PCI_DEVFN(6, 0), 0x84, &hostid)
+ == PCIBIOS_SUCCESSFUL && (hostid == 0))
+ {
+ pcibios_write_config_byte(0, PCI_DEVFN(6, 0),
+ 0x84, 7);
+ }
+ }
+#endif /* !PCI_MODIFY */
+}
+
+
+unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
+{
+#if PCI_MODIFY
+ /*
+ * Scan the tree, allocating PCI memory and I/O space.
+ */
+ layout_bus(&pci_root);
+#endif
+
+ /*
+ * Now is the time to do all those dirty little deeds...
+ */
+ switch (hwrpb->sys_type) {
+ case ST_DEC_AXPPCI_33: noname_fixup(); break;
+
+ default:
+ printk("pcibios_fixup: don't know how to fixup sys type %ld\n",
+ hwrpb->sys_type);
+ break;
+ }
+ return mem_start;
+}
+
+#endif /* CONFIG_PCI */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
new file mode 100644
index 000000000..b54ea220b
--- /dev/null
+++ b/arch/alpha/kernel/entry.S
@@ -0,0 +1,554 @@
+/*
+ * alpha/entry.S
+ *
+ * kernel entry-points
+ */
+
+#include <asm/system.h>
+
+#define halt .long PAL_halt
+#define rti .long PAL_rti
+
+#define NR_SYSCALLS 310
+#define osf_vfork sys_fork
+
+/*
+ * These offsets must match with "struct hae" in io.h:
+ */
+#define HAE_CACHE 0
+#define HAE_REG 8
+
+/*
+ * stack offsets
+ */
+#define SP_OFF 160
+
+#define SWITCH_STACK_SIZE 320
+
+/*
+ * task structure offsets
+ */
+#define TASK_STATE 0
+#define TASK_COUNTER 8
+#define TASK_PRIORITY 16
+#define TASK_SIGNAL 24
+#define TASK_BLOCKED 32
+#define TASK_FLAGS 40
+
+/*
+ * This defines the normal kernel pt-regs layout.
+ *
+ * regs 9-15 preserved by C code
+ * regs 16-18 saved by PAL-code
+ * regs 29-30 saved and set up by PAL-code
+ */
+#define SAVE_ALL \
+ subq $30,160,$30; \
+ stq $0,0($30); \
+ stq $1,8($30); \
+ stq $2,16($30); \
+ stq $3,24($30); \
+ stq $4,32($30); \
+ stq $5,40($30); \
+ stq $6,48($30); \
+ stq $7,56($30); \
+ stq $8,64($30); \
+ stq $19,72($30); \
+ stq $20,80($30); \
+ stq $21,88($30); \
+ stq $22,96($30); \
+ stq $23,104($30); \
+ stq $24,112($30); \
+ stq $25,120($30); \
+ stq $26,128($30); \
+ stq $27,136($30); \
+ stq $28,144($30); \
+ lda $2,hae; \
+ ldq $2,HAE_CACHE($2); \
+ stq $2,152($30)
+
+#define RESTORE_ALL \
+ lda $8,hae; \
+ ldq $7,HAE_CACHE($8); \
+ ldq $6,152($30); \
+ subq $7,$6,$5; \
+ beq $5,99f; \
+ ldq $7,HAE_REG($8); \
+ addq $31,7,$16; \
+ call_pal PAL_swpipl; \
+ stq $6,HAE_CACHE($8); \
+ stq $6,0($7); \
+ mb; \
+ bis $0,$0,$16; \
+ call_pal PAL_swpipl; \
+99:; \
+ ldq $0,0($30); \
+ ldq $1,8($30); \
+ ldq $2,16($30); \
+ ldq $3,24($30); \
+ ldq $4,32($30); \
+ ldq $5,40($30); \
+ ldq $6,48($30); \
+ ldq $7,56($30); \
+ ldq $8,64($30); \
+ ldq $19,72($30); \
+ ldq $20,80($30); \
+ ldq $21,88($30); \
+ ldq $22,96($30); \
+ ldq $23,104($30); \
+ ldq $24,112($30); \
+ ldq $25,120($30); \
+ ldq $26,128($30); \
+ ldq $27,136($30); \
+ ldq $28,144($30); \
+ addq $30,160,$30
+
+.text
+.set noat
+
+.align 3
+.globl entInt
+.ent entInt
+entInt:
+ SAVE_ALL
+/* start atomic operation with respect to software interrupts */
+ lda $0,intr_count
+ ldq $1,0($0)
+ addq $1,1,$1
+ stq $1,0($0)
+/* set up the arguments to the C interrupt handler */
+ lda $27,do_entInt
+ jsr $26,($27),do_entInt
+/* ok, check if we need to do software interrupts */
+1: lda $0,intr_count
+ ldq $1,0($0)
+ subq $1,1,$1
+ bne $1,2f /* interrupt within interrupt: return now */
+ lda $2,bh_active
+ ldq $3,0($2)
+ lda $2,bh_mask
+ ldq $2,0($2)
+ and $2,$3,$2
+ bne $2,3f
+ stq $1,0($0)
+ br $31,ret_from_sys_call
+.align 3
+2: stq $1,0($0)
+ br $31,restore_all
+.align 3
+3: lda $27,do_bottom_half
+ jsr $26,($27),do_bottom_half
+ br $31,1b
+.end entInt
+
+.align 3
+.globl entMM
+.ent entMM
+entMM:
+ SAVE_ALL
+ lda $27,do_page_fault
+ lda $26,ret_from_sys_call
+ jsr $31,($27),do_page_fault
+.end entMM
+
+.align 3
+.globl entArith
+.ent entArith
+entArith:
+ SAVE_ALL
+ lda $27,do_entArith
+ lda $26,ret_from_sys_call
+ jsr $31,($27),do_entArith
+.end entArith
+
+.align 3
+.globl entIF
+.ent entIF
+entIF:
+ SAVE_ALL
+ lda $27,do_entIF
+ lda $26,ret_from_sys_call
+ jsr $31,($27),do_entIF
+.end entIF
+
+/*
+ * Fork() is one of the special system calls: it needs to
+ * save the callee-saved regs so that the regs can be found
+ * for the new process.. We save them in the "context switch"
+ * stack format (see arch/alpha/kernel/process.c).
+ *
+ * Also, for the kernel fork, we need to fake the system call
+ * stack buildup, as we can't do system calls from kernel space.
+ */
+.align 3
+.globl kernel_fork
+.ent kernel_fork
+kernel_fork:
+ subq $30,6*8,$30
+ stq $31,0($30)
+ stq $26,8($30)
+ stq $29,16($30)
+ stq $16,24($30)
+ stq $17,32($30)
+ stq $18,40($30)
+ SAVE_ALL
+ lda $27,sys_fork
+ jsr $26,($27),sys_fork
+ br ret_from_sys_call
+.end kernel_fork
+
+.align 3
+.ent do_switch_stack
+do_switch_stack:
+ lda $30,-SWITCH_STACK_SIZE($30)
+ stq $9,0($30)
+ stq $10,8($30)
+ stq $11,16($30)
+ stq $12,24($30)
+ stq $13,32($30)
+ stq $14,40($30)
+ stq $15,48($30)
+ stq $26,56($30)
+ stt $f0,64($30)
+ stt $f1,72($30)
+ stt $f2,80($30)
+ stt $f3,88($30)
+ stt $f4,96($30)
+ stt $f5,104($30)
+ stt $f6,112($30)
+ stt $f7,120($30)
+ stt $f8,128($30)
+ stt $f9,136($30)
+ stt $f10,144($30)
+ stt $f11,152($30)
+ stt $f12,160($30)
+ stt $f13,168($30)
+ stt $f14,176($30)
+ stt $f15,184($30)
+ stt $f16,192($30)
+ stt $f17,200($30)
+ stt $f18,208($30)
+ stt $f19,216($30)
+ stt $f20,224($30)
+ stt $f21,232($30)
+ stt $f22,240($30)
+ stt $f23,248($30)
+ stt $f24,256($30)
+ stt $f25,264($30)
+ stt $f26,272($30)
+ stt $f27,280($30)
+ stt $f28,288($30)
+ stt $f29,296($30)
+ stt $f30,304($30)
+ ret $31,($0),1
+.end do_switch_stack
+
+.align 3
+.ent undo_switch_stack
+undo_switch_stack:
+ ldq $9,0($30)
+ ldq $10,8($30)
+ ldq $11,16($30)
+ ldq $12,24($30)
+ ldq $13,32($30)
+ ldq $14,40($30)
+ ldq $15,48($30)
+ ldq $26,56($30)
+ ldt $f0,64($30)
+ ldt $f1,72($30)
+ ldt $f2,80($30)
+ ldt $f3,88($30)
+ ldt $f4,96($30)
+ ldt $f5,104($30)
+ ldt $f6,112($30)
+ ldt $f7,120($30)
+ ldt $f8,128($30)
+ ldt $f9,136($30)
+ ldt $f10,144($30)
+ ldt $f11,152($30)
+ ldt $f12,160($30)
+ ldt $f13,168($30)
+ ldt $f14,176($30)
+ ldt $f15,184($30)
+ ldt $f16,192($30)
+ ldt $f17,200($30)
+ ldt $f18,208($30)
+ ldt $f19,216($30)
+ ldt $f20,224($30)
+ ldt $f21,232($30)
+ ldt $f22,240($30)
+ ldt $f23,248($30)
+ ldt $f24,256($30)
+ ldt $f25,264($30)
+ ldt $f26,272($30)
+ ldt $f27,280($30)
+ ldt $f28,288($30)
+ ldt $f29,296($30)
+ ldt $f30,304($30)
+ lda $30,SWITCH_STACK_SIZE($30)
+ ret $31,($0),1
+.end undo_switch_stack
+
+.align 3
+.globl entUna
+.ent entUna
+entUna:
+ lda $30,-256($30)
+ stq $0,0($30)
+ stq $1,8($30)
+ stq $2,16($30)
+ stq $3,24($30)
+ stq $4,32($30)
+ stq $5,40($30)
+ stq $6,48($30)
+ stq $7,56($30)
+ stq $8,64($30)
+ stq $9,72($30)
+ stq $10,80($30)
+ stq $11,88($30)
+ stq $12,96($30)
+ stq $13,104($30)
+ stq $14,112($30)
+ stq $15,120($30)
+ /* 16-18 PAL-saved */
+ stq $19,152($30)
+ stq $20,160($30)
+ stq $21,168($30)
+ stq $22,176($30)
+ stq $23,184($30)
+ stq $24,192($30)
+ stq $25,200($30)
+ stq $26,208($30)
+ stq $27,216($30)
+ stq $28,224($30)
+ stq $29,232($30)
+ stq $30,240($30)
+ stq $31,248($30)
+ lda $27,do_entUna
+ jsr $26,($27),do_entUna
+ ldq $0,0($30)
+ ldq $1,8($30)
+ ldq $2,16($30)
+ ldq $3,24($30)
+ ldq $4,32($30)
+ ldq $5,40($30)
+ ldq $6,48($30)
+ ldq $7,56($30)
+ ldq $8,64($30)
+ ldq $9,72($30)
+ ldq $10,80($30)
+ ldq $11,88($30)
+ ldq $12,96($30)
+ ldq $13,104($30)
+ ldq $14,112($30)
+ ldq $15,120($30)
+ /* 16-18 PAL-saved */
+ ldq $19,152($30)
+ ldq $20,160($30)
+ ldq $21,168($30)
+ ldq $22,176($30)
+ ldq $23,184($30)
+ ldq $24,192($30)
+ ldq $25,200($30)
+ ldq $26,208($30)
+ ldq $27,216($30)
+ ldq $28,224($30)
+ ldq $29,232($30)
+ ldq $30,240($30)
+ lda $30,256($30)
+ rti
+.end entUna
+
+.align 3
+.globl sys_fork
+.ent sys_fork
+sys_fork:
+ br $0,do_switch_stack
+ bis $30,$30,$16
+ lda $27,alpha_fork
+ jsr $26,($27),alpha_fork
+ br $0,undo_switch_stack
+ ldq $0,0($30)
+ ret $31,($26),1
+.end sys_fork
+
+.align 3
+.globl alpha_switch_to
+.ent alpha_switch_to
+alpha_switch_to:
+ br $0,do_switch_stack
+ call_pal PAL_swpctx
+ br $0,undo_switch_stack
+ ret $31,($26),1
+.end alpha_switch_to
+
+/*
+ * Oh, well.. Disassembling OSF/1 binaries to find out how the
+ * system calls work isn't much fun.
+ *
+ * entSys is special in that the PAL-code doesn't save a0-a2, so
+ * we start off by doing that by hand.
+ */
+.align 3
+.globl entSys
+.globl ret_from_sys_call
+.ent entSys
+entSys:
+ stq $16,24($30)
+ stq $17,32($30)
+ stq $18,40($30)
+ SAVE_ALL
+ lda $1,NR_SYSCALLS($31)
+ lda $2,sys_call_table
+ lda $27,do_entSys
+ cmpult $0,$1,$1
+ s8addq $0,$2,$2
+ beq $1,1f
+ ldq $27,0($2)
+1: jsr $26,($27),do_entSys
+ bis $31,$31,$1
+ bge $0,2f
+ bis $31,$31,$26 /* tell "ret_from_sys_call" that we can restart */
+ ldq $19,0($30) /* .. with this syscall nr */
+ ldq $20,72($30) /* .. and this a3 */
+ addq $31,1,$1 /* set a3 for errno return */
+ subq $31,$0,$0 /* with error in v0 */
+2: stq $0,0($30)
+ stq $1,72($30) /* a3 for return */
+.align 3
+ret_from_sys_call:
+ ldq $0,SP_OFF($30)
+ cmovne $26,0,$19
+ and $0,8,$0
+ beq $0,restore_all
+ret_from_reschedule:
+ lda $0,need_resched
+ lda $1,current
+ ldl $2,0($0)
+ lda $4,init_task
+ ldq $3,0($1)
+ bne $2,reschedule
+ subq $4,$3,$4
+ beq $4,restore_all
+ ldq $4,TASK_SIGNAL($3)
+ ldq $16,TASK_BLOCKED($3)
+ bic $4,$16,$4
+ bne $4,signal_return
+restore_all:
+ RESTORE_ALL
+ rti
+.align 3
+signal_return:
+ bis $30,$30,$17
+ br $0,do_switch_stack
+ bis $30,$30,$18
+ lda $27,do_signal
+ jsr $26,($27),do_signal
+ lda $30,SWITCH_STACK_SIZE($30)
+ br $31,restore_all
+.end entSys
+
+.align 3
+.ent reschedule
+reschedule:
+ subq $30,16,$30
+ stq $19,0($30)
+ stq $20,8($30)
+ lda $27,schedule
+ jsr $26,($27),schedule
+ ldq $19,0($30)
+ ldq $20,8($30)
+ addq $30,16,$30
+ br $31,ret_from_reschedule
+.end reschedule
+
+.align 3
+.ent sys_sigreturn
+sys_sigreturn:
+ bis $30,$30,$17
+ lda $30,-SWITCH_STACK_SIZE($30)
+ bis $30,$30,$18
+ lda $27,do_sigreturn
+ jsr $26,($27),do_sigreturn
+ br $0,undo_switch_stack
+ br $31,ret_from_sys_call
+.end sys_sigreturn
+
+.align 3
+.ent sys_sigsuspend
+sys_sigsuspend:
+ bis $30,$30,$17
+ br $0,do_switch_stack
+ bis $30,$30,$18
+ lda $27,do_sigsuspend
+ jsr $26,($27),do_sigsuspend
+ lda $30,SWITCH_STACK_SIZE($30)
+ br $31,ret_from_sys_call
+.end sys_sigreturn
+
+ .align 3
+ .globl sys_call_table
+sys_call_table:
+/*0*/ .quad do_entSys, sys_exit, sys_fork, sys_read, sys_write
+ .quad do_entSys, sys_close, sys_wait4, do_entSys, sys_link
+ .quad sys_unlink, do_entSys, sys_chdir, sys_fchdir, sys_mknod
+ .quad sys_chmod, sys_chown, sys_brk, do_entSys, sys_lseek
+ .quad sys_getxpid, osf_mount, osf_umount, sys_setuid, sys_getxuid
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, sys_access, do_entSys
+ .quad do_entSys, sys_sync, sys_kill, do_entSys, sys_setpgid
+ .quad do_entSys, sys_dup, sys_pipe, do_entSys, do_entSys
+ .quad sys_open, do_entSys, sys_getxgid, osf_sigprocmask, do_entSys
+/*50*/ .quad do_entSys, do_entSys, do_entSys, do_entSys, sys_ioctl
+ .quad do_entSys, do_entSys, sys_symlink, sys_readlink, sys_execve
+ .quad sys_umask, do_entSys, do_entSys, sys_getpgrp, sys_getpagesize
+ .quad do_entSys, osf_vfork, sys_newstat, sys_newlstat, do_entSys
+ .quad do_entSys, osf_mmap, do_entSys, sys_munmap, sys_mprotect
+ .quad sys_madvise, do_entSys, do_entSys, do_entSys, sys_getgroups
+ .quad do_entSys, do_entSys, do_entSys, sys_setitimer, do_entSys
+ .quad do_entSys, sys_getitimer, sys_gethostname, do_entSys, sys_getdtablesize
+ .quad sys_dup2, sys_newfstat, sys_fcntl, sys_select, do_entSys
+ .quad sys_fsync, do_entSys, sys_socket, do_entSys, do_entSys
+/*100*/ .quad do_entSys, do_entSys, do_entSys, sys_sigreturn, sys_bind
+ .quad do_entSys, sys_listen, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, sys_sigsuspend, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, sys_gettimeofday, sys_getrusage, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, sys_settimeofday, sys_fchown, sys_fchmod
+ .quad do_entSys, sys_setreuid, sys_setregid, sys_rename, sys_truncate
+ .quad sys_ftruncate, do_entSys, sys_setgid, do_entSys, do_entSys
+ .quad do_entSys, sys_mkdir, sys_rmdir, sys_utimes, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, sys_getrlimit
+ .quad sys_setrlimit, do_entSys, sys_setsid, do_entSys, do_entSys
+/*150*/ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, sys_sigaction, do_entSys, do_entSys, osf_getdirentries
+ .quad osf_statfs, osf_fstatfs, do_entSys, do_entSys, do_entSys
+ .quad osf_getdomainname, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, osf_swapon
+/*200*/ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, osf_utsname, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+/*250*/ .quad do_entSys, osf_usleep_thread, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+/* linux-specific system calls start at 300 */
+/*300*/ .quad sys_bdflush, sys_sethae, do_entSys, do_entSys, do_entSys
+ .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
new file mode 100644
index 000000000..2cff1159a
--- /dev/null
+++ b/arch/alpha/kernel/head.S
@@ -0,0 +1,97 @@
+/*
+ * alpha/boot/head.S
+ *
+ * initial boot stuff.. At this point, the bootloader has already
+ * switched into OSF/1 PAL-code, and loaded us at the correct address
+ * (START_ADDR). So there isn't much left for us to do: just set up
+ * the kernel global pointer and jump to the kernel entry-point.
+ */
+
+#define __ASSEMBLY__
+#include <asm/system.h>
+#include <linux/fd.h>
+
+#define halt .long PAL_halt
+
+.globl swapper_pg_dir
+swapper_pg_dir=SWAPPER_PGD
+
+ .set noreorder
+ .globl __start
+ .ent __start
+__start:
+ br $27,1f
+1: ldgp $29,0($27)
+ lda $27,start_kernel
+ jsr $26,($27),start_kernel
+ halt
+ .end __start
+
+ .align 3
+ .globl wrent
+ .ent wrent
+wrent:
+ .long PAL_wrent
+ ret ($26)
+ .end wrent
+
+ .align 3
+ .globl wrkgp
+ .ent wrkgp
+wrkgp:
+ .long PAL_wrkgp
+ ret ($26)
+ .end wrkgp
+
+ .align 3
+ .globl wrusp
+ .ent wrusp
+wrusp:
+ .long PAL_wrusp
+ ret ($26)
+ .end wrusp
+
+ .align 3
+ .globl rdusp
+ .ent rdusp
+rdusp:
+ .long PAL_rdusp
+ ret ($26)
+ .end rdusp
+
+ .align 3
+ .globl tbi
+ .ent tbi
+tbi:
+ .long PAL_tbi
+ ret ($26)
+ .end tbi
+
+ .align 3
+ .globl imb
+ .ent imb
+imb:
+ .long PAL_imb
+ ret ($26)
+ .end imb
+
+ .align 3
+ .globl rdmces
+ .ent rdmces
+rdmces:
+ call_pal PAL_rdmces
+ ret ($26)
+ .end rdmces
+
+ .align 3
+ .globl wrmces
+ .ent wrmces
+wrmces:
+ call_pal PAL_wrmces
+ ret ($26)
+ .end wrmces
+
+.align 9
+.globl floppy_track_buffer
+floppy_track_buffer:
+ .space 512*2*MAX_BUFFER_SECTORS,1
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
new file mode 100644
index 000000000..a59077539
--- /dev/null
+++ b/arch/alpha/kernel/irq.c
@@ -0,0 +1,414 @@
+/*
+ * linux/arch/alpha/kernel/irq.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ */
+
+#include <linux/config.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/dma.h>
+
+static unsigned char cache_21 = 0xff;
+static unsigned char cache_A1 = 0xff;
+
+void disable_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+ unsigned char mask;
+
+ mask = 1 << (irq_nr & 7);
+ save_flags(flags);
+ if (irq_nr < 8) {
+ cli();
+ cache_21 |= mask;
+ outb(cache_21,0x21);
+ restore_flags(flags);
+ return;
+ }
+ cli();
+ cache_A1 |= mask;
+ outb(cache_A1,0xA1);
+ restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+ unsigned char mask;
+
+ mask = ~(1 << (irq_nr & 7));
+ save_flags(flags);
+ if (irq_nr < 8) {
+ cli();
+ cache_21 &= mask;
+ outb(cache_21,0x21);
+ restore_flags(flags);
+ return;
+ }
+ cli();
+ cache_A1 &= mask;
+ outb(cache_A1,0xA1);
+ restore_flags(flags);
+}
+
+/*
+ * Initial irq handlers.
+ */
+struct irqaction {
+ void (*handler)(int, struct pt_regs *);
+ unsigned long flags;
+ unsigned long mask;
+ const char *name;
+};
+
+static struct irqaction irq_action[16] = {
+ { 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 }
+};
+
+int get_irq_list(char *buf)
+{
+ int i, len = 0;
+ struct irqaction * action = irq_action;
+
+ for (i = 0 ; i < 16 ; 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;
+}
+
+static inline void ack_irq(int irq)
+{
+ /* ACK the interrupt making it the lowest priority */
+ /* First the slave .. */
+ if (irq > 7) {
+ outb(0xE0 | (irq - 8), 0xa0);
+ irq = 2;
+ }
+ /* .. then the master */
+ outb(0xE0 | irq, 0x20);
+}
+
+static inline void mask_irq(int irq)
+{
+ if (irq < 8) {
+ cache_21 |= 1 << irq;
+ outb(cache_21, 0x21);
+ } else {
+ cache_A1 |= 1 << (irq - 8);
+ outb(cache_A1, 0xA1);
+ }
+}
+
+static inline void unmask_irq(unsigned long irq)
+{
+ if (irq < 8) {
+ cache_21 &= ~(1 << irq);
+ outb(cache_21, 0x21);
+ } else {
+ cache_A1 &= ~(1 << (irq - 8));
+ outb(cache_A1, 0xA1);
+ }
+}
+
+int request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
+ unsigned long irqflags, const char * devname)
+{
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (irq > 15)
+ return -EINVAL;
+ action = irq + irq_action;
+ if (action->handler)
+ return -EBUSY;
+ if (!handler)
+ return -EINVAL;
+ save_flags(flags);
+ cli();
+ action->handler = handler;
+ action->flags = irqflags;
+ action->mask = 0;
+ action->name = devname;
+ if (irq < 8) {
+ if (irq) {
+ cache_21 &= ~(1<<irq);
+ outb(cache_21,0x21);
+ }
+ } else {
+ cache_21 &= ~(1<<2);
+ cache_A1 &= ~(1<<(irq-8));
+ outb(cache_21,0x21);
+ outb(cache_A1,0xA1);
+ }
+ restore_flags(flags);
+ return 0;
+}
+
+void free_irq(unsigned int irq)
+{
+ struct irqaction * action = irq + irq_action;
+ unsigned long flags;
+
+ if (irq > 15) {
+ printk("Trying to free IRQ%d\n", irq);
+ return;
+ }
+ if (!action->handler) {
+ printk("Trying to free free IRQ%d\n", irq);
+ return;
+ }
+ save_flags(flags);
+ cli();
+ mask_irq(irq);
+ action->handler = NULL;
+ action->flags = 0;
+ action->mask = 0;
+ action->name = NULL;
+ restore_flags(flags);
+}
+
+static void handle_nmi(struct pt_regs * regs)
+{
+ printk("Whee.. NMI received. Probable hardware error\n");
+ printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
+}
+
+static void unexpected_irq(int irq, struct pt_regs * regs)
+{
+ int i;
+
+ printk("IO device interrupt, irq = %d\n", irq);
+ printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
+ printk("Expecting: ");
+ for (i = 0; i < 16; i++)
+ if (irq_action[i].handler)
+ printk("[%s:%d] ", irq_action[i].name, i);
+ printk("\n");
+ printk("64=%02x, 60=%02x, 3fa=%02x 2fa=%02x\n",
+ inb(0x64), inb(0x60), inb(0x3fa), inb(0x2fa));
+ outb(0x0c, 0x3fc);
+ outb(0x0c, 0x2fc);
+ outb(0,0x61);
+ outb(0,0x461);
+}
+
+static inline void handle_irq(int irq, struct pt_regs * regs)
+{
+ struct irqaction * action = irq + irq_action;
+
+ kstat.interrupts[irq]++;
+ if (!action->handler) {
+ unexpected_irq(irq, regs);
+ return;
+ }
+ action->handler(irq, regs);
+}
+
+static void local_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ switch (vector) {
+ /* com1: map to irq 4 */
+ case 0x900:
+ handle_irq(4, regs);
+ return;
+
+ /* com2: map to irq 3 */
+ case 0x920:
+ handle_irq(3, regs);
+ return;
+
+ /* keyboard: map to irq 1 */
+ case 0x980:
+ handle_irq(1, regs);
+ return;
+
+ /* mouse: map to irq 9 */
+ case 0x990:
+ handle_irq(9, regs);
+ return;
+ default:
+ printk("Unknown local interrupt %lx\n", vector);
+ }
+}
+
+/*
+ * The vector is 0x8X0 for EISA interrupt X, and 0x9X0 for the local
+ * motherboard interrupts.. This is for the Jensen.
+ *
+ * 0x660 - NMI
+ *
+ * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
+ * 0x810 - IRQ1 line printer (duh..)
+ * 0x860 - IRQ6 floppy disk
+ * 0x8E0 - IRQ14 SCSI controller
+ *
+ * 0x900 - COM1
+ * 0x920 - COM2
+ * 0x980 - keyboard
+ * 0x990 - mouse
+ *
+ * The PCI version is more sane: it doesn't have the local interrupts at
+ * all, and has only normal PCI interrupts from devices. Happily it's easy
+ * enough to do a sane mapping from the Jensen.. Note that this means
+ * that we may have to do a hardware "ack" to a different interrupt than
+ * we report to the rest of the world..
+ */
+static void device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ struct irqaction * action;
+
+ if (vector == 0x660) {
+ handle_nmi(regs);
+ return;
+ }
+
+ ack = irq = (vector - 0x800) >> 4;
+#ifndef CONFIG_PCI
+ if (vector >= 0x900) {
+ local_device_interrupt(vector, regs);
+ return;
+ }
+ /* irq1 is supposed to be the keyboard, silly Jensen */
+ if (irq == 1)
+ irq = 7;
+#endif
+ kstat.interrupts[irq]++;
+ action = irq_action + irq;
+ /* quick interrupts get executed with no extra overhead */
+ if (action->flags & SA_INTERRUPT) {
+ action->handler(irq, regs);
+ ack_irq(ack);
+ return;
+ }
+ /*
+ * For normal interrupts, we mask it out, and then ACK it.
+ * This way another (more timing-critical) interrupt can
+ * come through while we're doing this one.
+ *
+ * Note! A irq without a handler gets masked and acked, but
+ * never unmasked. The autoirq stuff depends on this (it looks
+ * at the masks before and after doing the probing).
+ */
+ mask_irq(ack);
+ ack_irq(ack);
+ if (!action->handler)
+ return;
+ action->handler(irq, regs);
+ unmask_irq(ack);
+}
+
+/*
+ * Start listening for interrupts..
+ */
+unsigned int probe_irq_on(void)
+{
+ unsigned int i, irqs = 0, irqmask;
+ unsigned long delay;
+
+ for (i = 15; i > 0; i--) {
+ if (!irq_action[i].handler) {
+ enable_irq(i);
+ irqs |= (1 << i);
+ }
+ }
+
+ /* wait for spurious interrupts to mask themselves out again */
+ for (delay = jiffies + HZ/10; delay > jiffies; )
+ /* about 100 ms delay */;
+
+ /* now filter out any obviously spurious interrupts */
+ irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int) cache_21;
+ irqs &= ~irqmask;
+ return irqs;
+}
+
+/*
+ * Get the result of the IRQ probe.. A negative result means that
+ * we have several candidates (but we return the lowest-numbered
+ * one).
+ */
+int probe_irq_off(unsigned int irqs)
+{
+ unsigned int i, irqmask;
+
+ irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
+ irqs &= irqmask;
+ if (!irqs)
+ return 0;
+ i = ffz(~irqs);
+ if (irqs != (1 << i))
+ i = -i;
+ return i;
+}
+
+static void machine_check(unsigned long vector, unsigned long la_ptr, struct pt_regs * regs)
+{
+ printk("Machine check\n");
+}
+
+asmlinkage void do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ switch (type) {
+ case 0:
+ printk("Interprocessor interrupt? You must be kidding\n");
+ break;
+ case 1:
+ /* timer interrupt.. */
+ handle_irq(0, &regs);
+ return;
+ case 2:
+ machine_check(vector, la_ptr, &regs);
+ break;
+ case 3:
+ device_interrupt(vector, &regs);
+ return;
+ case 4:
+ printk("Performance counter interrupt\n");
+ break;;
+ default:
+ printk("Hardware intr %ld %lx? Huh?\n", type, vector);
+ }
+ printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
+}
+
+extern asmlinkage void entInt(void);
+
+void init_IRQ(void)
+{
+ wrent(entInt, 0);
+ dma_outb(0, DMA1_RESET_REG);
+ dma_outb(0, DMA2_RESET_REG);
+ dma_outb(0, DMA1_CLR_MASK_REG);
+ dma_outb(0, DMA2_CLR_MASK_REG);
+}
diff --git a/arch/alpha/kernel/lca.c b/arch/alpha/kernel/lca.c
new file mode 100644
index 000000000..c32c308fb
--- /dev/null
+++ b/arch/alpha/kernel/lca.c
@@ -0,0 +1,304 @@
+/*
+ * Code common to all LCA chips.
+ *
+ * Written by David Mosberger (davidm@cs.arizona.edu) with some code
+ * taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
+ * bios code.
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef CONFIG_PCI
+
+#define vulp volatile unsigned long *
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the LCA_IOC_CONF register
+ * accordingly. It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Type 0:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | | | | | | | | | | | | | | |F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:11 Device select bit.
+ * 10:8 Function number
+ * 7:2 Register number
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., scsi and ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned long *pci_addr)
+{
+ unsigned long addr;
+
+ if (bus == 0) {
+ int device = device_fn >> 3;
+ int func = device_fn & 0x7;
+
+ /* type 0 configuration cycle: */
+
+ if (device > 12) {
+ return -1;
+ } /* if */
+
+ *((volatile unsigned long*) LCA_IOC_CONF) = 0;
+ addr = (1 << (11 + device)) | (func << 8) | where;
+ } else {
+ /* type 1 configuration cycle: */
+ *((volatile unsigned long*) LCA_IOC_CONF) = 1;
+ addr = (bus << 16) | (device_fn << 8) | where;
+ } /* if */
+ *pci_addr = addr;
+
+ return 0;
+}
+
+
+static unsigned int conf_read(unsigned long addr)
+{
+ unsigned long old_ipl, code, stat0;
+ unsigned int value;
+
+ old_ipl = swpipl(7); /* avoid getting hit by machine check */
+
+ /* reset status register to avoid loosing errors: */
+ stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
+ *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+ mb();
+
+ /* access configuration space: */
+
+ value = *((volatile unsigned int*)addr);
+ draina();
+
+ stat0 = *((unsigned long*)LCA_IOC_STAT0);
+ if (stat0 & LCA_IOC_STAT0_ERR) {
+ code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
+ & LCA_IOC_STAT0_CODE_MASK);
+ if (code != 1) {
+ printk("lca.c:conf_read: got stat0=%lx\n", stat0);
+ }
+
+ /* reset error status: */
+ *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+
+ value = 0xffffffff;
+ }
+ swpipl(old_ipl);
+
+ return value;
+}
+
+
+static void conf_write(unsigned long addr, unsigned int value)
+{
+ unsigned long old_ipl, code, stat0;
+
+ old_ipl = swpipl(7); /* avoid getting hit by machine check */
+
+ /* reset status register to avoid loosing errors: */
+ stat0 = *((volatile unsigned long*)LCA_IOC_STAT0);
+ *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+ mb();
+
+ /* access configuration space: */
+
+ *((volatile unsigned int*)addr) = value;
+ draina();
+
+ stat0 = *((unsigned long*)LCA_IOC_STAT0);
+ if (stat0 & LCA_IOC_STAT0_ERR) {
+ code = ((stat0 >> LCA_IOC_STAT0_CODE_SHIFT)
+ & LCA_IOC_STAT0_CODE_MASK);
+ if (code != 1) {
+ printk("lca.c:conf_write: got stat0=%lx\n", stat0);
+ }
+
+ /* reset error status: */
+ *((volatile unsigned long*)LCA_IOC_STAT0) = stat0;
+ mb();
+ wrmces(0x7); /* reset machine check */
+ }
+ swpipl(old_ipl);
+}
+
+
+int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x00;
+
+ *value = conf_read(addr) >> ((where & 3) * 8);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xffff;
+
+ if (where & 0x1) {
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ } /* if */
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x08;
+
+ *value = conf_read(addr) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int *value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ *value = 0xffffffff;
+
+ if (where & 0x3) {
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ } /* if */
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x18;
+
+ *value = conf_read(addr);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned char value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x00;
+
+ conf_write(addr, value << ((where & 3) * 8));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned short value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x08;
+
+ conf_write(addr, value << ((where & 3) * 8));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
+ unsigned char where, unsigned int value)
+{
+ unsigned long addr = LCA_CONF;
+ unsigned long pci_addr;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
+ return PCIBIOS_SUCCESSFUL;
+ } /* if */
+
+ addr |= (pci_addr << 5) + 0x18;
+
+ conf_write(addr, value << ((where & 3) * 8));
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
+{
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 1 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA. Window 0
+ * goes at 1 GB and is 1 GB large.
+ */
+ *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
+ *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
+ *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
+ *(vulp)LCA_IOC_T_BASE0 = 0;
+
+ return mem_start;
+}
+
+#endif /* CONFIG_PCI */
+
+ /*** end of lca.c ***/
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
new file mode 100644
index 000000000..ddf090283
--- /dev/null
+++ b/arch/alpha/kernel/osf_sys.c
@@ -0,0 +1,494 @@
+/*
+ * linux/arch/alpha/kernel/osf_sys.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+/*
+ * This file handles some of the stranger OSF/1 system call interfaces.
+ * Some of the system calls expect a non-C calling standard, others have
+ * special parameter blocks..
+ */
+
+#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/ldt.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/utsname.h>
+#include <linux/time.h>
+#include <linux/major.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+extern int do_mount(dev_t, const char *, char *, int, void *);
+extern int do_pipe(int *);
+
+extern struct file_operations * get_blkfops(unsigned int);
+extern struct file_operations * get_chrfops(unsigned int);
+
+extern dev_t get_unnamed_dev(void);
+extern void put_unnamed_dev(dev_t);
+
+extern asmlinkage int sys_umount(char *);
+extern asmlinkage int sys_swapon(const char *specialfile);
+
+/*
+ * OSF/1 directory handling functions...
+ *
+ * The "getdents()" interface is much more sane: the "basep" stuff is
+ * braindamage (it can't really handle filesystems where the directory
+ * offset differences aren't the same as "d_reclen").
+ */
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+7) & ~7)
+
+struct osf_dirent {
+ unsigned int d_ino;
+ unsigned short d_reclen;
+ unsigned short d_namlen;
+ char d_name[1];
+};
+
+struct osf_dirent_callback {
+ struct osf_dirent * dirent;
+ long *basep;
+ int count;
+ int error;
+};
+
+static int osf_filldir(void * __buf, char * name, int namlen, off_t offset, ino_t ino)
+{
+ struct osf_dirent * dirent;
+ struct osf_dirent_callback * buf = (struct osf_dirent_callback *) __buf;
+ int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+ buf->error = -EINVAL; /* unly used if we fail */
+ if (reclen > buf->count)
+ return -EINVAL;
+ if (buf->basep) {
+ put_user(offset, buf->basep);
+ buf->basep = NULL;
+ }
+ dirent = buf->dirent;
+ put_user(ino, &dirent->d_ino);
+ put_user(namlen, &dirent->d_namlen);
+ put_user(reclen, &dirent->d_reclen);
+ memcpy_tofs(dirent->d_name, name, namlen);
+ put_fs_byte(0, dirent->d_name + namlen);
+ ((char *) dirent) += reclen;
+ buf->dirent = dirent;
+ buf->count -= reclen;
+ return 0;
+}
+
+asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent * dirent,
+ unsigned int count, long *basep)
+{
+ int error;
+ struct file * file;
+ struct osf_dirent_callback buf;
+
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ if (!file->f_op || !file->f_op->readdir)
+ return -ENOTDIR;
+ error = verify_area(VERIFY_WRITE, dirent, count);
+ if (error)
+ return error;
+ if (basep) {
+ error = verify_area(VERIFY_WRITE, basep, sizeof(long));
+ if (error)
+ return error;
+ }
+ buf.dirent = dirent;
+ buf.basep = basep;
+ buf.count = count;
+ buf.error = 0;
+ error = file->f_op->readdir(file->f_inode, file, dirent, osf_filldir);
+ if (error < 0)
+ return error;
+ if (count == buf.count)
+ return buf.error;
+ return count - buf.count;
+}
+
+/*
+ * Heh. As documented by DEC..
+ */
+asmlinkage unsigned long sys_madvise(void)
+{
+ return 0;
+}
+
+asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
+ struct pt_regs regs)
+{
+ (&regs)->r20 = current->euid;
+ return current->uid;
+}
+
+asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
+ struct pt_regs regs)
+{
+ (&regs)->r20 = current->egid;
+ return current->gid;
+}
+
+asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
+ struct pt_regs regs)
+{
+ (&regs)->r20 = current->p_opptr->pid;
+ return current->pid;
+}
+
+#define OSF_MAP_ANONYMOUS 0x0010
+#define OSF_MAP_FIXED 0x0100
+#define OSF_MAP_HASSEMAPHORE 0x0200
+#define OSF_MAP_INHERIT 0x0400
+#define OSF_MAP_UNALIGNED 0x0800
+
+asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long osf_flags, unsigned long fd,
+ unsigned long off)
+{
+ struct file * file = NULL;
+ unsigned long flags = osf_flags & 0x0f;
+
+ if (osf_flags & (OSF_MAP_HASSEMAPHORE | OSF_MAP_INHERIT | OSF_MAP_UNALIGNED))
+ printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, osf_flags);
+ if (osf_flags & OSF_MAP_FIXED)
+ flags |= MAP_FIXED;
+ if (osf_flags & OSF_MAP_ANONYMOUS)
+ flags |= MAP_ANONYMOUS;
+ else {
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ }
+ return do_mmap(file, addr, len, prot, flags, off);
+}
+
+asmlinkage int osf_statfs(char * path, struct statfs * buffer, unsigned long bufsiz)
+{
+ struct inode * inode;
+ int retval;
+
+ if (bufsiz > sizeof(struct statfs))
+ bufsiz = sizeof(struct statfs);
+ retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
+ if (retval)
+ return retval;
+ retval = namei(path, &inode);
+ if (retval)
+ return retval;
+ if (!inode->i_sb->s_op->statfs) {
+ iput(inode);
+ return -ENOSYS;
+ }
+ inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
+ iput(inode);
+ return 0;
+}
+
+asmlinkage int osf_fstatfs(unsigned long fd, struct statfs * buffer, unsigned long bufsiz)
+{
+ struct file * file;
+ struct inode * inode;
+ int retval;
+
+ retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
+ if (retval)
+ return retval;
+ if (bufsiz > sizeof(struct statfs))
+ bufsiz = sizeof(struct statfs);
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ return -EBADF;
+ if (!(inode = file->f_inode))
+ return -ENOENT;
+ if (!inode->i_sb->s_op->statfs)
+ return -ENOSYS;
+ inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
+ return 0;
+}
+
+/*
+ * Uhh.. OSF/1 mount parameters aren't exactly obvious..
+ *
+ * Although to be frank, neither are the native Linux/i386 ones..
+ */
+struct ufs_args {
+ char * devname;
+ int flags;
+ uid_t exroot;
+};
+
+struct cdfs_args {
+ char * devname;
+ int flags;
+ uid_t exroot;
+/*
+ * this has lots more here, which linux handles with the option block
+ * but I'm too lazy to do the translation into ascii..
+ */
+};
+
+struct procfs_args {
+ char * devname;
+ int flags;
+ uid_t exroot;
+};
+
+static int getdev(const char * name, int rdonly, struct inode ** ino)
+{
+ dev_t dev;
+ struct inode * inode;
+ struct file_operations * fops;
+ int retval;
+
+ retval = namei(name, &inode);
+ if (retval)
+ return retval;
+ if (!S_ISBLK(inode->i_mode)) {
+ iput(inode);
+ return -ENOTBLK;
+ }
+ if (IS_NODEV(inode)) {
+ iput(inode);
+ return -EACCES;
+ }
+ dev = inode->i_rdev;
+ if (MAJOR(dev) >= MAX_BLKDEV) {
+ iput(inode);
+ return -ENXIO;
+ }
+ fops = get_blkfops(MAJOR(dev));
+ if (!fops) {
+ iput(inode);
+ return -ENODEV;
+ }
+ if (fops->open) {
+ struct file dummy;
+ memset(&dummy, 0, sizeof(dummy));
+ dummy.f_inode = inode;
+ dummy.f_mode = rdonly ? 1 : 3;
+ retval = fops->open(inode, &dummy);
+ if (retval) {
+ iput(inode);
+ return retval;
+ }
+ }
+ *ino = inode;
+ return 0;
+}
+
+static void putdev(struct inode * inode)
+{
+ struct file_operations * fops;
+
+ fops = get_blkfops(MAJOR(inode->i_rdev));
+ if (fops->release)
+ fops->release(inode, NULL);
+}
+
+/*
+ * We can't actually handle ufs yet, so we translate UFS mounts to
+ * ext2fs mounts... I wouldn't mind a USF filesystem, but the UFS
+ * layout is so braindead it's a major headache doing it..
+ */
+static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
+{
+ int retval;
+ struct inode * inode;
+ struct cdfs_args tmp;
+
+ retval = verify_area(VERIFY_READ, args, sizeof(*args));
+ if (retval)
+ return retval;
+ memcpy_fromfs(&tmp, args, sizeof(tmp));
+ retval = getdev(tmp.devname, 0, &inode);
+ if (retval)
+ return retval;
+ retval = do_mount(inode->i_rdev, dirname, "ext2", flags, NULL);
+ if (retval)
+ putdev(inode);
+ iput(inode);
+ return retval;
+}
+
+static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
+{
+ int retval;
+ struct inode * inode;
+ struct cdfs_args tmp;
+
+ retval = verify_area(VERIFY_READ, args, sizeof(*args));
+ if (retval)
+ return retval;
+ memcpy_fromfs(&tmp, args, sizeof(tmp));
+ retval = getdev(tmp.devname, 1, &inode);
+ if (retval)
+ return retval;
+ retval = do_mount(inode->i_rdev, dirname, "iso9660", flags, NULL);
+ if (retval)
+ putdev(inode);
+ iput(inode);
+ return retval;
+}
+
+static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
+{
+ dev_t dev;
+ int retval;
+ struct procfs_args tmp;
+
+ retval = verify_area(VERIFY_READ, args, sizeof(*args));
+ if (retval)
+ return retval;
+ memcpy_fromfs(&tmp, args, sizeof(tmp));
+ dev = get_unnamed_dev();
+ if (!dev)
+ return -ENODEV;
+ retval = do_mount(dev, dirname, "proc", flags, NULL);
+ if (retval)
+ put_unnamed_dev(dev);
+ return retval;
+}
+
+asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
+{
+ int retval;
+
+ retval = -EINVAL;
+ switch (typenr) {
+ case 1:
+ retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
+ break;
+ case 6:
+ retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
+ break;
+ case 9:
+ retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
+ break;
+ default:
+ printk("osf_mount(%ld, %x)\n", typenr, flag);
+ }
+ return retval;
+}
+
+asmlinkage int osf_umount(char * path, int flag)
+{
+ return sys_umount(path);
+}
+
+/*
+ * I don't know what the parameters are: the first one
+ * seems to be a timeval pointer, and I suspect the second
+ * one is the time remaining.. Ho humm.. No documentation.
+ */
+asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
+{
+ struct timeval tmp;
+ unsigned long ticks;
+ int retval;
+
+ retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
+ if (retval)
+ return retval;
+ if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
+ return retval;
+ memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
+ ticks = tmp.tv_usec;
+ ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
+ ticks += tmp.tv_sec * HZ;
+ current->timeout = ticks + jiffies;
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (!remain)
+ return 0;
+ ticks = jiffies;
+ if (ticks < current->timeout)
+ ticks = current->timeout - ticks;
+ else
+ ticks = 0;
+ current->timeout = 0;
+ tmp.tv_sec = ticks / HZ;
+ tmp.tv_usec = ticks % HZ;
+ memcpy_tofs(remain, &tmp, sizeof(*remain));
+ return 0;
+}
+
+asmlinkage int osf_utsname(char * name)
+{
+ int error = verify_area(VERIFY_WRITE, name, 5*32);
+ if (error)
+ return error;
+ memcpy_tofs(name + 0, system_utsname.sysname, 32);
+ memcpy_tofs(name + 32, system_utsname.nodename, 32);
+ memcpy_tofs(name + 64, system_utsname.release, 32);
+ memcpy_tofs(name + 96, system_utsname.version, 32);
+ memcpy_tofs(name + 128, system_utsname.machine, 32);
+ return 0;
+}
+
+asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
+{
+ /* for now, simply ignore flags, lowat and hiwat... */
+ return sys_swapon(path);
+}
+
+asmlinkage unsigned long sys_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
+asmlinkage unsigned long sys_getdtablesize(void)
+{
+ return NR_OPEN;
+}
+
+asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
+ struct pt_regs regs)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (error)
+ return error;
+ (&regs)->r20 = fd[1];
+ return fd[0];
+}
+
+/*
+ * For compatibility with OSF/1 only. Use utsname(2) instead.
+ */
+asmlinkage int osf_getdomainname(char *name, int namelen)
+{
+ unsigned len;
+ int i, error;
+
+ error = verify_area(VERIFY_WRITE, name, namelen);
+ if (error)
+ return error;
+
+ len = namelen;
+ if (namelen > 32)
+ len = 32;
+
+ for (i = 0; i < len; ++i) {
+ put_user(system_utsname.domainname[i], name + i);
+ if (system_utsname.domainname[i] == '\0')
+ break;
+ }
+ return 0;
+}
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
new file mode 100644
index 000000000..257f431a5
--- /dev/null
+++ b/arch/alpha/kernel/process.c
@@ -0,0 +1,186 @@
+/*
+ * linux/arch/alpha/kernel/process.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#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/ldt.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/utsname.h>
+#include <linux/time.h>
+#include <linux/major.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ (&regs)->hae = hae;
+ return 0;
+}
+
+asmlinkage int sys_idle(void)
+{
+ if (current->pid != 0)
+ return -EPERM;
+
+ /* endless idle loop with no priority at all */
+ current->counter = -100;
+ for (;;) {
+ schedule();
+ }
+}
+
+void hard_reset_now(void)
+{
+ halt();
+}
+
+void show_regs(struct pt_regs * regs)
+{
+ printk("\nps: %04lx pc: %016lx\n", regs->ps, regs->pc);
+ printk("rp: %016lx sp: %p\n", regs->r26, regs+1);
+ printk(" r0: %016lx r1: %016lx r2: %016lx r3: %016lx\n",
+ regs->r0, regs->r1, regs->r2, regs->r3);
+ printk(" r4: %016lx r5: %016lx r6: %016lx r7: %016lx\n",
+ regs->r4, regs->r5, regs->r6, regs->r7);
+ printk(" r8: %016lx r16: %016lx r17: %016lx r18: %016lx\n",
+ regs->r8, regs->r16, regs->r17, regs->r18);
+ printk("r19: %016lx r20: %016lx r21: %016lx r22: %016lx\n",
+ regs->r19, regs->r20, regs->r21, regs->r22);
+ printk("r23: %016lx r24: %016lx r25: %016lx r26: %016lx\n",
+ regs->r23, regs->r24, regs->r25, regs->r26);
+ printk("r27: %016lx r28: %016lx r29: %016lx hae: %016lx\n",
+ regs->r27, regs->r28, regs->gp, regs->hae);
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+}
+
+/*
+ * "alpha_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+int alpha_fork(struct switch_stack * swstack)
+{
+ return do_fork(COPYVM | SIGCHLD,
+ rdusp(),
+ (struct pt_regs *) (swstack+1));
+}
+
+extern void ret_from_sys_call(void);
+/*
+ * Copy an alpha thread..
+ *
+ * Note the "stack_offset" stuff: when returning to kernel mode, we need
+ * to have some extra stack-space for the kernel stack that still exists
+ * after the "ret_from_sys_call". When returning to user mode, we only
+ * want the space needed by the syscall stack frame (ie "struct pt_regs").
+ * Use the passed "regs" pointer to determine how much space we need
+ * for a kernel fork().
+ */
+void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ struct task_struct * p, struct pt_regs * regs)
+{
+ struct pt_regs * childregs;
+ struct switch_stack * childstack, *stack;
+ unsigned long stack_offset;
+
+ stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
+ if (!(regs->ps & 8))
+ stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
+ childregs = (struct pt_regs *) (p->kernel_stack_page + stack_offset);
+
+ *childregs = *regs;
+ childregs->r0 = 0;
+ childregs->r19 = 0;
+ childregs->r20 = 1; /* OSF/1 has some strange fork() semantics.. */
+ regs->r0 = p->pid;
+ regs->r20 = 0;
+ stack = ((struct switch_stack *) regs) - 1;
+ childstack = ((struct switch_stack *) childregs) - 1;
+ *childstack = *stack;
+ childstack->r26 = (unsigned long) ret_from_sys_call;
+ p->tss.usp = usp;
+ p->tss.ksp = (unsigned long) childstack;
+ p->tss.flags = 1;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+}
+
+/*
+ * sys_execve() executes a new program.
+ *
+ * This works due to the alpha calling sequence: the first 6 args
+ * are gotten from registers, while the rest is on the stack, so
+ * we get a0-a5 for free, and then magically find "struct pt_regs"
+ * on the stack for us..
+ *
+ * Don't do this at home.
+ */
+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)
+{
+ int error;
+ char * filename;
+
+ error = getname((char *) a0, &filename);
+ if (error)
+ return error;
+ error = do_execve(filename, (char **) a1, (char **) a2, &regs);
+ putname(filename);
+ return error;
+}
+
+/*
+ * This doesn't actually work correctly like this: we need to do the
+ * same stack setups that fork() does first.
+ */
+asmlinkage int sys_clone(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ unsigned long clone_flags = a0;
+ unsigned long newsp;
+
+ newsp = rdusp();
+ if (newsp == a1 || !a1)
+ clone_flags |= COPYVM;
+ else
+ newsp = a1;
+ return do_fork(clone_flags, newsp, &regs);
+}
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
new file mode 100644
index 000000000..23a2efd65
--- /dev/null
+++ b/arch/alpha/kernel/setup.c
@@ -0,0 +1,172 @@
+/*
+ * linux/arch/alpha/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+/*
+ * 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/ldt.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/delay.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/hwrpb.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+
+struct hae hae = {
+ 0,
+ (unsigned long*) HAE_ADDRESS
+};
+
+struct hwrpb_struct *hwrpb;
+
+unsigned char aux_device_present;
+
+/*
+ * This is setup by the secondary bootstrap loader. Because
+ * the zero page is zeroed out as soon as the vm system is
+ * initialized, we need to copy things out into a more permanent
+ * place.
+ */
+#define PARAM ZERO_PGE
+#define COMMAND_LINE ((char*)(PARAM + 0x0000))
+#define COMMAND_LINE_SIZE 256
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+
+/*
+ * 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.
+ */
+struct screen_info screen_info = {
+ 0, 0, /* 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 */
+};
+
+static unsigned long find_end_memory(void)
+{
+ int i;
+ unsigned long high = 0;
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
+
+ memdesc = (struct memdesc_struct *) (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+ cluster = memdesc->cluster;
+ for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
+ unsigned long tmp;
+ tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
+ if (tmp > high)
+ high = tmp;
+ }
+ /* round it up to an even number of pages.. */
+ high = (high + PAGE_SIZE) & (PAGE_MASK*2);
+ return PAGE_OFFSET + high;
+}
+
+void setup_arch(char **cmdline_p,
+ unsigned long * memory_start_p, unsigned long * memory_end_p)
+{
+ extern int _end;
+
+ hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
+
+ set_hae(hae.cache); /* sync HAE register w/hae_cache */
+
+ ROOT_DEV = 0x0802; /* sda2 */
+#ifndef CONFIG_PCI
+ aux_device_present = 0xaa;
+#else
+ aux_device_present = 0x00;
+#endif
+ command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ strcpy(command_line, COMMAND_LINE);
+
+ *cmdline_p = command_line;
+ *memory_start_p = (unsigned long) &_end;
+ *memory_end_p = find_end_memory();
+
+#ifdef CONFIG_PCI
+ *memory_start_p = lca_init(*memory_start_p, *memory_end_p);
+#endif
+}
+
+asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
+{
+ return -EIO;
+}
+
+
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ */
+int get_cpuinfo(char *buffer)
+{
+ const char *cpu_name[] = {
+ "EV3", "EV4", "Unknown 1", "LCA4", "EV5", "EV45"
+ };
+ const char *systype_name[] = {
+ "ADU", "Cobra", "Ruby", "Flamingo", "Unknown 1", "Jensen",
+ "Pelican", "Unknown 2", "Sable", "AXPvme", "Noname",
+ "Turbolaser", "Avanti", "Mustang", "Alcor", "Unknown 3",
+ "Mikasa", "Unknown3", "EB66", "EB64+"
+ };
+ struct percpu_struct *cpu;
+ unsigned int cpu_index, system_index;
+# define N(a) (sizeof(a)/sizeof(a[0]))
+
+ cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
+ cpu_index = (unsigned) (cpu->type - 1);
+ system_index = (unsigned) (hwrpb->sys_type - 1);
+
+ return sprintf(buffer,
+ "cpu\t\t\t: Alpha\n"
+ "cpu model\t\t: %s\n"
+ "cpu variation\t\t: %ld\n"
+ "cpu revision\t\t: %ld\n"
+ "cpu serial number\t: %s\n"
+ "system type\t\t: %s\n"
+ "system variation\t: %ld\n"
+ "system revision\t\t: %ld\n"
+ "system serial number\t: %s\n"
+ "cycle frequency [Hz]\t: %lu\n"
+ "timer frequency [Hz]\t: %lu.%02lu\n"
+ "page size [bytes]\t: %ld\n"
+ "phys. address bits\t: %ld\n"
+ "max. addr. space #\t: %ld\n"
+ "BogoMIPS\t\t: %lu.%02lu\n",
+
+ (cpu_index < N(cpu_name) ? cpu_name[cpu_index] : "Unknown"),
+ cpu->variation, cpu->revision, (char*)cpu->serial_no,
+ (system_index < N(systype_name) ? systype_name[system_index] : "Unknown"),
+ hwrpb->sys_variation, hwrpb->sys_revision,
+ (char*)hwrpb->ssn,
+ hwrpb->cycle_freq,
+ hwrpb->intr_freq / 4096,
+ (100 * hwrpb->intr_freq / 4096) % 100,
+ hwrpb->pagesize,
+ hwrpb->pa_bits,
+ hwrpb->max_asn,
+ loops_per_sec / 500000, (loops_per_sec / 5000) % 100);
+# undef N
+}
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
new file mode 100644
index 000000000..cc7069728
--- /dev/null
+++ b/arch/alpha/kernel/signal.c
@@ -0,0 +1,319 @@
+/*
+ * linux/arch/alpha/kernel/signal.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/mm.h>
+
+#include <asm/bitops.h>
+#include <asm/segment.h>
+
+#define _S(nr) (1<<((nr)-1))
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage void ret_from_sys_call(void);
+asmlinkage int do_signal(unsigned long, struct pt_regs *, struct switch_stack *,
+ unsigned long, unsigned long);
+asmlinkage void imb(void);
+
+/*
+ * The OSF/1 sigprocmask calling sequence is different from the
+ * C sigprocmask() sequence..
+ */
+asmlinkage unsigned long osf_sigprocmask(int how, unsigned long newmask)
+{
+ unsigned long oldmask = current->blocked;
+
+ newmask &= _BLOCKABLE;
+ switch (how) {
+ case SIG_BLOCK:
+ current->blocked |= newmask;
+ return oldmask;
+ case SIG_UNBLOCK:
+ current->blocked &= ~newmask;
+ return oldmask;
+ case SIG_SETMASK:
+ current->blocked = newmask;
+ return oldmask;
+ }
+ return -EINVAL;
+}
+
+/*
+ * atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int do_sigsuspend(unsigned long mask, struct pt_regs * regs, struct switch_stack * sw)
+{
+ unsigned long oldmask = current->blocked;
+ current->blocked = mask & _BLOCKABLE;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(oldmask,regs, sw, 0, 0))
+ return -EINTR;
+ }
+}
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+asmlinkage void do_sigreturn(struct sigcontext_struct * sc,
+ struct pt_regs * regs, struct switch_stack * sw)
+{
+ unsigned long mask;
+ int i;
+
+ /* verify that it's a good sigcontext before using it */
+ if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
+ do_exit(SIGSEGV);
+ if (get_fs_quad(&sc->sc_ps) != 8)
+ do_exit(SIGSEGV);
+ mask = get_fs_quad(&sc->sc_mask);
+ if (mask & ~_BLOCKABLE)
+ do_exit(SIGSEGV);
+
+ /* ok, looks fine, start restoring */
+ wrusp(get_fs_quad(sc->sc_regs+30));
+ regs->pc = get_fs_quad(&sc->sc_pc);
+ sw->r26 = (unsigned long) ret_from_sys_call;
+ current->blocked = mask;
+
+ regs->r0 = get_fs_quad(sc->sc_regs+0);
+ regs->r1 = get_fs_quad(sc->sc_regs+1);
+ regs->r2 = get_fs_quad(sc->sc_regs+2);
+ regs->r3 = get_fs_quad(sc->sc_regs+3);
+ regs->r4 = get_fs_quad(sc->sc_regs+4);
+ regs->r5 = get_fs_quad(sc->sc_regs+5);
+ regs->r6 = get_fs_quad(sc->sc_regs+6);
+ regs->r7 = get_fs_quad(sc->sc_regs+7);
+ regs->r8 = get_fs_quad(sc->sc_regs+8);
+ sw->r9 = get_fs_quad(sc->sc_regs+9);
+ sw->r10 = get_fs_quad(sc->sc_regs+10);
+ sw->r11 = get_fs_quad(sc->sc_regs+11);
+ sw->r12 = get_fs_quad(sc->sc_regs+12);
+ sw->r13 = get_fs_quad(sc->sc_regs+13);
+ sw->r14 = get_fs_quad(sc->sc_regs+14);
+ sw->r15 = get_fs_quad(sc->sc_regs+15);
+ regs->r16 = get_fs_quad(sc->sc_regs+16);
+ regs->r17 = get_fs_quad(sc->sc_regs+17);
+ regs->r18 = get_fs_quad(sc->sc_regs+18);
+ regs->r19 = get_fs_quad(sc->sc_regs+19);
+ regs->r20 = get_fs_quad(sc->sc_regs+20);
+ regs->r21 = get_fs_quad(sc->sc_regs+21);
+ regs->r22 = get_fs_quad(sc->sc_regs+22);
+ regs->r23 = get_fs_quad(sc->sc_regs+23);
+ regs->r24 = get_fs_quad(sc->sc_regs+24);
+ regs->r25 = get_fs_quad(sc->sc_regs+25);
+ regs->r26 = get_fs_quad(sc->sc_regs+26);
+ regs->r27 = get_fs_quad(sc->sc_regs+27);
+ regs->r28 = get_fs_quad(sc->sc_regs+28);
+ regs->gp = get_fs_quad(sc->sc_regs+29);
+ for (i = 0; i < 31; i++)
+ sw->fp[i] = get_fs_quad(sc->sc_fpregs+i);
+}
+
+/*
+ * Set up a signal frame...
+ */
+static void setup_frame(struct sigaction * sa, struct sigcontext_struct ** fp, unsigned long pc,
+ struct pt_regs * regs, struct switch_stack * sw, int signr, unsigned long oldmask)
+{
+ int i;
+ struct sigcontext_struct * sc;
+
+ sc = *fp;
+ /* check here if we would need to switch stacks.. */
+ sc--;
+ if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
+ do_exit(SIGSEGV);
+
+ put_fs_quad(oldmask, &sc->sc_mask);
+ put_fs_quad(8, &sc->sc_ps);
+ put_fs_quad(pc, &sc->sc_pc);
+ put_fs_quad((unsigned long)*fp, sc->sc_regs+30);
+
+ put_fs_quad(regs->r0 , sc->sc_regs+0);
+ put_fs_quad(regs->r1 , sc->sc_regs+1);
+ put_fs_quad(regs->r2 , sc->sc_regs+2);
+ put_fs_quad(regs->r3 , sc->sc_regs+3);
+ put_fs_quad(regs->r4 , sc->sc_regs+4);
+ put_fs_quad(regs->r5 , sc->sc_regs+5);
+ put_fs_quad(regs->r6 , sc->sc_regs+6);
+ put_fs_quad(regs->r7 , sc->sc_regs+7);
+ put_fs_quad(regs->r8 , sc->sc_regs+8);
+ put_fs_quad(sw->r9 , sc->sc_regs+9);
+ put_fs_quad(sw->r10 , sc->sc_regs+10);
+ put_fs_quad(sw->r11 , sc->sc_regs+11);
+ put_fs_quad(sw->r12 , sc->sc_regs+12);
+ put_fs_quad(sw->r13 , sc->sc_regs+13);
+ put_fs_quad(sw->r14 , sc->sc_regs+14);
+ put_fs_quad(sw->r15 , sc->sc_regs+15);
+ put_fs_quad(regs->r16, sc->sc_regs+16);
+ put_fs_quad(regs->r17, sc->sc_regs+17);
+ put_fs_quad(regs->r18, sc->sc_regs+18);
+ put_fs_quad(regs->r19, sc->sc_regs+19);
+ put_fs_quad(regs->r20, sc->sc_regs+20);
+ put_fs_quad(regs->r21, sc->sc_regs+21);
+ put_fs_quad(regs->r22, sc->sc_regs+22);
+ put_fs_quad(regs->r23, sc->sc_regs+23);
+ put_fs_quad(regs->r24, sc->sc_regs+24);
+ put_fs_quad(regs->r25, sc->sc_regs+25);
+ put_fs_quad(regs->r26, sc->sc_regs+26);
+ put_fs_quad(regs->r27, sc->sc_regs+27);
+ put_fs_quad(regs->r28, sc->sc_regs+28);
+ put_fs_quad(regs->gp , sc->sc_regs+29);
+ for (i = 0; i < 31; i++)
+ put_fs_quad(sw->fp[i], sc->sc_fpregs+i);
+
+ /*
+ * The following is:
+ *
+ * bis $30,$30,$16
+ * addq $31,0x67,$0
+ * call_pal callsys
+ *
+ * ie, "sigreturn(stack-pointer)"
+ */
+ put_fs_quad(0x43ecf40047de0410, sc->sc_retcode+0);
+ put_fs_quad(0x0000000000000083, sc->sc_retcode+1);
+ regs->r26 = (unsigned long) sc->sc_retcode;
+ regs->r16 = signr;
+ *fp = sc;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ *
+ * "r0" and "r19" are the registers we need to restore for system call
+ * restart. "r0" is also used as an indicator whether we can restart at
+ * all (if we get here from anything but a syscall return, it will be 0)
+ */
+asmlinkage int do_signal(unsigned long oldmask,
+ struct pt_regs * regs,
+ struct switch_stack * sw,
+ unsigned long r0, unsigned long r19)
+{
+ unsigned long mask = ~current->blocked;
+ unsigned long handler_signal = 0;
+ struct sigcontext_struct *frame = NULL;
+ unsigned long pc = 0;
+ unsigned long signr;
+ struct sigaction * sa;
+
+ while ((signr = current->signal & mask) != 0) {
+ signr = ffz(~signr);
+ clear_bit(signr, &current->signal);
+ sa = current->sigaction + signr;
+ signr++;
+ if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ current->exit_code = signr;
+ current->state = TASK_STOPPED;
+ notify_parent(current);
+ schedule();
+ if (!(signr = current->exit_code))
+ continue;
+ current->exit_code = 0;
+ if (signr == SIGSTOP)
+ continue;
+ if (_S(signr) & current->blocked) {
+ current->signal |= _S(signr);
+ continue;
+ }
+ sa = current->sigaction + signr - 1;
+ }
+ if (sa->sa_handler == SIG_IGN) {
+ if (signr != SIGCHLD)
+ continue;
+ /* check for SIGCHLD: it's special */
+ while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+ /* nothing */;
+ continue;
+ }
+ if (sa->sa_handler == SIG_DFL) {
+ if (current->pid == 1)
+ continue;
+ switch (signr) {
+ case SIGCONT: case SIGCHLD: case SIGWINCH:
+ continue;
+
+ case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
+ if (current->flags & PF_PTRACED)
+ continue;
+ current->state = TASK_STOPPED;
+ current->exit_code = signr;
+ if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
+ SA_NOCLDSTOP))
+ notify_parent(current);
+ schedule();
+ continue;
+
+ case SIGQUIT: case SIGILL: case SIGTRAP:
+ case SIGABRT: case SIGFPE: case SIGSEGV:
+ if (current->binfmt && current->binfmt->core_dump) {
+ if (current->binfmt->core_dump(signr, regs))
+ signr |= 0x80;
+ }
+ /* fall through */
+ default:
+ current->signal |= _S(signr & 0x7f);
+ do_exit(signr);
+ }
+ }
+ /*
+ * OK, we're invoking a handler
+ */
+ if (r0) {
+ if (regs->r0 == ERESTARTNOHAND ||
+ (regs->r0 == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
+ regs->r0 = EINTR;
+ }
+ handler_signal |= 1 << (signr-1);
+ mask &= ~sa->sa_mask;
+ }
+ if (r0 &&
+ (regs->r0 == ERESTARTNOHAND ||
+ regs->r0 == ERESTARTSYS ||
+ regs->r0 == ERESTARTNOINTR)) {
+ regs->r0 = r0;
+ regs->r19 = r19;
+ regs->pc -= 4;
+ }
+ if (!handler_signal) /* no handler will be called - return 0 */
+ return 0;
+ pc = regs->pc;
+ frame = (struct sigcontext_struct *) rdusp();
+ signr = 1;
+ sa = current->sigaction;
+ for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
+ if (mask > handler_signal)
+ break;
+ if (!(mask & handler_signal))
+ continue;
+ setup_frame(sa,&frame,pc,regs,sw,signr,oldmask);
+ pc = (unsigned long) sa->sa_handler;
+ regs->r27 = pc;
+ if (sa->sa_flags & SA_ONESHOT)
+ sa->sa_handler = NULL;
+ current->blocked |= sa->sa_mask;
+ oldmask |= sa->sa_mask;
+ }
+ imb();
+ wrusp((unsigned long) frame);
+ regs->pc = pc; /* "return" to the first handler */
+ return 1;
+}
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
new file mode 100644
index 000000000..4e3512ddd
--- /dev/null
+++ b/arch/alpha/kernel/traps.c
@@ -0,0 +1,159 @@
+/*
+ * kernel/traps.c
+ *
+ * (C) Copyright 1994 Linus Torvalds
+ */
+
+/*
+ * This file initializes the trap entry points
+ */
+
+#include <linux/sched.h>
+#include <linux/tty.h>
+
+#include <asm/unaligned.h>
+
+void die_if_kernel(char * str, struct pt_regs * regs, long err)
+{
+ long i;
+ unsigned long sp;
+ unsigned int * pc;
+
+ printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
+ sp = (unsigned long) (regs+1);
+ if (regs->ps & 8)
+ sp = rdusp();
+ printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps);
+ printk("rp = %lx sp = %lx\n", regs->r26, sp);
+ printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
+ regs->r0, regs->r1, regs->r2, regs->r3);
+ printk("r8=%lx\n", regs->r8);
+ printk("r16=%lx r17=%lx r18=%lx r19=%lx\n",
+ regs->r16, regs->r17, regs->r18, regs->r19);
+ printk("r20=%lx r21=%lx r22=%lx r23=%lx\n",
+ regs->r20, regs->r21, regs->r22, regs->r23);
+ printk("r24=%lx r25=%lx r26=%lx r27=%lx\n",
+ regs->r24, regs->r25, regs->r26, regs->r27);
+ printk("r28=%lx r29=%lx r30=%lx\n",
+ regs->r28, regs->gp, sp);
+ if (regs->ps & 8)
+ return;
+ printk("Code:");
+ pc = (unsigned int *) regs->pc;
+ for (i = -3; i < 6; i++)
+ printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
+ printk("\n");
+ for (i = 0 ; i < 5000000000 ; i++)
+ /* pause */;
+ halt();
+}
+
+asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
+ unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ printk("Arithmetic trap: %02lx %016lx\n", summary, write_mask);
+ die_if_kernel("Arithmetic fault", &regs, 0);
+}
+
+asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ die_if_kernel("Instruction fault", &regs, type);
+}
+
+/*
+ * entUna has a different register layout to be reasonably simple. It
+ * needs access to all the integer registers (the kernel doesn't use
+ * fp-regs), and it needs to have them in order for simpler access.
+ *
+ * Due to the non-standard register layout (and because we don't want
+ * to handle floating-point regs), we disallow user-mode unaligned
+ * accesses (we'd need to do "verify_area()" checking, as well as
+ * do a full "ret_from_sys_call" return).
+ *
+ * Oh, btw, we don't handle the "gp" register correctly, but if we fault
+ * on a gp-register unaligned load/store, something is _very_ wrong
+ * in the kernel anyway..
+ */
+struct allregs {
+ unsigned long regs[32];
+ unsigned long ps, pc, gp, a0, a1, a2;
+};
+
+asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct allregs regs)
+{
+ static int cnt = 0;
+
+ if (regs.ps & 8)
+ do_exit(SIGSEGV);
+ if (++cnt < 5)
+ printk("Unaligned trap at %016lx: %p %lx %ld\n",
+ regs.pc, va, opcode, reg);
+ /* $16-$18 are PAL-saved, and are offset by 19 entries */
+ if (reg >= 16 && reg <= 18)
+ reg += 19;
+ switch (opcode) {
+ case 0x28: /* ldl */
+ *(reg+regs.regs) = (int) ldl_u(va);
+ return;
+ case 0x29: /* ldq */
+ *(reg+regs.regs) = ldq_u(va);
+ return;
+ case 0x2c: /* stl */
+ stl_u(*(reg+regs.regs), va);
+ return;
+ case 0x2d: /* stq */
+ stq_u(*(reg+regs.regs), va);
+ return;
+ }
+ printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
+ regs.pc, va, opcode, reg);
+ do_exit(SIGSEGV);
+}
+
+/*
+ * DEC means people to use the "retsys" instruction for return from
+ * a system call, but they are clearly misguided about this. We use
+ * "rti" in all cases, and fill in the stack with the return values.
+ * That should make signal handling etc much cleaner.
+ *
+ * Even more horribly, DEC doesn't allow system calls from kernel mode.
+ * "Security" features letting the user do something the kernel can't
+ * are a thinko. DEC palcode is strange. The PAL-code designers probably
+ * got terminally tainted by VMS at some point.
+ */
+asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
+{
+ printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
+ return -1;
+}
+
+extern asmlinkage void entMM(void);
+extern asmlinkage void entIF(void);
+extern asmlinkage void entArith(void);
+extern asmlinkage void entUna(void);
+extern asmlinkage void entSys(void);
+
+void trap_init(void)
+{
+ unsigned long gptr;
+
+ /*
+ * Tell PAL-code what global pointer we want in the kernel..
+ */
+ __asm__("br %0,___tmp\n"
+ "___tmp:\tldgp %0,0(%0)"
+ : "=r" (gptr));
+ wrkgp(gptr);
+
+ wrent(entArith, 1);
+ wrent(entMM, 2);
+ wrent(entIF, 3);
+ wrent(entUna, 4);
+ wrent(entSys, 5);
+}
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
new file mode 100644
index 000000000..9ac9310b2
--- /dev/null
+++ b/arch/alpha/lib/Makefile
@@ -0,0 +1,38 @@
+#
+# Makefile for alpha-specific library files..
+#
+
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+.s.o:
+ $(AS) -c -o $*.o $<
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+
+OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o
+
+lib.a: $(OBJS)
+ $(AR) rcs lib.a $(OBJS)
+ sync
+
+__divqu.o: divide.S
+ $(CC) -DDIV -c -o __divqu.o divide.S
+
+__remqu.o: divide.S
+ $(CC) -DREM -c -o __remqu.o divide.S
+
+__divlu.o: divide.S
+ $(CC) -DDIV -DINTSIZE -c -o __divlu.o divide.S
+
+__remlu.o: divide.S
+ $(CC) -DREM -DINTSIZE -c -o __remlu.o divide.S
+
+dep:
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
diff --git a/arch/alpha/lib/divide.S b/arch/alpha/lib/divide.S
new file mode 100644
index 000000000..9388d3f34
--- /dev/null
+++ b/arch/alpha/lib/divide.S
@@ -0,0 +1,160 @@
+/*
+ * arch/alpha/lib/divide.S
+ *
+ * (C) 1995 Linus Torvalds
+ *
+ * Alpha division..
+ */
+
+/*
+ * The alpha chip doesn't provide hardware division, so we have to do it
+ * by hand. The compiler expects the functions
+ *
+ * __divqu: 64-bit unsigned long divide
+ * __remqu: 64-bit unsigned long remainder
+ * __divqs/__remqs: signed 64-bit
+ * __divlu/__remlu: unsigned 32-bit
+ * __divls/__remls: signed 32-bit
+ *
+ * These are not normal C functions: instead of the normal
+ * calling sequence, these expect their arguments in registers
+ * $24 and $25, and return the result in $27. Register $28 may
+ * be clobbered (assembly temporary), anything else must be saved.
+ *
+ * In short: painful.
+ *
+ * This is a rather simple bit-at-a-time algorithm: it's very good
+ * at dividing random 64-bit numbers, but the more usual case where
+ * the divisor is small is handled better by the DEC algorithm
+ * using lookup tables. This uses much less memory, though, and is
+ * nicer on the cache.. Besides, I don't know the copyright status
+ * of the DEC code.
+ */
+
+/*
+ * My temporaries:
+ * $0 - current bit
+ * $1 - shifted divisor
+ * $2 - modulus/quotient
+ *
+ * $23 - return address
+ * $24 - dividend
+ * $25 - divisor
+ *
+ * $27 - quotient/modulus
+ * $28 - compare status
+ */
+
+#define halt .long 0
+
+/*
+ * Select function type and registers
+ */
+#define mask $0
+#define divisor $1
+#define compare $28
+
+#ifdef DIV
+#define func(x) __div##x
+#define modulus $2
+#define quotient $27
+#define GETSIGN(x) xor $24,$25,x
+#else
+#define func(x) __rem##x
+#define modulus $27
+#define quotient $2
+#define GETSIGN(x) bis $24,$24,x
+#endif
+
+/*
+ * For 32-bit operations, we need to extend to 64-bit
+ */
+#ifdef INTSIZE
+#define ufunction func(lu)
+#define sfunction func(l)
+#define LONGIFY(x) zapnot x,15,x
+#define SLONGIFY(x) addl x,0,x
+#else
+#define ufunction func(qu)
+#define sfunction func(q)
+#define LONGIFY(x)
+#define SLONGIFY(x)
+#endif
+
+.set noat
+.globl ufunction
+.ent ufunction
+ufunction:
+ subq $30,32,$30
+ stq $0, 0($30)
+ stq $1, 8($30)
+ stq $2,16($30)
+
+ bis $25,$25,divisor
+ bis $24,$24,modulus
+ bis $31,$31,quotient
+ LONGIFY(divisor)
+ LONGIFY(modulus)
+ beq divisor, 9f /* div by zero */
+ bis $31,1,mask
+
+ /* shift divisor left */
+1: cmpult divisor,modulus,compare
+ blt divisor, 3f
+ addq divisor,divisor,divisor
+ addq mask,mask,mask
+ bne compare,1b
+
+ /* ok, start to go right again.. */
+2: srl divisor,1,divisor
+ beq mask,9f
+ srl mask,1,mask
+3: cmpule divisor,modulus,compare
+ beq compare,2b
+ addq quotient,mask,quotient
+ beq mask,9f
+ subq modulus,divisor,modulus
+ br 2b
+
+9: ldq $0, 0($30)
+ ldq $1, 8($30)
+ ldq $2, 16($30)
+ addq $30,32,$30
+ ret $31,($23),1
+ .end ufunction
+
+/*
+ * Uhh.. Ugly signed division. I'd rather not have it at all, but
+ * it's needed in some circumstances. There are different ways to
+ * handle this, really. This does:
+ * -a / b = a / -b = -(a / b)
+ * -a % b = -(a % b)
+ * a % -b = a % b
+ * which is probably not the best solution, but at least should
+ * have the property that (x/y)*y + (x%y) = x.
+ */
+.globl sfunction
+.ent sfunction
+sfunction:
+ bis $24,$25,$28
+ SLONGIFY($28)
+ bge $28,ufunction
+ subq $30,32,$30
+ stq $23,0($30)
+ stq $24,8($30)
+ stq $25,16($30)
+ subq $31,$24,$28
+ cmovlt $24,$28,$24 /* abs($24) */
+ subq $31,$25,$28
+ cmovlt $25,$28,$25 /* abs($25) */
+ bsr $23,ufunction
+ ldq $23,0($30)
+ ldq $24,8($30)
+ ldq $25,16($30)
+ addq $30,32,$30
+ GETSIGN($28)
+ SLONGIFY($28)
+ bge $28,1f
+ subq $31,$27,$27
+1: ret $31,($23),1
+ .end sfunction
diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c
new file mode 100644
index 000000000..b5f7290ab
--- /dev/null
+++ b/arch/alpha/lib/io.c
@@ -0,0 +1,98 @@
+/*
+ * Alpha IO and memory functions.. Just expand the inlines in the header
+ * files..
+ */
+#include <asm/io.h>
+
+/*
+ * Jensen has a separate "local" and "bus" IO space for
+ * byte-wide IO.
+ */
+#ifdef __is_local
+#undef __bus_inb
+unsigned int __bus_inb(unsigned long addr)
+{
+ return ___bus_inb(addr);
+}
+
+#undef __bus_outb
+void __bus_outb(unsigned char b, unsigned long addr)
+{
+ ___bus_outb(b, addr);
+}
+#endif
+
+#undef inb
+unsigned int inb(unsigned long addr)
+{
+ return __inb(addr);
+}
+
+#undef inw
+unsigned int inw(unsigned long addr)
+{
+ return __inw(addr);
+}
+
+#undef inl
+unsigned int inl(unsigned long addr)
+{
+ return __inl(addr);
+}
+
+
+#undef outb
+void outb(unsigned char b, unsigned long addr)
+{
+ __outb(b, addr);
+}
+
+#undef outw
+void outw(unsigned short b, unsigned long addr)
+{
+ __outw(b, addr);
+}
+
+#undef outl
+void outl(unsigned int b, unsigned long addr)
+{
+ __outl(b, addr);
+}
+
+
+#undef readb
+unsigned long readb(unsigned long addr)
+{
+ return __readb(addr);
+}
+
+#undef readw
+unsigned long readw(unsigned long addr)
+{
+ return __readw(addr);
+}
+
+#undef readl
+unsigned long readl(unsigned long addr)
+{
+ return __readl(addr);
+}
+
+
+#undef writeb
+void writeb(unsigned short b, unsigned long addr)
+{
+ __writeb(b, addr);
+}
+
+#undef writew
+void writew(unsigned short b, unsigned long addr)
+{
+ __writew(b, addr);
+}
+
+#undef writel
+void writel(unsigned int b, unsigned long addr)
+{
+ __writel(b, addr);
+}
diff --git a/arch/alpha/lib/memcpy.c b/arch/alpha/lib/memcpy.c
new file mode 100644
index 000000000..4bbf92f69
--- /dev/null
+++ b/arch/alpha/lib/memcpy.c
@@ -0,0 +1,74 @@
+/*
+ * linux/arch/alpha/lib/memcpy.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+/*
+ * This is reasonably optimized for the quad-word-aligned case, which
+ * happens with page/buffer copies. It's horribly bad for the unaligned
+ * case: it could be made much better, but that would require lots of
+ * assembly (unaligned 8-byte load + shift + aligned 4-byte store, for
+ * example).
+ */
+
+#include <linux/types.h>
+
+static inline void __memcpy_b(unsigned long d, unsigned long s, long n)
+{
+ while (--n >= 0)
+ *(char *) (d++) = *(char *) (s++);
+}
+
+static inline void __memcpy_q(unsigned long d, unsigned long s, long n)
+{
+ /* this first part could be done in one go with ldq_u*2/mask/stq_u */
+ while (d & 7) {
+ if (--n < 0)
+ return;
+ *(char *) d = *(char *) s;
+ d++;
+ s++;
+ }
+ while ((n -= 8) >= 0) {
+ *(unsigned long *) d = *(unsigned long *) s;
+ d += 8;
+ s += 8;
+ }
+ /* as could this.. */
+ __memcpy_b(d,s,n+8);
+}
+
+static inline void __memcpy_l(unsigned long d, unsigned long s, long n)
+{
+ while (d & 3) {
+ if (--n < 0)
+ return;
+ *(char *) d = *(char *) s;
+ d++;
+ s++;
+ }
+ while ((n -= 4) >= 0) {
+ *(unsigned int *) d = *(unsigned int *) s;
+ d += 4;
+ s += 4;
+ }
+ __memcpy_b(d,s,n+4);
+}
+
+void * __memcpy(void * dest, const void *src, size_t n)
+{
+ unsigned long differ;
+ differ = ((unsigned long) dest ^ (unsigned long) src) & 7;
+
+ if (!differ) {
+ __memcpy_q((unsigned long) dest, (unsigned long) src, n);
+ return dest;
+ }
+ if (differ == 4) {
+ __memcpy_l((unsigned long) dest, (unsigned long) src, n);
+ return dest;
+ }
+ __memcpy_b((unsigned long) dest, (unsigned long) src, n);
+ return dest;
+}
diff --git a/arch/alpha/lib/memset.c b/arch/alpha/lib/memset.c
new file mode 100644
index 000000000..d22d44424
--- /dev/null
+++ b/arch/alpha/lib/memset.c
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/alpha/lib/memset.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+/*
+ * These are only slightly optimized so far..
+ */
+
+#include <linux/types.h>
+
+void * __constant_c_memset(void * s, unsigned long c, long count)
+{
+ unsigned long xs = (unsigned long) s;
+
+ /*
+ * the first and last parts could be done with just one
+ * unaligned load/store, but I don't want to think about it
+ */
+ while (count > 0 && (xs & 7)) {
+ *(char *) xs = c;
+ count--; xs++;
+ }
+ while (count > 7) {
+ *(unsigned long *) xs = c;
+ count -=8; xs += 8;
+ }
+ while (count > 0) {
+ *(char *) xs = c;
+ count--; xs++;
+ }
+ return s;
+}
+
+void * __memset(void * s,char c,size_t count)
+{
+ char *xs = (char *) s;
+
+ while (count--)
+ *xs++ = c;
+
+ return s;
+}
diff --git a/arch/alpha/mm/Makefile b/arch/alpha/mm/Makefile
new file mode 100644
index 000000000..9d825b683
--- /dev/null
+++ b/arch/alpha/mm/Makefile
@@ -0,0 +1,32 @@
+#
+# Makefile for the linux alpha-specific parts of the memory manager.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+.c.o:
+ $(CC) $(CFLAGS) -c $<
+.s.o:
+ $(AS) -o $*.o $<
+.c.s:
+ $(CC) $(CFLAGS) -S $<
+
+OBJS = init.o fault.o
+
+mm.o: $(OBJS)
+ $(LD) -r -o mm.o $(OBJS)
+
+modules:
+
+dep:
+ $(CPP) -M *.c > .depend
+
+#
+# include a dependency file if one exists
+#
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
new file mode 100644
index 000000000..10ac8f496
--- /dev/null
+++ b/arch/alpha/mm/fault.c
@@ -0,0 +1,100 @@
+/*
+ * linux/arch/alpha/mm/fault.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/head.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgtable.h>
+
+extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void tbi(unsigned long type, unsigned long arg);
+#define tbisi(x) tbi(1,(x))
+#define tbisd(x) tbi(2,(x))
+#define tbis(x) tbi(3,(x))
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to handle_mm_fault().
+ *
+ * mmcsr:
+ * 0 = translation not valid
+ * 1 = access violation
+ * 2 = fault-on-read
+ * 3 = fault-on-execute
+ * 4 = fault-on-write
+ *
+ * cause:
+ * -1 = instruction fetch
+ * 0 = load
+ * 1 = store
+ */
+asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr, long cause,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
+{
+ struct vm_area_struct * vma;
+
+ vma = find_vma(current, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
+ goto bad_area;
+ vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
+ vma->vm_start = (address & PAGE_MASK);
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+ if (cause < 0) {
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ } else if (!cause) {
+ /* Allow reads even for write-only mappings */
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
+ goto bad_area;
+ } else {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ }
+ tbis(address);
+ handle_mm_fault(vma, address, cause > 0);
+ return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ if (user_mode(&regs)) {
+ printk("memory violation at pc=%08lx (%08lx)\n", regs.pc, address);
+ die_if_kernel("oops", &regs, cause);
+ send_sig(SIGSEGV, current, 1);
+ return;
+ }
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ printk(KERN_ALERT "Unable to handle kernel paging request at virtual address %08lx\n",address);
+ die_if_kernel("Oops", &regs, cause);
+ do_exit(SIGKILL);
+}
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
new file mode 100644
index 000000000..62203ef84
--- /dev/null
+++ b/arch/alpha/mm/init.c
@@ -0,0 +1,204 @@
+/*
+ * linux/arch/alpha/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/head.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgtable.h>
+#include <asm/hwrpb.h>
+
+extern void scsi_mem_init(unsigned long);
+extern void sound_mem_init(void);
+extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void show_net_buffers(void);
+
+/*
+ * 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.
+ */
+pmd_t * __bad_pagetable(void)
+{
+ memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
+ return (pmd_t *) EMPTY_PGT;
+}
+
+pte_t __bad_page(void)
+{
+ memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
+ return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
+}
+
+unsigned long __zero_page(void)
+{
+ memset((void *) ZERO_PGE, 0, PAGE_SIZE);
+ return (unsigned long) ZERO_PGE;
+}
+
+void show_mem(void)
+{
+ int i,free = 0,total = 0,reserved = 0;
+ int shared = 0;
+
+ printk("\nMem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ i = MAP_NR(high_memory);
+ while (i-- > 0) {
+ total++;
+ if (mem_map[i] & MAP_PAGE_RESERVED)
+ reserved++;
+ else if (!mem_map[i])
+ free++;
+ else
+ shared += mem_map[i]-1;
+ }
+ 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
+}
+
+extern unsigned long free_area_init(unsigned long, unsigned long);
+
+static void load_PCB(struct thread_struct * pcb)
+{
+ __asm__ __volatile__(
+ "stq $30,0(%0)\n\t"
+ "bis %0,%0,$16\n\t"
+ "call_pal %1"
+ : /* no outputs */
+ : "r" (pcb), "i" (PAL_swpctx)
+ : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
+}
+
+/*
+ * paging_init() sets up the page tables: in the alpha version this actually
+ * unmaps the bootup page table (as we're now in KSEG, so we don't need it).
+ */
+unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
+{
+ int i;
+ unsigned long newptbr;
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
+
+ /* initialize mem_map[] */
+ start_mem = free_area_init(start_mem, end_mem);
+
+ /* find free clusters, update mem_map[] accordingly */
+ memdesc = (struct memdesc_struct *) (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+ cluster = memdesc->cluster;
+ for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
+ unsigned long pfn, nr;
+ if (cluster->usage & 1)
+ continue;
+ pfn = cluster->start_pfn;
+ nr = cluster->numpages;
+
+ /* non-volatile memory. We might want to mark this for later */
+ if (cluster->usage & 2)
+ continue;
+
+ while (nr--)
+ mem_map[pfn++] = 0;
+ }
+
+ /* unmap the console stuff: we don't need it, and we don't want it */
+ /* Also set up the real kernel PCB while we're at it.. */
+ memset((void *) ZERO_PGE, 0, PAGE_SIZE);
+ memset(swapper_pg_dir, 0, PAGE_SIZE);
+ newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
+ pgd_val(swapper_pg_dir[1023]) = (newptbr << 32) | pgprot_val(PAGE_KERNEL);
+ init_task.tss.ptbr = newptbr;
+ init_task.tss.flags = 1;
+ init_task.kernel_stack_page = INIT_STACK;
+ load_PCB(&init_task.tss);
+
+ invalidate_all();
+ return start_mem;
+}
+
+void mem_init(unsigned long start_mem, unsigned long end_mem)
+{
+ unsigned long tmp;
+
+ end_mem &= PAGE_MASK;
+ high_memory = end_mem;
+ start_mem = PAGE_ALIGN(start_mem);
+
+ /*
+ * Mark the pages used by the kernel as reserved..
+ */
+ tmp = KERNEL_START;
+ while (tmp < start_mem) {
+ mem_map[MAP_NR(tmp)] = MAP_PAGE_RESERVED;
+ tmp += PAGE_SIZE;
+ }
+
+
+#ifdef CONFIG_SCSI
+ scsi_mem_init(high_memory);
+#endif
+#ifdef CONFIG_SOUND
+ sound_mem_init();
+#endif
+
+ for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
+ if (mem_map[MAP_NR(tmp)])
+ continue;
+ mem_map[MAP_NR(tmp)] = 1;
+ free_page(tmp);
+ }
+ tmp = nr_free_pages << PAGE_SHIFT;
+ printk("Memory: %luk available\n", tmp >> 10);
+ return;
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+ int i;
+
+ i = MAP_NR(high_memory);
+ val->totalram = 0;
+ val->sharedram = 0;
+ val->freeram = nr_free_pages << PAGE_SHIFT;
+ val->bufferram = buffermem;
+ while (i-- > 0) {
+ if (mem_map[i] & MAP_PAGE_RESERVED)
+ continue;
+ val->totalram++;
+ if (!mem_map[i])
+ continue;
+ val->sharedram += mem_map[i]-1;
+ }
+ val->totalram <<= PAGE_SHIFT;
+ val->sharedram <<= PAGE_SHIFT;
+ return;
+}