Import 2.4.0-test3pre82.4.0-test3pre8
authorLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:36:23 +0000 (23 15:36 -0500)
committerLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:36:23 +0000 (23 15:36 -0500)
260 files changed:
Documentation/Configure.help
MAINTAINERS
Makefile
arch/i386/kernel/entry.S
arch/i386/kernel/process.c
arch/mips/Makefile
arch/mips/arc/memory.c
arch/mips/boot/Makefile
arch/mips/cobalt/Makefile[new file with mode: 0644]
arch/mips/cobalt/cobaltscc.c[new file with mode: 0644]
arch/mips/cobalt/diagdefs.h[new file with mode: 0644]
arch/mips/cobalt/hw-access.c[new file with mode: 0644]
arch/mips/cobalt/int-handler.S[new file with mode: 0644]
arch/mips/cobalt/pci.c[new file with mode: 0644]
arch/mips/cobalt/reset.c[new file with mode: 0644]
arch/mips/cobalt/serial.h[new file with mode: 0644]
arch/mips/cobalt/setup.c[new file with mode: 0644]
arch/mips/cobalt/via.c[new file with mode: 0644]
arch/mips/cobalt/z8530.h[new file with mode: 0644]
arch/mips/config.in
arch/mips/ddb5074/pci.c
arch/mips/ddb5074/setup.c
arch/mips/dec/prom/memory.c
arch/mips/defconfig
arch/mips/defconfig-cobalt[copied from arch/mips64/defconfig-ip27 with 52% similarity]
arch/mips/defconfig-decstation
arch/mips/defconfig-ip22
arch/mips/defconfig-rm200[copied from arch/mips64/defconfig-ip22 with 67% similarity]
arch/mips/kernel/Makefile
arch/mips/kernel/fpe.c
arch/mips/kernel/head.S
arch/mips/kernel/irixelf.c
arch/mips/kernel/irixioctl.c
arch/mips/kernel/irixsig.c
arch/mips/kernel/irq.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/scall_o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/signal.c
arch/mips/kernel/softfp.S
arch/mips/kernel/syscall.c
arch/mips/kernel/sysirix.c
arch/mips/kernel/sysmips.c
arch/mips/kernel/time.c
arch/mips/kernel/traps.c
arch/mips/lib/Makefile
arch/mips/lib/r3k_dump_tlb.c
arch/mips/mm/fault.c
arch/mips/mm/init.c
arch/mips/mm/r2300.c
arch/mips/mm/umap.c
arch/mips/sgi/kernel/Makefile
arch/mips/sgi/kernel/indyIRQ.S
arch/mips/sgi/kernel/setup.c
arch/mips/sgi/kernel/time.c
arch/mips/sni/pci.c
arch/mips/sni/setup.c
arch/mips/tools/Makefile
arch/mips64/Makefile
arch/mips64/arc/identify.c
arch/mips64/arc/memory.c
arch/mips64/boot/Makefile
arch/mips64/config.in
arch/mips64/defconfig
arch/mips64/defconfig-ip22
arch/mips64/defconfig-ip27
arch/mips64/kernel/Makefile
arch/mips64/kernel/head.S
arch/mips64/kernel/ioctl32.c
arch/mips64/kernel/linux32.c
arch/mips64/kernel/mips64_ksyms.c
arch/mips64/kernel/process.c
arch/mips64/kernel/ptrace.c
arch/mips64/kernel/r4k_tlb.S[new file with mode: 0644]
arch/mips64/kernel/r4k_tlb_glue.S
arch/mips64/kernel/scall_o32.S
arch/mips64/kernel/setup.c
arch/mips64/kernel/signal.c
arch/mips64/kernel/signal32.c
arch/mips64/kernel/smp.c
arch/mips64/kernel/softfp.S
arch/mips64/kernel/syscall.c
arch/mips64/kernel/traps.c
arch/mips64/ld.script.elf32
arch/mips64/ld.script.elf64
arch/mips64/lib/dump_tlb.c
arch/mips64/lib/floppy-std.c
arch/mips64/mm/andes.c
arch/mips64/mm/fault.c
arch/mips64/mm/init.c
arch/mips64/mm/r4xx0.c
arch/mips64/sgi-ip22/ip22-setup.c
arch/mips64/sgi-ip27/Makefile
arch/mips64/sgi-ip27/ip27-berr.c
arch/mips64/sgi-ip27/ip27-init.c
arch/mips64/sgi-ip27/ip27-irq.c
arch/mips64/sgi-ip27/ip27-klconfig.c
arch/mips64/sgi-ip27/ip27-klnuma.c[new file with mode: 0644]
arch/mips64/sgi-ip27/ip27-memory.c
arch/mips64/sgi-ip27/ip27-nmi.c
arch/mips64/sgi-ip27/ip27-pci.c
arch/mips64/sgi-ip27/ip27-reset.c
arch/mips64/sgi-ip27/ip27-setup.c
arch/mips64/sgi-ip27/ip27-timer.c
arch/mips64/tools/Makefile
arch/sparc/defconfig
arch/sparc64/config.in
arch/sparc64/defconfig
arch/sparc64/kernel/binfmt_aout32.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/lib/Makefile
arch/sparc64/lib/dec_and_lock.S[new file with mode: 0644]
arch/sparc64/mm/ultra.S
arch/sparc64/solaris/fs.c
drivers/Makefile
drivers/block/lvm-snap.c
drivers/char/misc.c
drivers/char/nvram.c
drivers/char/serial.c
drivers/char/tty_io.c
drivers/i2c/i2c-core.c
drivers/ide/ide.c
drivers/net/Space.c
drivers/net/hamradio/dmascc.c
drivers/net/sgiseeq.c
drivers/scsi/NCR53C9x.h
drivers/scsi/dec_esp.c
drivers/scsi/scsi.c
drivers/sgi/Config.in
drivers/sgi/char/ds1286.c
drivers/sgi/char/graphics.c
drivers/sgi/char/sgicons.c
drivers/sgi/char/sgiserial.c
drivers/sgi/char/shmiq.c
drivers/sgi/char/streamable.c
drivers/sgi/char/usema.c
drivers/tc/zs.c
drivers/video/aty128fb.c
drivers/video/matrox/matroxfb_crtc2.c
drivers/video/matrox/matroxfb_maven.c
drivers/video/newport_con.c
drivers/video/valkyriefb.c
drivers/video/valkyriefb.h
fs/binfmt_elf.c
fs/dcache.c
fs/fat/inode.c
fs/partitions/Config.in
fs/partitions/check.c
fs/partitions/ultrix.c
fs/partitions/ultrix.h[new file with mode: 0644]
fs/stat.c
include/asm-alpha/socket.h
include/asm-arm/socket.h
include/asm-i386/socket.h
include/asm-i386/timex.h
include/asm-ia64/socket.h
include/asm-m68k/socket.h
include/asm-mips/delay.h
include/asm-mips/floppy.h
include/asm-mips/highmem.h
include/asm-mips/ide.h
include/asm-mips/keyboard.h
include/asm-mips/mipsregs.h
include/asm-mips/offset.h[deleted file]
include/asm-mips/param.h
include/asm-mips/pgtable.h
include/asm-mips/posix_types.h
include/asm-mips/ptrace.h
include/asm-mips/semaphore-helper.h
include/asm-mips/sfp-machine.h[new file with mode: 0644]
include/asm-mips/signal.h
include/asm-mips/socket.h
include/asm-mips/stat.h
include/asm-mips/system.h
include/asm-mips/types.h
include/asm-mips/uaccess.h
include/asm-mips64/addrspace.h
include/asm-mips64/delay.h
include/asm-mips64/dma.h
include/asm-mips64/floppy.h[copied from include/asm-mips/floppy.h with 62% similarity]
include/asm-mips64/ide.h[copied from include/asm-mips/ide.h with 75% similarity]
include/asm-mips64/io.h
include/asm-mips64/irq.h
include/asm-mips64/mipsregs.h
include/asm-mips64/mmu_context.h
include/asm-mips64/mmzone.h
include/asm-mips64/offset.h[deleted file]
include/asm-mips64/page.h
include/asm-mips64/param.h
include/asm-mips64/pgalloc.h
include/asm-mips64/pgtable.h
include/asm-mips64/posix_types.h
include/asm-mips64/processor.h
include/asm-mips64/ptrace.h
include/asm-mips64/resource.h
include/asm-mips64/serial.h
include/asm-mips64/sfp-machine.h[new file with mode: 0644]
include/asm-mips64/sn/addrs.h
include/asm-mips64/sn/agent.h
include/asm-mips64/sn/arch.h
include/asm-mips64/sn/io.h
include/asm-mips64/sn/klconfig.h
include/asm-mips64/sn/kldir.h
include/asm-mips64/sn/klkernvars.h[new file with mode: 0644]
include/asm-mips64/sn/mapped_kernel.h[new file with mode: 0644]
include/asm-mips64/sn/nmi.h
include/asm-mips64/sn/sn0/ip27.h
include/asm-mips64/sn/sn_private.h
include/asm-mips64/sn/types.h
include/asm-mips64/socket.h
include/asm-mips64/stat.h
include/asm-mips64/uaccess.h
include/asm-ppc/socket.h
include/asm-s390/socket.h
include/asm-sh/socket.h
include/asm-sparc/socket.h
include/asm-sparc64/socket.h
include/linux/dmascc.h[deleted file]
include/linux/in6.h
include/linux/pci_ids.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/tty.h
include/net/checksum.h
include/net/inet_ecn.h[new file with mode: 0644]
include/net/ip.h
include/net/ipv6.h
include/net/neighbour.h
include/net/route.h
include/net/sock.h
kernel/ksyms.c
kernel/sched.c
mm/slab.c
net/core/neighbour.c
net/core/sock.c
net/decnet/dn_route.c
net/ipv4/Config.in
net/ipv4/arp.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_sockglue.c
net/ipv4/ipip.c
net/ipv4/proc.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/ipv6/datagram.c
net/ipv6/proc.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/udp.c
net/netsyms.c
net/packet/af_packet.c
net/sched/sch_red.c
net/sched/sch_teql.c

index e3812f6..9a7ee4a 100644 (file)
@@ -1578,6+1578,16 @@ CONFIG_BAGET_MIPS
   more details about the Baget see the Linux/MIPS FAQ on 
   http://oss.sgi.com/mips .
 
+Support for Cobalt Microserver
+CONFIG_COBALT_MICRO_SERVER
+  This enables support for the Cobalt Microserver.  For more information
+  see the Linux/MIPS FAQ on http://oss.sgi.com/mips .
+
+Support for 2800
+CONFIG_COBALT_28
+  This adds support for the Cobalt Microserver 2800.  A kernel with this
+  option selected will only work on the 2800.
+
 Support for DECstations
 CONFIG_DECSTATION
   This enables support for DEC's MIPS based workstations.  For details
@@ -4308,12+4318,10 @@ CONFIG_DMASCC
   modem), in order to send and receive AX.25 packet radio network
   traffic.
 
-  Currently, this driver supports Ottawa PI/PI2
-  (http://hydra.carleton.ca/info/pi2.html ) and Gracilis PackeTwin
-  (http://www.paccomm.com/gracilis.html ) boards. They are detected
-  automatically. If you have one of these cards, say Y here and read
-  the AX25-HOWTO, available from
-  http://www.linuxdoc.org/docs.html#howto .
+  Currently, this driver supports Ottawa PI/PI2, Paccomm/Gracilis
+  PackeTwin, and S5SCC/DMA boards. They are detected automatically.
+  If you have one of these cards, say Y here and read the AX25-HOWTO,
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   This driver can operate multiple boards simultaneously. If you
   compile it as a module (by saying M instead of Y), it will be called
@@ -4329,7+4337,9 @@ CONFIG_DMASCC
   certain parameters, such as channel access timing, clock mode, and
   DMA channel. This is accomplished with a small utility program,
   dmascc_cfg, available at
-  http://www.nt.tuwien.ac.at/~kkudielk/Linux/ .
+  http://www.nt.tuwien.ac.at/~kkudielk/Linux/ . Please be sure to get
+  at least version 1.27 of dmascc_cfg, as older versions will not
+  work with the current driver.
 
 Z8530 SCC driver for AX.25
 CONFIG_SCC
index b3a4c6d..7fcfdae 100644 (file)
@@ -438,8+438,9 @@ S:      Maintained
 
 HIGH-SPEED SCC DRIVER FOR AX.25
 P:     Klaus Kudielka
-M:     oe1kib@oe1kib.ampr.org
+M:     klaus.kudielka@ieee.org
 L:     linux-hams@vger.rutgers.edu
+W:     http://www.nt.tuwien.ac.at/~kkudielk/Linux/
 S:     Maintained
 
 LOGICAL VOLUME MANAGER
index 0265956..0bb6f6b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -85,11+85,6 @@ CPPFLAGS := -D__KERNEL__ -I$(HPATH)
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Werror
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
 
-# use '-fno-strict-aliasing', but only if the compiler can take it
-CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
-
-export CPPFLAGS CFLAGS AFLAGS
-
 #
 # ROOT_DEV specifies the default root-device when making the image.
 # This can be either FLOPPY, CURRENT, /dev/xxxx or empty, in which case
@@ -179,6+174,11 @@ DRIVERS += $(DRIVERS-y)
 
 include arch/$(ARCH)/Makefile
 
+# use '-fno-strict-aliasing', but only if the compiler can take it
+CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
+
+export CPPFLAGS CFLAGS AFLAGS
+
 export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS
 
 .S.s:
index a80d61e..660a9e1 100644 (file)
@@ -77,8+77,8 @@ sigpending    =  8
 addr_limit     = 12
 exec_domain    = 16
 need_resched   = 20
-processor      = 56
-tsk_ptrace     = 60
+processor      = 48
+tsk_ptrace     = 56
 
 ENOSYS = 38
 
index bddac2a..e240cc7 100644 (file)
@@ -88,12+88,38 @@ static void default_idle(void)
 }
 
 /*
+ * On SMP it's slightly faster (but much more power-consuming!)
+ * to poll the ->need_resched flag instead of waiting for the
+ * cross-CPU IPI to arrive. Use this option with caution.
+ */
+static void poll_idle (void)
+{
+       int oldval;
+
+       __sti();
+
+       /*
+        * Deal with another CPU just having chosen a thread to
+        * run here:
+        */
+       oldval = xchg(&current->need_resched, -1);
+
+       if (!oldval)
+               asm volatile(
+                       "2:"
+                       "cmpl $-1, %0;"
+                       "rep; nop;"
+                       "je 2b;"
+                               : :"m" (current->need_resched));
+}
+
+/*
  * The idle thread. There's no useful work to be
  * done, so just try to conserve power and have a
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
-void cpu_idle(void)
+void cpu_idle (void)
 {
        /* endless idle loop with no priority at all */
        init_idle();
@@ -111,6+137,18 @@ void cpu_idle(void)
        }
 }
 
+static int __init idle_setup (char *str)
+{
+       if (!strncmp(str, "poll", 4)) {
+               printk("using polling idle threads.\n");
+               pm_idle = poll_idle;
+       }
+
+       return 1;
+}
+
+__setup("idle=", idle_setup);
+
 static long no_idt[2] = {0, 0};
 static int reboot_mode = 0;
 static int reboot_thru_bios = 0;
index baccc39..c433f10 100644 (file)
@@ -1,4+1,3 @@
-# $Id: Makefile,v 1.22 2000/01/26 00:07:44 ralf Exp $
 #
 # 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
@@ -101,6+100,12 @@ LIBS          += arch/mips/arc/arclib.a
 LOADADDR      += 0x80080000
 endif
 
+ifdef CONFIG_COBALT_MICRO_SERVER
+ARCHIVES      += arch/mips/cobalt/cobalt.o
+SUBDIRS       += arch/mips/cobalt
+LOADADDR      += 0x80000000
+endif
+
 ifdef CONFIG_SNI_RM200_PCI
 CORE_FILES    += arch/mips/sni/sni.o
 SUBDIRS       += arch/mips/sni arch/mips/arc
@@ -193,6+198,11 @@ archclean:
        $(MAKE) -C arch/mips/baget clean
 
 archmrproper:
+       @$(MAKEBOOT) mrproper
+       $(MAKE) -C arch/$(ARCH)/tools mrproper
 
 archdep:
+       if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \
+        touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \
+       fi;
        @$(MAKEBOOT) dep
index 22c868c..49de2ff 100644 (file)
@@ -144,7+144,7 @@ static inline struct prom_pmemblock *find_largest_memblock(void)
 void __init prom_meminit(void)
 {
        struct prom_pmemblock *largest;
-       unsigned long bootmap_size, kbegin, kend;
+       unsigned long bootmap_size;
        struct linux_mdesc *p;
        int totram;
        int i = 0;
index 1ae3a3f..c59df5a 100644 (file)
@@ -46,9+46,26 @@ dep:
 
 clean:
        rm -f vmlinux.ecoff
+       rm -f zImage zImage.tmp mkboot
+
+mrproper:
+       rm -f vmlinux.ecoff
        rm -f addinitrd
        rm -f elf2ecoff
 
+zImage:        $(CONFIGURE) mkboot $(TOPDIR)/vmlinux
+       $(OBJCOPY) $(strip-flags) $(TOPDIR)/vmlinux zImage.tmp
+       ./mkboot zImage.tmp zImage
+       rm -f zImage.tmp
+
+mkboot: mkboot.c
+       $(HOSTCC) -o $@ $^
+
+zdisk:         zImage
+       cp $(TOPDIR)/vmlinux $(TOPDIR)/vm
+       $(STRIP) $(TOPDIR)/vm
+       gzip -9f $(TOPDIR)/vm
+
 dummy:
 
 include $(TOPDIR)/Rules.make
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
new file mode 100644 (file)
index 0000000..088e1d2
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# Makefile for the Cobalt micro systems family specific parts of the 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).
+#
+# $Id: Makefile,v 1.1 1997/10/23 22:25:41 ralf Exp $
+#
+
+.S.s:
+       $(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+       $(CC) $(CFLAGS) -c $< -o $*.o
+
+all: cobalt.o
+O_TARGET := cobalt.o
+O_OBJS  := cobaltscc.o hw-access.o int-handler.o pci.o reset.o setup.o via.o
+
+int-handler.o: int-handler.S
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/mips/cobalt/cobaltscc.c b/arch/mips/cobalt/cobaltscc.c
new file mode 100644 (file)
index 0000000..05002a1
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Filename: cobaltscc.c
+ * 
+ * Description: Functions for supporting and testing serial I/O
+ * 
+ * Author(s): Timothy Stonis
+ * 
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+#include "z8530.h"
+#include "diagdefs.h"
+#include "serial.h"
+#include "asm/io.h"
+
+/*
+ * Function prototypes
+ */
+void InitSerialPort(unsigned char *);
+void RegisterDelay(void);
+void InitScc(void);
+
+/*
+ * Function: RegisterDelay
+ *
+ * Description: A little delay since the SCC can't handle quick consecutive 
+ *              accesses
+ * In: none
+ * Out: none
+ */
+void RegisterDelay(void)
+{
+       register int ctr;
+  
+       for(ctr=0;ctr<0x40;ctr++);
+}
+
+/*
+ * Function: SccInit
+ *
+ * Description: Initialize all the SCC registers for 19200 baud, asynchronous,
+ *             8 bit, 1 stop bit, no parity communication (Channel A)
+ *
+ * In: none
+ *
+ * Out: none
+ */
+void InitScc(void)
+{
+       /* Force hardware reset */
+       Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, FHWRES);
+       RegisterDelay();
+  
+       /* x32 clock, 1 stop bit, no parity */
+       Write8530(kSCC_ChanA | kSCC_Command, R4 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, X16CLK | SB1);
+       RegisterDelay();
+  
+       /* Rx 8 bits, Rx disabled */
+       Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, Rx8);
+       RegisterDelay();
+   
+       /* Tx 8 bits, DTR, RTS, Tx off */
+       Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, Tx8 | DTR | RTS);
+       RegisterDelay();
+
+       /* Int. Disabled */
+       Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, 0x0);
+       RegisterDelay();
+
+       /* NRZ */
+       Write8530(kSCC_ChanA | kSCC_Command, R10 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, NRZ);
+       RegisterDelay();
+
+       /* Tx & Rx = BRG out, TRxC = BRG out */
+       Write8530(kSCC_ChanA | kSCC_Command, R11 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, TCBR | RCBR | TRxCBR | TRxCOI); 
+       RegisterDelay();
+
+       /* Time constant = 0x01 */
+       Write8530(kSCC_ChanA | kSCC_Command, R12 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, kSCC_115200 ); 
+       RegisterDelay();
+
+       /* Time constant high = 0x00 */
+       Write8530(kSCC_ChanA | kSCC_Command, R13 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, 0x00); 
+       RegisterDelay();
+
+       /* BRG in = ~RTxC, BRG off, loopback */
+       Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, LOOPBAK | BRSRC); 
+       RegisterDelay();
+}
+
+/*
+ * Function: EnableScc
+ *
+ * Description: Enable transmit and receive on SCC Channel A
+ * In: none
+ * Out: none
+ */
+void EnableScc(void)
+{
+       /* Enable BRG */
+       Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, BRENABL | BRSRC);
+       RegisterDelay();
+  
+       /* Rx enable (Rx 8 bits) */
+       Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, RxENABLE | Rx8);
+       RegisterDelay();
+
+       /* Tx enable (Tx8, DTR, RTS) */
+       Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
+       RegisterDelay();
+       Write8530(kSCC_ChanA, TxENAB | Tx8 | DTR | RTS); 
+       RegisterDelay();
+}
+
+/*
+ * Function: SccOutb
+ *
+ * Description: Write a byte to the SCC (Channel A) and blink LED
+ * In: Byte to send
+ * Out: none
+ */
+void SccOutb(unsigned char byte)
+{
+       /* LED on.. */
+       Write8530(kSCC_ChanB | kSCC_Command, R5);
+       RegisterDelay();
+       Write8530(kSCC_ChanB | kSCC_Command, RTS);
+       RegisterDelay();
+       while ((Read8530(kSCC_ChanA) & Tx_BUF_EMP) == 0)
+               RegisterDelay();
+       Write8530(kSCC_ChanA | kSCC_Direct, byte);
+       RegisterDelay();
+       /* LED off.. */
+       Write8530(kSCC_ChanB | kSCC_Command, R9);
+       RegisterDelay();
+       Write8530(kSCC_ChanB | kSCC_Command, CHRB);
+       RegisterDelay();
+}
+
+/*
+ * Function: SccInb
+ *
+ * Description: Read a byte from the SCC (Channel A)
+ * In: Byte to send
+ * Out: none
+ */
+void SccInb(unsigned char *byte)
+{
+       while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0)
+               RegisterDelay();
+       *byte = Read8530(kSCC_ChanA | kSCC_Direct);
+       RegisterDelay();
+}
+
+/*
+ * Function: SccWrite
+ *
+ * Description: Write a null terminated string to the SCC 
+ * In: C string
+ * Out: none
+ */
+void SccWrite(const unsigned char *string)
+{
+       while((*string) != 0) { 
+               if (*string == 10)
+                       SccOutb((unsigned char) 13);
+               SccOutb(*(string++));
+       }
+}
+
+/*
+ * Function: InitSerialPort
+ *
+ * Description: Initialize the SCC and spit out the header message 
+ * In: Header message
+ * Out: none
+ */
+void InitSerialPort(unsigned char *msg)
+{
+       InitScc();
+       EnableScc();
+       SccWrite(msg);
+}
+
+/*
+ * Function: SccInbTimeout
+ *
+ * Description: Read a byte from the SCC (Channel A) with timeout
+ * In: Byte to send
+ * Out: Timeout status
+ */
+unsigned char SccInbTimeout(unsigned char *byte, unsigned long timeout)
+{
+       unsigned long ctr = 0;
+
+       while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) {
+               RegisterDelay();
+               if ((ctr++) > timeout)
+                       return 0xFF;
+       }
+
+       *byte = Read8530(kSCC_ChanA | kSCC_Direct);
+       RegisterDelay();
+       return 0;
+}
+
+#include <linux/serial_reg.h>
+
+extern int serial_echo_init (int base);
+extern int serial_echo_print (const char *s);
+
+/*
+ * this defines the address for the port to which printk echoing is done
+ *  when CONFIG_SERIAL_ECHO is defined
+ */
+#define SERIAL_ECHO_PORT       0x1C800000 
+
+static int serial_echo_port = 0;
+
+#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port)
+#define serial_echo_inb(a)    inb((a)+serial_echo_port)
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/* Wait for transmitter & holding register to empty */
+#define WAIT_FOR_XMITR \
+ do { \
+       lsr = serial_echo_inb(UART_LSR); \
+ } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
+
+/*
+ * These two functions abstract the actual communications with the
+ * debug port.  This is so we can change the underlying communications
+ * mechanism without modifying the rest of the code.
+ */
+int
+serial_echo_print(const char *s)
+{
+        int     lsr, ier;
+        int     i;
+
+        if (!serial_echo_port)
+               return 0;
+
+        /*
+         * First save the IER then disable the interrupts
+         */
+        ier = serial_echo_inb(UART_IER);
+        serial_echo_outb(0x00, UART_IER);
+
+        /*
+         * Now, do each character
+         */
+        for (i = 0; *s; i++, s++) {
+                WAIT_FOR_XMITR;
+
+                /* Send the character out. */
+                serial_echo_outb(*s, UART_TX);
+
+                /* if a LF, also do CR... */
+                if (*s == 10) {
+                        WAIT_FOR_XMITR;
+                        serial_echo_outb(13, UART_TX);
+                }
+        }
+
+        /*
+         * Finally, Wait for transmitter & holding register to empty
+         *  and restore the IER
+         */
+        do {
+                lsr = serial_echo_inb(UART_LSR);
+        } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
+        serial_echo_outb(ier, UART_IER);
+
+        return 0;
+}
+
+
+int
+serial_echo_init(int base)
+{
+        int comstat, hi, lo;
+
+        serial_echo_port = base;
+
+        /*
+         * read the Divisor Latch
+         */
+        comstat = serial_echo_inb(UART_LCR);
+        serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR);
+        hi = serial_echo_inb(UART_DLM);
+        lo = serial_echo_inb(UART_DLL);
+        serial_echo_outb(comstat, UART_LCR);
+
+        /*
+         * now do hardwired init
+         */
+        serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
+        serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
+
+       /* This is computed using:
+        *
+        * const BASE_BAUD = (18432000 / 16);
+        * UART_DLM = (BASE_BAUD / baud_I_want) >> 8;
+        * UART_DLL = (BASE_BAUD / baud_I_want) & 0xff;
+        */
+        serial_echo_outb(0x00, UART_DLM); /* 115200 baud */
+        serial_echo_outb(0x0A, UART_DLL);
+
+        serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
+
+        /*
+        * Prior to disabling interrupts, read the LSR and RBR
+         * registers
+         */
+        comstat = serial_echo_inb(UART_LSR); /* COM? LSR */
+        comstat = serial_echo_inb(UART_RX);     /* COM? RBR */
+        serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */
+
+        return 0;
+}
diff --git a/arch/mips/cobalt/diagdefs.h b/arch/mips/cobalt/diagdefs.h
new file mode 100644 (file)
index 0000000..6bfedbd
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Filename: diagdefs.h
+ * 
+ * Description: Some general definitions used by the diagnostics 
+ * 
+ * Author(s): Timothy Stonis
+ * 
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+
+#define KSEG0_Base             0x80000000
+#define KSEG1_Base             0xA0000000
+
+// Some useful Galileo registers/base addresses (boot time kseg1 mapping) 
+#define kGal_InternalBase      ( 0x14000000 | KSEG1_Base ) 
+#define kGal_DevBank0Base      ( 0x1C000000 | KSEG1_Base )
+#define kGal_DevBank1Base      ( 0x1C800000 | KSEG1_Base )
+
+#define kGal_RAS10Lo           0x008
+#define kGal_RAS10Hi           0x010
+#define kGal_RAS32Lo           0x018
+#define kGal_RAS32Hi           0x020
+
+#define kGal_PCIIOLo           0x048
+#define kGal_PCIIOHi           0x050
+
+#define kGal_RAS10LoCfg                0x000
+#define kGal_RAS10HiCfg                0x03
+#define kGal_RAS32LoCfg                0x004
+#define kGal_RAS32HiCfg                0x07
+
+#define kGal_PCIIOLoCfg                0x000
+#define kGal_PCIIOHiCfg                0x0F
+
+
+#define kGal_DevBank0PReg      0x45C
+#define kGal_DevBank1PReg      0x460
+#define kGal_DevBank2PReg      0x464
+#define kGal_DevBank3PReg      0x468
+#define kGal_DevBankBPReg      0x46C
+
+#define kGal_DRAMCReg          0x448
+#define kGal_DRAM0PReg         0x44C
+#define kGal_DRAM1PReg         0x450
+#define kGal_DRAM2PReg         0x454
+#define kGal_DRAM3PReg         0x458
+
+#define kGal_ConfigAddr                0xCF8
+#define kGal_ConfigData                0xCFC
+#define kGal_PCICfgEn          0x1F // Generate config cycle 
+#define kGal_DevNum            0x00 // Technically 0x06, but 0 works too
+#define kGal_MasMemEn          0x06
+#define kGal_Latency           0x700
+
+#define kGal_RAS01StartReg     0x10
+#define kGal_RAS23StartReg     0x14
+#define kGal_RAS01SizeReg      0x0C08
+#define kGal_RAS23SizeReg      0x0C0C
+
+
+#define kGal_RAS01Start                0x000
+#define kGal_RAS23Start                0x00800000
+#define kGal_RAS01Size         0x007FFFFF
+#define kGal_RAS23Size         0x007FFFFF
+
+
+// Paramter information for devices, DRAM, etc
+#define        kGal_DevBank0Cfg        0x1446DB33
+#define        kGal_DevBank1Cfg        0x144FE667
+#define        kGal_DevBankBCfg        0x1446DC43
+#define        kGal_DRAMConfig         0x00000300
+#define        kGal_DRAM0Config        0x00000010
+#define        kGal_DRAM1Config        0x00000010
+#define        kGal_DRAM2Config        0x00000010
+#define        kGal_DRAM3Config        0x00000010
+
+#define        kGal_DRAM0Hi            0x00000003
+#define        kGal_DRAM0Lo            0x00000000
+#define        kGal_DRAM1Hi            0x00000007
+#define        kGal_DRAM1Lo            0x00000004
+#define        kGal_DRAM2Hi            0x0000000B
+#define        kGal_DRAM2Lo            0x00000008
+#define        kGal_DRAM3Hi            0x0000000F
+#define        kGal_DRAM3Lo            0x0000000C
+
+#define kGal_RAS0Lo            0x400
+#define kGal_RAS0Hi            0x404
+#define kGal_RAS1Lo            0x408
+#define kGal_RAS1Hi            0x40C
+#define kGal_RAS2Lo            0x410
+#define kGal_RAS2Hi            0x414
+#define kGal_RAS3Lo            0x418
+#define kGal_RAS3Hi            0x41C
+
+// Feedback LED indicators during setup code (reset.S, main.c) 
+#define kLED_AllOn     0x0F
+#define kLED_FlashTest 0x01
+#define kLED_MemTest   0x02
+#define kLED_SCCTest   0x03
+#define kLED_GalPCI    0x04
+#define kLED_EnetTest  0x05
+#define kLED_SCSITest  0x06
+#define kLED_IOCTest   0x07
+#define kLED_Quickdone 0x0A
+#define kLED_Exception 0x0B
+#define kLED_ProcInit  0x0E
+#define kLED_AllOff    0x00
+
+#define kLEDBase       kGal_DevBank0Base
+
+// Some memory related constants 
+#define kRAM_Start     (0x00000000 | KSEG0_Base)
+
+#define        kTestPat1       0xA5A5A5A5
+#define kTestPat2      0x5A5A5A5A
+
+#define k1Meg_kseg1    (0x00100000 | KSEG0_Base)
+#define k2Meg_kseg1    (0x00200000 | KSEG0_Base)
+#define k4Meg_kseg1    (0x00400000 | KSEG0_Base)
+#define k8Meg_kseg1    (0x00800000 | KSEG0_Base)
+#define k16Meg_kseg1   (0x01000000 | KSEG0_Base)
+
+#define kInit_SP       k4Meg_kseg1 - 0x100
+#define kVectorBase    0x200   
+#define kDebugVectors  0x400
+#define kMallocCheese  0x80E00000
+#define kDecompAddr    0x80700000
+#define kCompAddr      0x80500000
+
+
+// Ethernet definitions
+#define        kEnet_VIOBase   ( 0x12100000 | KSEG1_Base )
+#define        kEnet_PIOBase   0x12100000
+#define        kEnet_CSCfg     0x46
+#define kEnet_DevNum   0x07
+#define kEnet_CSR3     0x18
+#define kEnet_CSR15    0x78
+
+
+#define kEnet_GEPOut   0x080f0000
+#define kEnet_GEPOn    0x000f0000
+
+
+// SCSI definitions
+#define        kSCSI_VIOBase   ( 0x12200000 | KSEG1_Base )
+#define        kSCSI_PIOBase   0x12200000 
+#define        kSCSI_CSCfg     0x46 
+#define kSCSI_DevNum   0x08
+#define kSCSI_GPCNTL   0x47
+#define kSCSI_GPREG    0x07
+#define kSCSI_SCRTCHA  0x34
+
+#define kSCSI_GPIOOut  0x0C
+#define kSCSI_LEDsOn   0x00
+
+// I/O Controller definitions
+#define kIOC_VIOBase   ( 0x10000000 | KSEG1_Base )
+#define kIOC_RIOBase   0x10000000 
+#define kIOC_DevNum    0x09
+#define kIOC_ISAFunc   0x00
+#define kIOC_IDEFunc   0x01
+#define kIOC_USBFunc   0x02
+#define kIOC_MiscC0    0x44
+#define kIOC_IDEEnable 0x40
+
+#define kIOC_PCIIDEOn  0x02800085
+#define kIOC_PriIDEOn  0x0A
+
+// Some PCI Definitions
+#define        kPCI_StatCmd    0x04
+#define        kPCI_LatCache   0x0C
+#define        kPCI_CBIO       0x10
+#define        kPCI_CBMEM      0x14
+
+// Random constants
+#define kBogoSec       0x0003F940
+#define kSCCDelay      0x00000001
diff --git a/arch/mips/cobalt/hw-access.c b/arch/mips/cobalt/hw-access.c
new file mode 100644 (file)
index 0000000..968dfef
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Low-level hardware access stuff for Cobalt Microserver 27 board.
+ *
+ * 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) 1995, 1996, 1997 by Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+#include <asm/cachectl.h>
+#include <asm/cobalt.h>
+#include <asm/segment.h>
+#include <asm/vector.h>
+
+void
+dummy(void)
+{
+       panic("What the hell is this called for?");
+}
+
+static unsigned char cobalt_read_cmos(unsigned long reg)
+{
+       unsigned char retval;
+
+       VIA_PORT_WRITE(0x70, reg);
+       retval = VIA_PORT_READ(0x71);
+       VIA_DELAY();
+
+       return retval;
+}
+
+static void cobalt_write_cmos(unsigned char val, unsigned long reg)
+{
+       VIA_PORT_WRITE(0x70, reg);
+       VIA_PORT_WRITE(0x71, val); 
+}
+
+struct feature cobalt_feature = {
+       /*
+        * How to access the floppy controller's ports
+        */
+       (void *)dummy, (void *)dummy,
+       /*
+        * How to access the floppy DMA functions.
+        */
+       (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
+       (void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
+       (void *)dummy, (void *)dummy, (void *)dummy,
+       /*
+        * How to access the RTC functions.
+        */
+       cobalt_read_cmos,
+       cobalt_write_cmos
+};
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
new file mode 100644 (file)
index 0000000..66c0d78
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * arch/mips/cobalt/int-handler.S
+ */
+#include <asm/asm.h>
+#include <asm/mipsconfig.h>
+#include <asm/mipsregs.h>
+#include <asm/cobalt.h>
+#include <asm/irq.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+/*
+ * cobalt_handle_int: Interrupt handler for the twenty-seven board.
+ */
+               .align  5
+               .set    noreorder
+               NESTED(cobalt_handle_int, PT_SIZE, ra)
+               .set    noat
+               SAVE_ALL
+               REG_S   sp,PT_OR2(sp)
+               CLI
+               .set    at
+               mfc0    t0,CP0_CAUSE
+               mfc0    t1,CP0_STATUS
+               and     t0,t1
+               xor     t1,t0
+               mtc0    t1,CP0_STATUS   # mask all active ints
+               /* Such a kind of cascade is optimal for R5000 */
+
+               andi    t1,t0,STATUSF_IP2
+               bnez    t1,ll_galileo_irq
+                andi   t1,t0,STATUSF_IP3
+               bnez    t1,ll_ethernet0_irq
+/*
+ * This should be conditional, and not used for the cube-1, but
+ * there is not a config flag that is useful.
+ */
+       
+                andi   t1,t0,STATUSF_IP4
+               bnez    t1,ll_ethernet1_irq
+/* #endif  */
+                andi   t1,t0,STATUSF_IP6
+               bnez    t1,ll_via_irq
+                andi   t1,t0,STATUSF_IP5
+               bnez    t1,ll_serial_irq
+                andi   t1,t0,STATUSF_IP7
+               bnez    t1,ll_pci_irq
+                 nop
+               /* wrong alarm ... */
+               j       spurious_interrupt
+                nop
+               END(cobalt_handle_int)
+       
+
+               .align  5
+               .set    reorder
+ll_galileo_irq:        move    a0,sp
+               INC_INTR_COUNT(s1,s2)
+               jal     galileo_irq
+                 nop
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
+
+               .align  5
+               .set    reorder
+ll_via_irq:    move    a0,sp
+               INC_INTR_COUNT(s1,s2)
+               jal     via_irq
+                 nop
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
+
+               .align  5
+               .set    reorder
+ll_ethernet0_irq:
+               INC_INTR_COUNT(s1,s2)
+               mfc0    s0,CP0_STATUS           # mask interrupt
+               ori     t0,s0,(STATUSF_IP3 | STATUSF_IP4)
+               xori    t0,(STATUSF_IP3 | STATUSF_IP4)
+               mtc0    t0,CP0_STATUS
+               li      a0,4
+               move    a1,sp
+               jal     do_IRQ
+                 nop
+               mtc0    s0,CP0_STATUS
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
+
+               .align  5
+               .set    reorder
+ll_serial_irq: li      a0,7
+               INC_INTR_COUNT(s1,s2)
+               move    a1,sp
+               jal     do_IRQ
+                 nop
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
+
+
+               .align  5
+               .set    reorder
+ll_ethernet1_irq:
+               INC_INTR_COUNT(s1,s2)
+               mfc0    s0,CP0_STATUS           # mask interrupt
+
+               ori     t0,s0, (STATUSF_IP3 | STATUSF_IP4)
+               xori    t0,(STATUSF_IP3 | STATUSF_IP4)
+
+               mtc0    t0,CP0_STATUS
+               li      a0,13
+               move    a1,sp
+               jal     do_IRQ
+                 nop
+               mtc0    s0,CP0_STATUS
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
+
+       #
+       # This is pretty weird.  The "pci" interrupt on the hardware
+       # skematic is from the PCI side of the galileo, so we would
+       # only get interrupts here if WE write the control register
+       # that normally enables the cpu to send interrupts to the PCI.
+       #
+       # If you want to interrupt a PCI card, look elsewhere.
+       #
+               .align  5
+               .set    reorder
+ll_pci_irq:    li      a0,7
+               INC_INTR_COUNT(s1,s2)
+               move    a1,sp
+               jal     do_IRQ
+                 nop
+               DEC_INTR_COUNT(s1,s2)
+               j       ret_from_irq
+                 nop
diff --git a/arch/mips/cobalt/pci.c b/arch/mips/cobalt/pci.c
new file mode 100644 (file)
index 0000000..a325ad7
--- /dev/null
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ *
+ * Cobalt Qube specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <asm/cobalt.h>
+#include <asm/pci.h>
+#include <asm/io.h>
+#undef PCI_DEBUG 
+
+#ifdef CONFIG_PCI
+
+static void qube_expansion_slot_bist(void)
+{
+       unsigned char ctrl;
+       int timeout = 100000;
+
+       pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
+       if(!(ctrl & PCI_BIST_CAPABLE))
+               return;
+
+       pcibios_write_config_byte(0, (0x0a<<3), PCI_BIST, ctrl|PCI_BIST_START);
+       do {
+               pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
+               if(!(ctrl & PCI_BIST_START))
+                       break;
+       } while(--timeout > 0);
+       if((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK))
+               printk("PCI: Expansion slot card failed BIST with code %x\n",
+                      (ctrl & PCI_BIST_CODE_MASK));
+}
+
+static void qube_expansion_slot_fixup(void)
+{
+       unsigned short pci_cmd;
+       unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */
+       unsigned long memaddr_base = 0x12000000;
+       int i;
+
+       /* Enable bits in COMMAND so driver can talk to it. */
+       pcibios_read_config_word(0, (0x0a<<3), PCI_COMMAND, &pci_cmd);
+       pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+       pcibios_write_config_word(0, (0x0a<<3), PCI_COMMAND, pci_cmd);
+
+       /* Give it a working IRQ. */
+       pcibios_write_config_byte(0, (0x0a<<3), PCI_INTERRUPT_LINE, 9);
+
+       /* Fixup base addresses, we only support I/O at the moment. */
+       for(i = 0; i <= 5; i++) {
+               unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4));
+               unsigned int rval, mask, size, alignme, aspace;
+               unsigned long *basep = &ioaddr_base;
+
+               /* Check type first, punt if non-IO. */
+               pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
+               aspace = (rval & PCI_BASE_ADDRESS_SPACE);
+               if(aspace != PCI_BASE_ADDRESS_SPACE_IO)
+                       basep = &memaddr_base;
+
+               /* Figure out how much it wants, if anything. */
+               pcibios_write_config_dword(0, (0x0a<<3), regaddr, 0xffffffff);
+               pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
+
+               /* Unused? */
+               if(rval == 0)
+                       continue;
+
+               rval &= PCI_BASE_ADDRESS_IO_MASK;
+               mask = (~rval << 1) | 0x1;
+               size = (mask & rval) & 0xffffffff;
+               alignme = size;
+               if(alignme < 0x400)
+                       alignme = 0x400;
+               rval = ((*basep + (alignme - 1)) & ~(alignme - 1));
+               *basep = (rval + size);
+               pcibios_write_config_dword(0, (0x0a<<3), regaddr, rval | aspace);
+       }
+       qube_expansion_slot_bist();
+}
+
+static void qube_raq_tulip_fixup(void)
+{
+       unsigned short pci_cmd;
+
+       /* Enable the device. */
+       pcibios_read_config_word(0, (0x0c<<3), PCI_COMMAND, &pci_cmd);
+       pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+       pcibios_write_config_word(0, (0x0c<<3), PCI_COMMAND, pci_cmd);
+
+       /* Give it it's IRQ. */
+       /* NOTE: RaQ board #1 has a bunch of green wires which swapped the
+        *       IRQ line values of Tulip 0 and Tulip 1.  All other
+        *       boards have eth0=4,eth1=13.  -DaveM
+        */
+#ifndef RAQ_BOARD_1_WITH_HWHACKS
+       pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 13);
+#else
+       pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 4);
+#endif
+
+       /* And finally, a usable I/O space allocation, right after what
+        * the first Tulip uses.
+        */
+       pcibios_write_config_dword(0, (0x0c<<3), PCI_BASE_ADDRESS_0, 0x10101001);
+}
+
+static void qube_raq_scsi_fixup(void)
+{
+       unsigned short pci_cmd;
+
+       /* Enable the device. */
+       pcibios_read_config_word(0, (0x08<<3), PCI_COMMAND, &pci_cmd);
+
+       pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
+               | PCI_COMMAND_INVALIDATE);
+       pcibios_write_config_word(0, (0x08<<3), PCI_COMMAND, pci_cmd);
+
+       /* Give it it's IRQ. */
+       pcibios_write_config_byte(0, (0x08<<3), PCI_INTERRUPT_LINE, 4);
+
+       /* And finally, a usable I/O space allocation, right after what
+        * the second Tulip uses.
+        */
+       pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_0, 0x10102001);
+       pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_1, 0x00002000);
+       pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_2, 0x00100000);
+}
+
+static unsigned long
+qube_pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
+{
+       extern int cobalt_is_raq;
+       int raq_p = cobalt_is_raq;
+       unsigned int tmp;
+
+       /* Fixup I/O and Memory space decoding on Galileo.  */
+       isa_slot_offset = COBALT_LOCAL_IO_SPACE;
+
+       /* Fix PCI latency-timer and cache-line-size values in Galileo
+        * host bridge.
+        */
+       pcibios_write_config_byte(0, 0, PCI_LATENCY_TIMER, 64);
+       pcibios_write_config_byte(0, 0, PCI_CACHE_LINE_SIZE, 7);
+
+        /*
+         * Now tell the SCSI device that we expect an interrupt at
+         * IRQ 7 and not the default 0.
+         */
+        pcibios_write_config_byte(0, 0x08<<3, PCI_INTERRUPT_LINE,
+                                  COBALT_SCSI_IRQ);
+
+        /*
+         * Now tell the Ethernet device that we expect an interrupt at
+         * IRQ 13 and not the default 189.
+        *
+        * The IRQ of the first Tulip is different on Qube and RaQ
+        * hardware except for the weird first RaQ bringup board,
+        * see above for details.  -DaveM
+         */
+       if (! raq_p) {
+               /* All Qube's route this the same way. */
+               pcibios_write_config_byte(0, 0x07<<3, PCI_INTERRUPT_LINE,
+                                         COBALT_ETHERNET_IRQ);
+       } else {
+#ifndef RAQ_BOARD_1_WITH_HWHACKS
+               pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 4);
+#else
+               pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 13);
+#endif
+       }
+
+       if (! raq_p) {
+               /* See if there is a device in the expansion slot, if so
+                * fixup IRQ, fix base addresses, and enable master +
+                * I/O + memory accesses in config space.
+                */
+               pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
+               if(tmp != 0xffffffff && tmp != 0x00000000)
+                       qube_expansion_slot_fixup();
+       } else {
+               /* If this is a RAQ, we may need to setup the second Tulip
+                * and SCSI as well.  Due to the different configurations
+                * a RaQ can have, we need to explicitly check for the
+                * presence of each of these (optional) devices.  -DaveM
+                */
+               pcibios_read_config_dword(0, 0x0c<<3, PCI_VENDOR_ID, &tmp);
+               if(tmp != 0xffffffff && tmp != 0x00000000)
+                       qube_raq_tulip_fixup();
+
+               pcibios_read_config_dword(0, 0x08<<3, PCI_VENDOR_ID, &tmp);
+               if(tmp != 0xffffffff && tmp != 0x00000000)
+                       qube_raq_scsi_fixup();
+
+               /* And if we are a 2800 we have to setup the expansion slot
+                * too.
+                */
+               pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
+               if(tmp != 0xffffffff && tmp != 0x00000000)
+                       qube_expansion_slot_fixup();
+       }
+
+       return mem_start;
+}
+
+static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) 
+{
+       if ((bus == 0) && ( (dev==0) || ((dev>6) && (dev <= 12))) )
+               return 0;  /* OK device number  */
+
+       return -1;  /* NOT ok device number */
+}
+
+#define PCI_CFG_DATA   ((volatile unsigned long *)0xb4000cfc)
+#define PCI_CFG_CTRL   ((volatile unsigned long *)0xb4000cf8)
+
+#define PCI_CFG_SET(dev,fun,off) \
+       ((*PCI_CFG_CTRL) = (0x80000000 | ((dev)<<11) | \
+                           ((fun)<<8) | (off)))
+
+static int qube_pcibios_read_config_dword (unsigned char bus,
+                                          unsigned char dev,
+                                          unsigned char offset,
+                                          unsigned int *val)
+{
+       unsigned char fun = dev & 0x07;
+
+       dev >>= 3;
+       if (offset & 0x3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       if (pci_range_ck(bus, dev)) {
+               *val = 0xFFFFFFFF;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+       PCI_CFG_SET(dev, fun, offset);
+       *val = *PCI_CFG_DATA;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_read_config_word (unsigned char bus,
+                                         unsigned char dev,
+                                         unsigned char offset,
+                                         unsigned short *val)
+{
+       unsigned char fun = dev & 0x07;
+
+       dev >>= 3;
+       if (offset & 0x1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       if (pci_range_ck(bus, dev)) {
+               *val = 0xffff;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+       PCI_CFG_SET(dev, fun, (offset & ~0x3));
+       *val = *PCI_CFG_DATA >> ((offset & 3) * 8);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_read_config_byte (unsigned char bus,
+                                         unsigned char dev,
+                                         unsigned char offset,
+                                         unsigned char *val)
+{
+       unsigned char fun = dev & 0x07;
+
+       dev >>= 3;
+       if (pci_range_ck(bus, dev)) {
+               *val = 0xff;
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+       PCI_CFG_SET(dev, fun, (offset & ~0x3));
+       *val = *PCI_CFG_DATA >> ((offset & 3) * 8);
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int qube_pcibios_write_config_dword (unsigned char bus,
+                                           unsigned char dev,
+                                           unsigned char offset,
+                                           unsigned int val)
+{
+       unsigned char fun = dev & 0x07;
+
+       dev >>= 3;
+       if(offset & 0x3)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       if (pci_range_ck(bus, dev))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       PCI_CFG_SET(dev, fun, offset);
+       *PCI_CFG_DATA = val;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+qube_pcibios_write_config_word (unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned short val)
+{
+       unsigned char fun = dev & 0x07;
+       unsigned long tmp;
+
+       dev >>= 3;
+       if (offset & 0x1)
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+       if (pci_range_ck(bus, dev))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       PCI_CFG_SET(dev, fun, (offset & ~0x3));
+       tmp = *PCI_CFG_DATA;
+       tmp &= ~(0xffff << ((offset & 0x3) * 8));
+       tmp |=  (val << ((offset & 0x3) * 8));
+       *PCI_CFG_DATA = tmp;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+qube_pcibios_write_config_byte (unsigned char bus, unsigned char dev,
+                                unsigned char offset, unsigned char val)
+{
+       unsigned char fun = dev & 0x07;
+       unsigned long tmp;
+
+       dev >>= 3;
+       if (pci_range_ck(bus, dev))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+       PCI_CFG_SET(dev, fun, (offset & ~0x3));
+       tmp = *PCI_CFG_DATA;
+       tmp &= ~(0xff << ((offset & 0x3) * 8));
+       tmp |=  (val << ((offset & 0x3) * 8));
+       *PCI_CFG_DATA = tmp;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops qube_pci_ops = {
+       qube_pcibios_fixup,
+       qube_pcibios_read_config_byte,
+       qube_pcibios_read_config_word,
+       qube_pcibios_read_config_dword,
+       qube_pcibios_write_config_byte,
+       qube_pcibios_write_config_word,
+       qube_pcibios_write_config_dword
+};
+
+#endif /* CONFIG_PCI */
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
new file mode 100644 (file)
index 0000000..b91c51f
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ *  Reset a Cobalt Qube.
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+
+void cobalt_machine_restart(char *command)
+{
+       *(volatile char *)0xbc000000 = 0x0f;
+
+       /*
+        * Ouch, we're still alive ... This time we take the silver bullet ...
+        * ... and find that we leave the hardware in a state in which the
+        * kernel in the flush locks up somewhen during of after the PCI
+        * detection stuff.
+        */
+       set_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL));
+       set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_UNCACHED);
+       flush_cache_all();
+       write_32bit_cp0_register(CP0_WIRED, 0);
+       __asm__ __volatile__(
+               "jr\t%0"
+               :
+               : "r" (0xbfc00000));
+}
+
+extern int led_state;
+#define kLED            0xBC000000
+#define LEDSet(x)       (*(volatile unsigned char *) kLED) = (( unsigned char)x)
+
+void cobalt_machine_halt(void)
+{
+       int mark;
+
+       // Blink our cute little LED (number 3)...
+       while (1) {
+               led_state = led_state | ( 1 << 3 );
+               LEDSet(led_state);  
+               mark = jiffies;
+               while (jiffies<(mark+HZ));
+               led_state = led_state & ~( 1 << 3 );
+               LEDSet(led_state);
+               mark = jiffies;
+               while (jiffies<(mark+HZ));
+       } 
+}
+
+/*
+ * This triggers the luser mode device driver for the power switch ;-)
+ */
+void cobalt_machine_power_off(void)
+{
+       printk("You can switch the machine off now.\n");
+       cobalt_machine_halt();
+}
diff --git a/arch/mips/cobalt/serial.h b/arch/mips/cobalt/serial.h
new file mode 100644 (file)
index 0000000..586f68f
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 
+ * Filename: serial.h
+ * 
+ * Description: Some general definitions used for serial code 
+ * 
+ * Author(s): Timothy Stonis
+ * 
+ * Copyright 1997, Cobalt Microserver, Inc.
+ */
+/*
+ * Serial port definitions
+ */
+#define kSCC_Base      kGal_DevBank1Base
+#define kHelloWorldMsg "Cobalt Networks Diagnostics - 'We serve it, you surf it'\n\r"
+#define kSCC_ChanA     0x01
+#define kSCC_ChanB     0x00
+#define kSCC_Direct    0x02
+#define kSCC_Command   0x00
+
+#define kSCC_TestVal   0xA5
+#define kSCC_19200     0x07    /* x32 clock mode, 19200 baud   */
+#define kSCC_115200    0x01    /* x16 clock mode, 115200 baud  */
+
+#define Read8530(n)    (*((unsigned char *) (kSCC_Base | (n))))
+
+#define Write8530(x,y) (*((unsigned char *) (kSCC_Base | (x))) = (y))
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
new file mode 100644 (file)
index 0000000..cb11a59
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * Setup pointers to hardware dependand routines.
+ *
+ * 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) 1996, 1997 by Ralf Baechle
+ */
+#include <linux/bios32.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/cobalt.h>
+#include <asm/pci.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/reboot.h>
+#include <asm/vector.h>
+
+extern void cobalt_machine_restart(char *command);
+extern void cobalt_machine_halt(void);
+extern void cobalt_machine_power_off(void);
+
+extern int serial_console;
+
+/*
+ * Initial irq handlers.
+ */
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{ 
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+
+extern struct feature cobalt_feature;
+extern asmlinkage void cobalt_handle_int(void);
+
+static void cobalt_irq_setup(void) 
+{
+       /*
+        * Clear all of the interrupts while we change the able around a bit.
+        */
+       set_cp0_status(ST0_IM, 0);
+
+       /* Sets the exception_handler array. */
+       set_except_vector(0, cobalt_handle_int);
+
+       request_region(0xb0000020, 0x20, "pic1");
+       request_region(0xb00000A0, 0x20, "pic2");
+       setup_x86_irq(2, &irq2);
+
+       cli();
+
+       set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1 | IE_IRQ0);
+
+       /* Setup VIA irq mask */
+       VIA_PORT_WRITE(0x20, 0x10);
+       VIA_PORT_WRITE(0x21, 0x00);
+       VIA_PORT_WRITE(0x21, 0x00);
+
+       VIA_PORT_WRITE(0xa0, 0x10);
+       VIA_PORT_WRITE(0xa1, 0x00);
+       VIA_PORT_WRITE(0xa1, 0x00);
+}
+
+void (*board_time_init)(struct irqaction *irq);
+
+static void cobalt_calibrate_timer(void)
+{
+       volatile unsigned long *timer_reg = (volatile unsigned long *)0xb4000850;
+
+       /* Default to 150MHZ, since this is what we are shipping. */
+       *timer_reg = 500000;
+}
+
+static void cobalt_time_init(struct irqaction *irq)
+{
+       /* Load timer value for 100 Hz */
+       cobalt_calibrate_timer();
+       /* *((volatile unsigned long *) 0xb4000850) = (unsigned long) 440000; */
+
+       setup_x86_irq(0, irq);
+
+       /* Enable timer ints */
+       *((volatile unsigned long *) 0xb4000864) = (unsigned long) 0x00000003;
+       /* Unmask timer int */
+       *((volatile unsigned long *) 0xb4000c1c) = (unsigned long) 0x00000100; 
+}
+
+extern struct pci_ops qube_pci_ops;
+int cobalt_serial_present;
+int cobalt_serial_type;
+int cobalt_is_raq;
+
+void cobalt_setup(void)
+{
+       tag *atag;
+
+       /*
+        * We just check if a tag_screen_info can be gathered
+        * in setup_arch(), if yes we don't proceed futher...
+        */
+       atag = bi_TagFind(tag_screen_info);
+       if (!atag) {
+               /*
+                * If no, we try to find the tag_arc_displayinfo which is
+                * always created by Milo for an ARC box (for now Milo only
+                * works on ARC boxes :) -Stoned.
+                */
+               atag = bi_TagFind(tag_arcdisplayinfo);
+               if (atag) {
+
+                       screen_info.orig_x = 
+                               ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
+                       screen_info.orig_y = 
+                               ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
+                       screen_info.orig_video_cols  = 
+                               ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
+                       screen_info.orig_video_lines  = 
+                               ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
+               }
+       }
+
+       _machine_restart = cobalt_machine_restart;
+       _machine_halt = cobalt_machine_halt;
+       _machine_power_off = cobalt_machine_power_off;
+
+       irq_setup = cobalt_irq_setup;
+       board_time_init = cobalt_time_init;
+       feature = &cobalt_feature;
+       mips_io_port_base = COBALT_LOCAL_IO_SPACE;
+
+       pci_ops = &qube_pci_ops;
+
+#ifdef CONFIG_COBALT_SERIAL
+       serial_console = 1;
+#endif /* CONFIG_COBALT_SERIAL */
+
+       /* We have to do this early, here, before the value could
+        * possibly be overwritten by the bootup sequence.
+        */
+       cobalt_serial_present = *((unsigned long *) 0xa020001c);
+       cobalt_serial_type    = *((unsigned long *) 0xa0200020);
+       cobalt_is_raq         = (cobalt_serial_present != 0x0
+                                && cobalt_serial_type == 0x1);
+}
+
+void   AddTagsEndSymbol(void);
+int bi_TagAdd (enum bi_tag type, unsigned long size, void *data);
+unsigned long next_tag = (unsigned long) NULL;
+unsigned long memory_upper = (unsigned long) NULL;
+
+int bi_TagAdd (enum bi_tag type, unsigned long size, void *data)
+{
+       tag t;
+       unsigned long addr;
+
+       t.tag = type;
+       t.size = size;
+
+       /*
+        * If next_tag equals NULL it means it's the first tag we're asked
+        * to create.
+        */
+       if (next_tag == (unsigned long) NULL)  {
+               /*
+                * If memory_upper not equals NULL it means that identify()
+                * was able to figure out how much memory is present in the
+                * box so we initialize next_tag from it.
+                */
+               if (memory_upper != (unsigned long) NULL)
+                       next_tag = memory_upper;
+
+               /* Else we rely on the fact that the first tag we create for
+                * a box for which we don't know how RAM it gots is a tag of
+                * type tag_memupper.  This is ensured by the first entry in
+                * the defaults tag list for such a box (see identify.c).
+                * First we check this.
+                */
+               else {
+                       /* Ok it's a memupper tag: we put it's value in 
+                        * memory_upper so launch() can pass it to the
+                        * kernel in register a0 and we initialize next_tag.
+                        */
+                       next_tag = *(unsigned long *) data;
+                       memory_upper = *((unsigned long *) data);
+               }
+       }
+
+       /* We put the tag structure.  */
+       addr = next_tag - (sizeof (tag));
+
+       memcpy ((void *) addr, (void *) &t, (size_t) (sizeof (tag)));
+
+       /* We put the tag's data if any.  */
+       if (size != 0) {
+               addr = addr - size;
+               memcpy ((void *) addr, data, (size_t) (t.size));
+       }
+
+       /*
+        * Set next_tag ready for the next tag creation.
+        */
+       next_tag = addr;
+       AddTagsEndSymbol();
+
+       return 0;
+}
+
+void SetUpBootInfo(void)
+{
+       unsigned long LongVar;
+       int atag;
+
+       /*
+        * This is hard coded here but will change when we have a
+        * Size mem routine.
+        */
+
+       /*
+        * 64mb of memory.
+        */
+
+       //mips_memory_upper = 0x84000000;
+
+
+#ifndef BOOTLOADER
+
+#if 0  /* You break'a the kernel I break'a ya face. -DaveM */
+
+       /* Eight meg of memory.         */
+       mips_memory_upper = 0x80800000;  /* XXX  this appears to be unused  - 
+                                           this assignment is not present in the normal
+                                           $cvstree/linux/arch/mips/cobalt/setup.c */
+#endif
+#else
+#include "../../../../include/diagdefs.h"
+       mips_memory_upper = (unsigned long) kBootloaderMipsMemoryUpper;
+#endif
+       LongVar = mips_memory_upper;
+       atag = bi_TagAdd(tag_memupper, ULONGSIZE, &LongVar);
+
+       /* Here is the machine type.
+       */
+       LongVar = MACH_COBALT_27;
+       atag = bi_TagAdd(tag_machtype, ULONGSIZE, &LongVar);
+
+       LongVar = 0x80000000;
+       atag = bi_TagAdd(tag_memlower, ULONGSIZE, &LongVar);
+
+       LongVar = CPU_R4300;
+       atag = bi_TagAdd(tag_cputype, ULONGSIZE, &LongVar);
+
+       LongVar = MACH_GROUP_COBALT;
+       atag = bi_TagAdd(tag_machgroup, ULONGSIZE, &LongVar);
+
+       LongVar = 0;
+       atag = bi_TagAdd(tag_scache_size, ULONGSIZE, &LongVar);
+
+       LongVar = 48;
+       atag = bi_TagAdd(tag_tlb_entries, ULONGSIZE, &LongVar);
+
+       LongVar = 0;
+       atag = bi_TagAdd(tag_drive_info, ULONGSIZE, &LongVar);
+
+       LongVar = 0xe0800000;
+       atag = bi_TagAdd(tag_vram_base, ULONGSIZE, &LongVar);
+
+       LongVar = 0;
+       atag = bi_TagAdd(tag_dummy, 0, &LongVar);
+}
+
+void AddTagsEndSymbol(void)
+{
+       short   X;
+       X = 1;
+}
+
+/*
+ * Oh shit, this is so crappy ...
+ */
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+int my_cacheflush(unsigned long start, unsigned long size, unsigned int what)
+{
+       flush_cache_range(current->mm, start, start + size);
+       return 0;
+}
+
+
+/*
+ * The ROM set the flag to 0x1 to turn off output.  This is interpreted
+ * as "valid", "no kernel output", and index '0' into the following
+ * tables.  We overload entry '0' to specify a sensible default rate.
+ */
+static int cons_baud_int[]  = { 9600, 0,  9600, 0, 0,  115200, 0, 0 };
+static int cons_baud_baud[] = { B9600, 0, B9600, 0, 0, B115200, 0, 0 };
+
+static union cobalt_cons_info
+cobalt_get_console_info(void)
+{
+       char board_id = 0;
+       static union cobalt_cons_info cons_info;
+       static int read_info = 0;
+       extern void add_init_env(char *);
+
+       if (read_info)
+               return cons_info;
+
+       VIA_PORT_WRITE(VIA_CMOS_ADDR, VIA_CMOS_CONSOLE_FLG);
+       cons_info.ccons_char = VIA_PORT_READ(VIA_CMOS_DATA);
+
+#if 0
+       printk("cobalt_get_console_info: read 0x%x from console flag\n",
+              cons_info.ccons_char);
+#endif
+
+       /*
+        * CMOS hasn't been initialized or baud rate isn't known.
+        * - read the board id and provide backwards compat.
+        */
+       if (cons_info.ccons_bits.valid != VIA_CMOS_CONS_VALID
+           || ! cons_baud_int[cons_info.ccons_bits.baud]
+           || ! cons_baud_baud[cons_info.ccons_bits.baud]) {
+               pcibios_read_config_byte(0, PCI_DEVSHFT(COBALT_PCICONF_VIA),
+                                        VIA_COBALT_BRD_ID_REG, &board_id);
+
+#if 0
+               printk("cobalt_get_console_info: read 0x%x from board config\n",
+                      board_id);
+#endif
+
+               switch (VIA_COBALT_BRD_REG_to_ID(board_id)) {
+               case COBALT_BRD_ID_QUBE1:
+                       cons_info.ccons_bits.baud = VIA_CMOS_CONS_115K;
+                       cons_info.ccons_bits.kout = 1;
+                       break;
+               case COBALT_BRD_ID_RAQ1:
+                       cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+                       cons_info.ccons_bits.kout = 1;
+                       break;
+               case COBALT_BRD_ID_QUBE2:
+                       cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+                       cons_info.ccons_bits.kout = 0;
+                       break;
+               case COBALT_BRD_ID_RAQ2:
+                       cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
+                       cons_info.ccons_bits.kout = 1;
+                       break;
+               }
+               cons_info.ccons_bits.valid = VIA_CMOS_CONS_VALID;
+       }
+
+       read_info = 1;
+
+#if defined(DEBUG_LOADER)
+       cons_info.ccons_bits.kout = 1;
+#endif
+
+       if (!cons_info.ccons_bits.kout) {
+               add_init_env("CONSOLE=/dev/null");
+       }
+
+#if 0
+       printk("cobalt_get_console_info: returning 0x%x\n",
+               cons_info.ccons_char);
+#endif
+
+       return cons_info;
+}
+
+int
+cobalt_cons_koutok(void)
+{
+       union cobalt_cons_info cons;
+
+       cons = cobalt_get_console_info();
+
+       return cons.ccons_bits.kout;
+}
+
+int
+cobalt_cons_baudbaud(void)
+{
+       union cobalt_cons_info cons;
+
+       cons = cobalt_get_console_info();
+
+       return cons_baud_baud[cons.ccons_bits.baud];
+}
+
+int
+cobalt_cons_baudint(void)
+{
+       union cobalt_cons_info cons;
+
+       cons = cobalt_get_console_info();
+
+       return cons_baud_int[cons.ccons_bits.baud];
+}
diff --git a/arch/mips/cobalt/via.c b/arch/mips/cobalt/via.c
new file mode 100644 (file)
index 0000000..7ab5e1e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Interrupt handling for the VIA ISA bridge.
+ *
+ * Everything the same ... just different ...
+ */
+#include <linux/kernel.h>
+#include <asm/cobalt.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+
+extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+
+extern unsigned char cache_21;
+extern unsigned char cache_A1;
+
+/*
+ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
+ * PCI devices.  Other onboard hardware needs specific routines.
+ */
+void mask_irq(unsigned int irq_nr)
+{
+       unsigned char mask;
+
+       mask = 1 << (irq_nr & 7);
+       if (irq_nr < 8) {
+               cache_21 |= mask;
+               outb(cache_21, 0x10000021);
+       } else {
+               cache_A1 |= mask;
+               outb(cache_A1, 0x100000a1);
+       }
+}
+
+void unmask_irq(unsigned int irq_nr)
+{
+       unsigned char mask;
+
+       mask = ~(1 << (irq_nr & 7));
+       if (irq_nr < 8) {
+               cache_21 &= mask;
+               outb(cache_21, 0x10000021);
+       } else {
+               cache_A1 &= mask;
+               outb(cache_A1, 0x100000a1);
+       }
+}
+
+asmlinkage void via_irq(struct pt_regs *regs)
+{
+       char mstat, sstat;
+  
+       /* Read Master Status */
+       VIA_PORT_WRITE(0x20, 0x0C);
+       mstat = VIA_PORT_READ(0x20);
+       if (mstat < 0) {
+               mstat &= 0x7f;
+               if (mstat != 2) {       
+                       do_IRQ(mstat, regs);
+                       VIA_PORT_WRITE(0x20, mstat | 0x20);
+               } else {
+                       sstat = VIA_PORT_READ(0xA0);
+
+                       /* Slave interrupt */
+                       VIA_PORT_WRITE(0xA0, 0x0C);
+                       sstat = VIA_PORT_READ(0xA0);
+   
+                       if (sstat < 0) {
+                               do_IRQ((sstat + 8) & 0x7f, regs);
+                               VIA_PORT_WRITE(0x20, 0x22);       
+                               VIA_PORT_WRITE(0xA0, (sstat & 0x7f) | 0x20);
+                       } else {
+                               printk("Spurious slave interrupt...\n");
+                       }
+               }
+       } else
+               printk("Spurious master interrupt...");
+}
+
+asmlinkage void galileo_irq(struct pt_regs *regs)
+{
+       unsigned long irq_src = *((unsigned long *) 0xb4000c18); 
+  
+       /* Check for timer irq ... */
+       if (irq_src & 0x00000100) {
+               *((volatile unsigned long *) 0xb4000c18) = 0;
+               do_IRQ(0, regs);
+       } else
+               printk("Spurious Galileo interrupt...\n");
+}
diff --git a/arch/mips/cobalt/z8530.h b/arch/mips/cobalt/z8530.h
new file mode 100644 (file)
index 0000000..6ed984d
--- /dev/null
@@ -0,0 +1,219 @@
+/* 8530 Serial Communications Controller Register definitions */
+#define        FLAG    0x7e
+
+/* Write Register 0 */
+#define        R0      0               /* Register selects */
+#define        R1      1
+#define        R2      2
+#define        R3      3
+#define        R4      4
+#define        R5      5
+#define        R6      6
+#define        R7      7
+#define        R8      8
+#define        R9      9
+#define        R10     10
+#define        R11     11
+#define        R12     12
+#define        R13     13
+#define        R14     14
+#define        R15     15
+
+#define        NULLCODE        0       /* Null Code */
+#define        POINT_HIGH      0x8     /* Select upper half of registers */
+#define        RES_EXT_INT     0x10    /* Reset Ext. Status Interrupts */
+#define        SEND_ABORT      0x18    /* HDLC Abort */
+#define        RES_RxINT_FC    0x20    /* Reset RxINT on First Character */
+#define        RES_Tx_P        0x28    /* Reset TxINT Pending */
+#define        ERR_RES         0x30    /* Error Reset */
+#define        RES_H_IUS       0x38    /* Reset highest IUS */
+
+#define        RES_Rx_CRC      0x40    /* Reset Rx CRC Checker */
+#define        RES_Tx_CRC      0x80    /* Reset Tx CRC Checker */
+#define        RES_EOM_L       0xC0    /* Reset EOM latch */
+
+/* Write Register 1 */
+
+#define        EXT_INT_ENAB    0x1     /* Ext Int Enable */
+#define        TxINT_ENAB      0x2     /* Tx Int Enable */
+#define        PAR_SPEC        0x4     /* Parity is special condition */
+
+#define        RxINT_DISAB     0       /* Rx Int Disable */
+#define        RxINT_FCERR     0x8     /* Rx Int on First Character Only or Error */
+#define        INT_ALL_Rx      0x10    /* Int on all Rx Characters or error */
+#define        INT_ERR_Rx      0x18    /* Int on error only */
+
+#define        WT_RDY_RT       0x20    /* Wait/Ready on R/T */
+#define        WT_FN_RDYFN     0x40    /* Wait/FN/Ready FN */
+#define        WT_RDY_ENAB     0x80    /* Wait/Ready Enable */
+
+/* Write Register #2 (Interrupt Vector) */
+
+/* Write Register 3 */
+
+#define        RxENABLE        0x1     /* Rx Enable */
+#define        SYNC_L_INH      0x2     /* Sync Character Load Inhibit */
+#define        ADD_SM          0x4     /* Address Search Mode (SDLC) */
+#define        RxCRC_ENAB      0x8     /* Rx CRC Enable */
+#define        ENT_HM          0x10    /* Enter Hunt Mode */
+#define        AUTO_ENAB       0x20    /* Auto Enables */
+#define        Rx5             0x0     /* Rx 5 Bits/Character */
+#define        Rx7             0x40    /* Rx 7 Bits/Character */
+#define        Rx6             0x80    /* Rx 6 Bits/Character */
+#define        Rx8             0xc0    /* Rx 8 Bits/Character */
+
+/* Write Register 4 */
+
+#define        PAR_ENA         0x1     /* Parity Enable */
+#define        PAR_EVEN        0x2     /* Parity Even/Odd* */
+
+#define        SYNC_ENAB       0       /* Sync Modes Enable */
+#define        SB1             0x4     /* 1 stop bit/char */
+#define        SB15            0x8     /* 1.5 stop bits/char */
+#define        SB2             0xc     /* 2 stop bits/char */
+
+#define        MONSYNC         0       /* 8 Bit Sync character */
+#define        BISYNC          0x10    /* 16 bit sync character */
+#define        SDLC            0x20    /* SDLC Mode (01111110 Sync Flag) */
+#define        EXTSYNC         0x30    /* External Sync Mode */
+
+#define        X1CLK           0x0     /* x1 clock mode */
+#define        X16CLK          0x40    /* x16 clock mode */
+#define        X32CLK          0x80    /* x32 clock mode */
+#define        X64CLK          0xC0    /* x64 clock mode */
+
+/* Write Register 5 */
+
+#define        TxCRC_ENAB      0x1     /* Tx CRC Enable */
+#define        RTS             0x2     /* RTS */
+#define        SDLC_CRC        0x4     /* SDLC/CRC-16 */
+#define        TxENAB          0x8     /* Tx Enable */
+#define        SND_BRK         0x10    /* Send Break */
+#define        Tx5             0x0     /* Tx 5 bits (or less)/character */
+#define        Tx7             0x20    /* Tx 7 bits/character */
+#define        Tx6             0x40    /* Tx 6 bits/character */
+#define        Tx8             0x60    /* Tx 8 bits/character */
+#define        DTR             0x80    /* DTR */
+
+/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
+
+/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
+
+/* Write Register 8 (transmit buffer) */
+
+/* Write Register 9 (Master interrupt control) */
+#define        VIS     1       /* Vector Includes Status */
+#define        NV      2       /* No Vector */
+#define        DLC     4       /* Disable Lower Chain */
+#define        MIE     8       /* Master Interrupt Enable */
+#define        STATHI  0x10    /* Status high */
+#define        NORESET 0       /* No reset on write to R9 */
+#define        CHRB    0x40    /* Reset channel B */
+#define        CHRA    0x80    /* Reset channel A */
+#define        FHWRES  0xc0    /* Force hardware reset */
+
+/* Write Register 10 (misc control bits) */
+#define        BIT6    1       /* 6 bit/8bit sync */
+#define        LOOPMODE 2      /* SDLC Loop mode */
+#define        ABUNDER 4       /* Abort/flag on SDLC xmit underrun */
+#define        MARKIDLE 8      /* Mark/flag on idle */
+#define        GAOP    0x10    /* Go active on poll */
+#define        NRZ     0       /* NRZ mode */
+#define        NRZI    0x20    /* NRZI mode */
+#define        FM1     0x40    /* FM1 (transition = 1) */
+#define        FM0     0x60    /* FM0 (transition = 0) */
+#define        CRCPS   0x80    /* CRC Preset I/O */
+
+/* Write Register 11 (Clock Mode control) */
+#define        TRxCXT  0       /* TRxC = Xtal output */
+#define        TRxCTC  1       /* TRxC = Transmit clock */
+#define        TRxCBR  2       /* TRxC = BR Generator Output */
+#define        TRxCDP  3       /* TRxC = DPLL output */
+#define        TRxCOI  4       /* TRxC O/I */
+#define        TCRTxCP 0       /* Transmit clock = RTxC pin */
+#define        TCTRxCP 8       /* Transmit clock = TRxC pin */
+#define        TCBR    0x10    /* Transmit clock = BR Generator output */
+#define        TCDPLL  0x18    /* Transmit clock = DPLL output */
+#define        RCRTxCP 0       /* Receive clock = RTxC pin */
+#define        RCTRxCP 0x20    /* Receive clock = TRxC pin */
+#define        RCBR    0x40    /* Receive clock = BR Generator output */
+#define        RCDPLL  0x60    /* Receive clock = DPLL output */
+#define        RTxCX   0x80    /* RTxC Xtal/No Xtal */
+
+/* Write Register 12 (lower byte of baud rate generator time constant) */
+
+/* Write Register 13 (upper byte of baud rate generator time constant) */
+
+/* Write Register 14 (Misc control bits) */
+#define        BRENABL 1       /* Baud rate generator enable */
+#define        BRSRC   2       /* Baud rate generator source */
+#define        DTRREQ  4       /* DTR/Request function */
+#define        AUTOECHO 8      /* Auto Echo */
+#define        LOOPBAK 0x10    /* Local loopback */
+#define        SEARCH  0x20    /* Enter search mode */
+#define        RMC     0x40    /* Reset missing clock */
+#define        DISDPLL 0x60    /* Disable DPLL */
+#define        SSBR    0x80    /* Set DPLL source = BR generator */
+#define        SSRTxC  0xa0    /* Set DPLL source = RTxC */
+#define        SFMM    0xc0    /* Set FM mode */
+#define        SNRZI   0xe0    /* Set NRZI mode */
+
+/* Write Register 15 (external/status interrupt control) */
+#define        ZCIE    2       /* Zero count IE */
+#define        DCDIE   8       /* DCD IE */
+#define        SYNCIE  0x10    /* Sync/hunt IE */
+#define        CTSIE   0x20    /* CTS IE */
+#define        TxUIE   0x40    /* Tx Underrun/EOM IE */
+#define        BRKIE   0x80    /* Break/Abort IE */
+
+
+/* Read Register 0 */
+#define        Rx_CH_AV        0x1     /* Rx Character Available */
+#define        ZCOUNT          0x2     /* Zero count */
+#define        Tx_BUF_EMP      0x4     /* Tx Buffer empty */
+#define        DCD             0x8     /* DCD */
+#define        SYNC_HUNT       0x10    /* Sync/hunt */
+#define        CTS             0x20    /* CTS */
+#define        TxEOM           0x40    /* Tx underrun */
+#define        BRK_ABRT        0x80    /* Break/Abort */
+
+/* Read Register 1 */
+#define        ALL_SNT         0x1     /* All sent */
+/* Residue Data for 8 Rx bits/char programmed */
+#define        RES3            0x8     /* 0/3 */
+#define        RES4            0x4     /* 0/4 */
+#define        RES5            0xc     /* 0/5 */
+#define        RES6            0x2     /* 0/6 */
+#define        RES7            0xa     /* 0/7 */
+#define        RES8            0x6     /* 0/8 */
+#define        RES18           0xe     /* 1/8 */
+#define        RES28           0x0     /* 2/8 */
+/* Special Rx Condition Interrupts */
+#define        PAR_ERR         0x10    /* Parity error */
+#define        Rx_OVR          0x20    /* Rx Overrun Error */
+#define        CRC_ERR         0x40    /* CRC/Framing Error */
+#define        END_FR          0x80    /* End of Frame (SDLC) */
+
+/* Read Register 2 (channel b only) - Interrupt vector */
+
+/* Read Register 3 (interrupt pending register) ch a only */
+#define        CHBEXT  0x1             /* Channel B Ext/Stat IP */
+#define        CHBTxIP 0x2             /* Channel B Tx IP */
+#define        CHBRxIP 0x4             /* Channel B Rx IP */
+#define        CHAEXT  0x8             /* Channel A Ext/Stat IP */
+#define        CHATxIP 0x10            /* Channel A Tx IP */
+#define        CHARxIP 0x20            /* Channel A Rx IP */
+
+/* Read Register 8 (receive data register) */
+
+/* Read Register 10  (misc status bits) */
+#define        ONLOOP  2               /* On loop */
+#define        LOOPSEND 0x10           /* Loop sending */
+#define        CLK2MIS 0x40            /* Two clocks missing */
+#define        CLK1MIS 0x80            /* One clock missing */
+
+/* Read Register 12 (lower byte of baud rate generator constant) */
+
+/* Read Register 13 (upper byte of baud rate generator constant) */
+
+/* Read Register 15 (value of WR 15) */
index d5c3905..4cf16f8 100644 (file)
@@ -1,4+1,4 @@
-# $Id: config.in,v 1.46 2000/03/26 22:59:01 ralf Exp $
+#
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -11,10+11,14 @@ endmenu
 
 mainmenu_option next_comment
 comment 'Machine selection'
-bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
    bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032
    bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS
+   bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER
+   if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
+      bool '  Support for 2800' CONFIG_COBALT_28
+   fi
    bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION
    bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074
 fi
@@ -27,10+31,11 @@ bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
 # Select some configuration options automatically for certain systems.
 #
 unset CONFIG_ARC32
-unset CONFIG_PCI
 unset CONFIG_ISA
+unset CONFIG_PCI
 unset CONFIG_MIPS_JAZZ
 unset CONFIG_VIDEO_G364
+unset CONFIG_PC_KEYB
 
 define_bool CONFIG_SBUS n
 
@@ -40,25+45,37 @@ fi
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
    define_bool CONFIG_ARC32 y
-   define_bool CONFIG_HAVE_IO_PORTS y
+   define_bool CONFIG_ISA y
    define_bool CONFIG_FB y
    define_bool CONFIG_FB_G364 y        
    define_bool CONFIG_MIPS_JAZZ y
+   define_bool CONFIG_PC_KEYB y
 fi
 if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
    define_bool CONFIG_ARC32 y
-   define_bool CONFIG_HAVE_IO_PORTS y
+   define_bool CONFIG_ISA y
    define_bool CONFIG_MIPS_JAZZ y
+   define_bool CONFIG_PC_KEYB y
+fi
+if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
+   define_bool CONFIG_ISA n
+   define_bool CONFIG_COBALT_27 y
+   define_bool CONFIG_COBALT_LCD y
+   define_bool CONFIG_COBALT_SERIAL y
+   define_bool CONFIG_PCI y
 fi
 if [ "$CONFIG_SGI_IP22" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_SGI y
 fi
 if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
    define_bool CONFIG_ARC32 y
-   define_bool CONFIG_HAVE_IO_PORTS y
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_ISA y
+   define_bool CONFIG_PC_KEYB y
 fi
 if [ "$CONFIG_DDB5074" = "y" ]; then
-   define_bool CONFIG_HAVE_IO_PORTS y
    define_bool CONFIG_ISA y
    define_bool CONFIG_PCI y
 fi
@@ -85,7+102,7 @@ mainmenu_option next_comment
                 R8000 CONFIG_CPU_R8000 \
                 R10000 CONFIG_CPU_R10000" R4x00
 
-       bool 'Advanced CPU Config' CONFIG_CPU_ADVANCED
+       bool 'Override CPU Options' CONFIG_CPU_ADVANCED
 
        if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then
                bool '  ll/sc Instructions available' CONFIG_CPU_HAS_LLSC
@@ -149,6+166,9 @@ comment 'General setup'
 
        if [ "$CONFIG_DECSTATION" = "y" ]; then
             bool 'TURBOchannel support' CONFIG_TC
+#           if [ "$CONFIG_TC" = "y" ]; then
+#              bool ' Access.Bus support' CONFIG_ACCESSBUS
+#           fi
        fi
 endmenu
 
@@ -170,13+190,13 @@ if [ "$CONFIG_NET" = "y" ]; then
    source net/Config.in
 fi
 
-if [ "$CONFIG_DECSTATION" != "n" -a \
-     "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+     "$CONFIG_SGI_IP22" != "y" ]; then
     source drivers/telephony/Config.in
 fi
 
-if [ "$CONFIG_SGI_IP22" != "n" -a \
-     "$CONFIG_DECSTATION" != "n" ]; then
+if [ "$CONFIG_SGI_IP22" != "y" -a \
+     "$CONFIG_DECSTATION" != "y" ]; then
 
     mainmenu_option next_comment
     comment 'ATA/IDE/MFM/RLL support'
@@ -202,8+222,8 @@ if [ "$CONFIG_SCSI" != "n" ]; then
 fi
 endmenu
 
-if [ "$CONFIG_DECSTATION" != "n" -a \
-     "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+     "$CONFIG_SGI_IP22" != "y" ]; then
     source drivers/i2o/Config.in
 fi
 
@@ -270,8+290,8 @@ if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then
    endmenu
 fi
 
-if [ "$CONFIG_DECSTATION" != "n" -a \
-     "$CONFIG_SGI_IP22" != "n" ]; then
+if [ "$CONFIG_DECSTATION" != "y" -a \
+     "$CONFIG_SGI_IP22" != "y" ]; then
    source drivers/char/Config.in
 fi
 
@@ -295,8+315,9 @@ if [ "$CONFIG_DECSTATION" = "y" ]; then
    if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
       int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
    fi
-   bool 'Keyboard Support' CONFIG_KEYBOARD
-   bool 'Mouse Support' CONFIG_MOUSE
+#   if [ "$CONFIG_ACCESSBUS" = "y" ]; then
+#      bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
+#   fi
    bool 'Enhanced Real Time Clock Support' CONFIG_RTC
    endmenu
 fi
index 0a76788..1201b0f 100644 (file)
@@ -320,6+320,13 @@ int pcibios_enable_resources(struct pci_dev *dev)
        int idx;
        struct resource *r;
 
+       /*
+        *  Don't touch the Nile 4
+        */
+       if (dev->vendor == PCI_VENDOR_ID_NEC &&
+           dev->device == PCI_DEVICE_ID_NEC_NILE4)
+           return 0;
+
        pci_read_config_word(dev, PCI_COMMAND, &cmd);
        old_cmd = cmd;
        for(idx=0; idx<6; idx++) {
index d2f48c2..1512345 100644 (file)
 #include <linux/mc146818rtc.h>
 #include <linux/pc_keyb.h>
 #include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/addrspace.h>
 #include <asm/bcache.h>
@@ -38,6+39,7 @@ extern void breakpoint(void);
 extern void console_setup(char *);
 #endif
 
+extern struct ide_ops std_ide_ops;
 extern struct rtc_ops ddb_rtc_ops;
 
 static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
@@ -107,6+109,9 @@ void __init ddb_setup(void)
     _machine_halt = ddb_machine_halt;
     _machine_power_off = ddb_machine_power_off;
 
+#ifdef CONFIG_BLK_DEV_IDE
+    ide_ops = &std_ide_ops;
+#endif
     rtc_ops = &ddb_rtc_ops;
 
     /* Reboot on panic */
index a093c45..1025104 100644 (file)
@@ -155,6+155,6 @@ void prom_free_prom_memory (void)
                addr += PAGE_SIZE;
        }
 
-       printk("Freeing unused PROM memory: %dk freed\n",
+       printk("Freeing unused PROM memory: %ldk freed\n",
               (end - PAGE_SIZE) >> 10);
 }
index d445124..18c3166 100644 (file)
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_ACER_PICA_61 is not set
 # CONFIG_ALGOR_P4032 is not set
 # CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
@@ -21,6+22,8 @@ CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
+CONFIG_PC_KEYB=y
+CONFIG_SGI=y
 # CONFIG_ISA is not set
 # CONFIG_PCI is not set
 
@@ -65,6+68,11 @@ CONFIG_KMOD=y
 # CONFIG_PCMCIA is not set
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -72,17+80,14 @@ CONFIG_KMOD=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -121,9+126,9 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -232,6+237,7 @@ CONFIG_AUTOFS4_FS=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
similarity index 52%
copy from arch/mips64/defconfig-ip27
copy to arch/mips/defconfig-cobalt
index cef645c..e2700ed 100644 (file)
 #
 # Code maturity level options
 #
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
 
 #
 # Machine selection
 #
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+CONFIG_COBALT_MICRO_SERVER=y
+CONFIG_COBALT_28=y
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
-CONFIG_SGI_IP27=y
-# CONFIG_SGI_SN0_N_MODE is not set
-# CONFIG_DISCONTIGMEM is not set
-# CONFIG_SMP is not set
-CONFIG_BOOT_ELF64=y
-CONFIG_ARC64=y
-CONFIG_COHERENT_IO=y
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SBUS is not set
+# CONFIG_ISA is not set
+CONFIG_COBALT_27=y
+CONFIG_COBALT_LCD=y
+CONFIG_COBALT_SERIAL=y
 CONFIG_PCI=y
-CONFIG_QL_ISP_A64=y
 # CONFIG_ISA is not set
-# CONFIG_SBUS is not set
 
 #
 # CPU selection
 #
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 # CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_NEVADA is not set
+CONFIG_CPU_NEVADA=y
 # CONFIG_CPU_R8000 is not set
-CONFIG_CPU_R10000=y
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
 
 #
 # General setup
 #
-# CONFIG_MIPS_INSANE_LARGE is not set
-# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=m
 CONFIG_NET=y
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-CONFIG_MIPS32_COMPAT=y
-CONFIG_BINFMT_ELF32=y
-# CONFIG_BINFMT_MISC is not set
 
 #
-# Loadable module support
+# Parallel port support
 #
+# CONFIG_PARPORT is not set
 CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
 CONFIG_KMOD=y
-CONFIG_PCI_NAMES=y
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
 
 #
 # Block devices
@@ -66,17+81,18 @@ CONFIG_PCI_NAMES=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
 # CONFIG_MD_RAID0 is not set
-# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_MD_BOOT is not set
+# CONFIG_AUTODETECT_RAID is not set
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
@@ -86,30+102,49 @@ CONFIG_PCI_NAMES=y
 # CONFIG_NETLINK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
-CONFIG_UNIX=y
+# CONFIG_UNIX is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
-# CONFIG_SYN_COOKIES is not set
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_PIMSM_V1 is not set
+# CONFIG_IP_PIMSM_V2 is not set
+CONFIG_IP_ALIAS=y
+CONFIG_SYN_COOKIES=y
 
 #
 # (it is safe to leave these untouched)
 #
 CONFIG_SKB_LARGE=y
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
+CONFIG_IPX=m
+# CONFIG_IPX_INTERN is not set
+# CONFIG_SPX is not set
+CONFIG_ATALK=m
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
 
 #
 # Telephony Support
@@ -134,16+169,18 @@ CONFIG_SCSI=y
 #
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=m
 
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_DEBUG_QUEUES is not set
-# CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_CONSTANTS is not set
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
 #
@@ -155,7+192,11 @@ CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
+CONFIG_SCSI_AIC7XXX=y
+# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=8
+# CONFIG_AIC7XXX_PROC_STATS is not set
+CONFIG_AIC7XXX_RESET_DELAY=5
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -171,25+212,30 @@ CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
-# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_NCR53C8XX=y
 # CONFIG_SCSI_SYM53C8XX is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
+CONFIG_SCSI_NCR53C8XX_SYNC=5
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+CONFIG_SCSI_NCR53C8XX_IOMAPPED=y
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-CONFIG_SCSI_QLOGIC_ISP=y
+# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # I2O device support
@@ -210,7+256,12 @@ CONFIG_NETDEVICES=y
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_APPLETALK is not set
+CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_NET_SB1000 is not set
@@ -219,11+270,11 @@ CONFIG_NETDEVICES=y
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-CONFIG_SGI_IOC3_ETH=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_PCI is not set
@@ -232,12+283,22 @@ CONFIG_SGI_IOC3_ETH=y
 #
 # Ethernet (1000 Mbit)
 #
+# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_HIPPI is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPPOE is not set
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Wireless LAN (non-hamradio)
@@ -249,6+310,8 @@ CONFIG_SGI_IOC3_ETH=y
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
 
 #
 # Wan interfaces
@@ -256,19+319,81 @@ CONFIG_SGI_IOC3_ETH=y
 # CONFIG_WAN is not set
 
 #
-# Amateur Radio support
+# ISDN subsystem
 #
-# CONFIG_HAMRADIO is not set
+CONFIG_ISDN=m
+CONFIG_ISDN_PPP=y
+CONFIG_ISDN_PPP_VJ=y
+CONFIG_ISDN_MPP=y
+CONFIG_ISDN_AUDIO=y
+# CONFIG_ISDN_TTY_FAX is not set
 
 #
-# IrDA (infrared) support
+# ISDN feature submodules
 #
-# CONFIG_IRDA is not set
+# CONFIG_ISDN_DRV_LOOP is not set
+# CONFIG_ISDN_DIVERSION is not set
 
 #
-# ISDN subsystem
+# low-level hardware drivers
+#
+
+#
+# Passive ISDN cards
+#
+CONFIG_ISDN_DRV_HISAX=m
+
+#
+#   D-channel protocol features
+#
+CONFIG_HISAX_EURO=y
+CONFIG_DE_AOC=y
+# CONFIG_HISAX_NO_SENDCOMPLETE is not set
+# CONFIG_HISAX_NO_LLC is not set
+# CONFIG_HISAX_NO_KEYPAD is not set
+CONFIG_HISAX_1TR6=y
+
+#
+#   HiSax supported cards
 #
-# CONFIG_ISDN is not set
+# CONFIG_HISAX_16_0 is not set
+# CONFIG_HISAX_16_3 is not set
+# CONFIG_HISAX_TELESPCI is not set
+# CONFIG_HISAX_S0BOX is not set
+# CONFIG_HISAX_AVM_A1 is not set
+# CONFIG_HISAX_FRITZPCI is not set
+# CONFIG_HISAX_AVM_A1_PCMCIA is not set
+CONFIG_HISAX_ELSA=y
+# CONFIG_HISAX_IX1MICROR2 is not set
+# CONFIG_HISAX_DIEHLDIVA is not set
+# CONFIG_HISAX_ASUSCOM is not set
+# CONFIG_HISAX_TELEINT is not set
+# CONFIG_HISAX_HFCS is not set
+# CONFIG_HISAX_SEDLBAUER is not set
+# CONFIG_HISAX_SPORTSTER is not set
+# CONFIG_HISAX_MIC is not set
+# CONFIG_HISAX_NETJET is not set
+# CONFIG_HISAX_NICCY is not set
+# CONFIG_HISAX_ISURF is not set
+# CONFIG_HISAX_HSTSAPHIR is not set
+# CONFIG_HISAX_BKM_A4T is not set
+# CONFIG_HISAX_SCT_QUADRO is not set
+# CONFIG_HISAX_GAZEL is not set
+# CONFIG_HISAX_HFC_PCI is not set
+# CONFIG_HISAX_W6692 is not set
+# CONFIG_HISAX_HFC_SX is not set
+
+#
+# Active ISDN cards
+#
+# CONFIG_ISDN_DRV_ICN is not set
+# CONFIG_ISDN_DRV_PCBIT is not set
+# CONFIG_ISDN_DRV_SC is not set
+# CONFIG_ISDN_DRV_ACT2000 is not set
+# CONFIG_ISDN_DRV_EICON is not set
+# CONFIG_ISDN_CAPI is not set
+# CONFIG_ISDN_CAPI_MIDDLEWARE is not set
+# CONFIG_HYSDN is not set
 
 #
 # Old CD-ROM drivers (not SCSI, not IDE)
@@ -279,13+404,10 @@ CONFIG_SGI_IOC3_ETH=y
 # Character devices
 #
 # CONFIG_VT is not set
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
 
 #
 # I2C support
@@ -308,8+430,9 @@ CONFIG_SERIAL_CONSOLE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
+CONFIG_RTC=y
 
 #
 # Video For Linux
@@ -325,11+448,12 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
 
 #
 # File systems
 #
-# CONFIG_QUOTA is not set
+CONFIG_QUOTA=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
@@ -337,14+461,15 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
+CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
-# CONFIG_ISO9660_FS is not set
+CONFIG_ISO9660_FS=m
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
@@ -372,12+497,12 @@ CONFIG_EXT2_FS=y
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
 # CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
-# CONFIG_SMB_FS is not set
+CONFIG_SMB_FS=m
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
 # CONFIG_NCPFS_IOCTL_LOCKING is not set
@@ -393,18+518,41 @@ CONFIG_LOCKD=y
 #
 # Partition Types
 #
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
-CONFIG_SGI_PARTITION=y
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_NLS is not set
-CONFIG_KCORE_ELF=y
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_ISO8859_9=m
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_KOI8_R=m
 
 #
 # Sound
@@ -419,7+567,6 @@ CONFIG_KCORE_ELF=y
 #
 # Kernel hacking
 #
-CONFIG_CROSSCOMPILE=y
+# CONFIG_CROSSCOMPILE is not set
 # CONFIG_MIPS_FPE_MODULE is not set
-# CONFIG_REMOTE_DEBUG is not set
 # CONFIG_MAGIC_SYSRQ is not set
index add67fe..c0e7558 100644 (file)
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_ACER_PICA_61 is not set
 # CONFIG_ALGOR_P4032 is not set
 # CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
 CONFIG_DECSTATION=y
 # CONFIG_DDB5074 is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
@@ -63,6+64,11 @@ CONFIG_TC=y
 # CONFIG_PCMCIA is not set
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -70,17+76,14 @@ CONFIG_TC=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -119,9+122,9 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -212,8+215,6 @@ CONFIG_SERIAL=y
 CONFIG_ZS=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_UNIX98_PTYS is not set
-# CONFIG_KEYBOARD is not set
-# CONFIG_MOUSE is not set
 # CONFIG_RTC is not set
 
 #
@@ -232,6+233,7 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
index d445124..18c3166 100644 (file)
@@ -13,6+13,7 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_ACER_PICA_61 is not set
 # CONFIG_ALGOR_P4032 is not set
 # CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
 # CONFIG_DECSTATION is not set
 # CONFIG_DDB5074 is not set
 # CONFIG_MIPS_MAGNUM_4000 is not set
@@ -21,6+22,8 @@ CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
 # CONFIG_SBUS is not set
 CONFIG_ARC32=y
+CONFIG_PC_KEYB=y
+CONFIG_SGI=y
 # CONFIG_ISA is not set
 # CONFIG_PCI is not set
 
@@ -65,6+68,11 @@ CONFIG_KMOD=y
 # CONFIG_PCMCIA is not set
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -72,17+80,14 @@ CONFIG_KMOD=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -121,9+126,9 @@ CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
@@ -232,6+237,7 @@ CONFIG_AUTOFS4_FS=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
similarity index 67%
copy from arch/mips64/defconfig-ip22
copy to arch/mips/defconfig-rm200
index 85e7ace..fba87cd 100644 (file)
 #
 # Code maturity level options
 #
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
 
 #
 # Machine selection
 #
-CONFIG_SGI_IP22=y
-# CONFIG_SGI_IP27 is not set
-CONFIG_BOOT_ELF32=y
-CONFIG_ARC32=y
-CONFIG_BOARD_SCACHE=y
-CONFIG_ARC_MEMORY=y
-# CONFIG_ISA is not set
-# CONFIG_PCI is not set
+# CONFIG_ACER_PICA_61 is not set
+# CONFIG_ALGOR_P4032 is not set
+# CONFIG_BAGET_MIPS is not set
+# CONFIG_COBALT_MICRO_SERVER is not set
+# CONFIG_DECSTATION is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_MIPS_MAGNUM_4000 is not set
+# CONFIG_OLIVETTI_M700 is not set
+# CONFIG_SGI_IP22 is not set
+CONFIG_SNI_RM200_PCI=y
 # CONFIG_SBUS is not set
+CONFIG_ARC32=y
+CONFIG_PCI=y
+CONFIG_ISA=y
+CONFIG_PC_KEYB=y
 
 #
 # CPU selection
 #
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
 CONFIG_CPU_R5000=y
 # CONFIG_CPU_NEVADA is not set
 # CONFIG_CPU_R8000 is not set
 # CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_LLSC=y
+# CONFIG_CPU_HAS_WB is not set
 
 #
 # General setup
 #
-# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_KCORE_ELF=y
+CONFIG_ELF_KERNEL=y
+# CONFIG_BINFMT_AOUT is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
 CONFIG_NET=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-CONFIG_SYSVIPC=y
+# CONFIG_PCI_NAMES is not set
+# CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_BINFMT_ELF=y
-# CONFIG_MIPS32_COMPAT is not set
-# CONFIG_BINFMT_MISC is not set
 
 #
-# Loadable module support
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Plug and Play configuration
 #
-# CONFIG_MODULES is not set
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
 
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
+CONFIG_BLK_DEV_FD=y
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
@@ -81,9+107,7 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -93,7+117,10 @@ CONFIG_IP_PNP_BOOTP=y
 #
 # (it is safe to leave these untouched)
 #
-CONFIG_SKB_LARGE=y
+# CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
@@ -101,6+128,19 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
 
 #
 # Telephony Support
@@ -124,6+164,7 @@ CONFIG_SKB_LARGE=y
 # I2O device support
 #
 # CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
 # CONFIG_I2O_BLOCK is not set
 # CONFIG_I2O_LAN is not set
 # CONFIG_I2O_SCSI is not set
@@ -132,58+173,7 @@ CONFIG_SKB_LARGE=y
 #
 # Network device support
 #
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-CONFIG_SGISEEQ=y
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# CONFIG_NETDEVICES is not set
 
 #
 # ISDN subsystem
@@ -204,8+194,6 @@ CONFIG_VT_CONSOLE=y
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
 
 #
 # I2C support
@@ -228,6+216,7 @@ CONFIG_VT_CONSOLE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
@@ -245,6+234,7 @@ CONFIG_VT_CONSOLE=y
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
 
 #
 # File systems
@@ -262,6+252,7 @@ CONFIG_VT_CONSOLE=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
@@ -290,13+281,13 @@ CONFIG_EXT2_FS=y
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
-CONFIG_NFS_FS=y
+# CONFIG_NFS_FS is not set
 # CONFIG_NFS_V3 is not set
-CONFIG_ROOT_NFS=y
+# CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -313,27+304,36 @@ CONFIG_LOCKD=y
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
 # Console drivers
 #
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_FONT_8x16=y
-CONFIG_KCORE_ELF=y
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
 
 #
-# Sound
+# Frame-buffer support
 #
-# CONFIG_SOUND is not set
+# CONFIG_FB is not set
 
 #
-# SGI devices
+# Sound
 #
-# CONFIG_SGI_SERIAL is not set
-CONFIG_SGI_DS1286=y
+# CONFIG_SOUND is not set
 
 #
 # USB support
@@ -344,5+344,5 @@ CONFIG_SGI_DS1286=y
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
-# CONFIG_REMOTE_DEBUG is not set
+# CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_MAGIC_SYSRQ is not set
index 9ef5ecb..e213c0d 100644 (file)
@@ -1,4+1,3 @@
-# $Id: Makefile,v 1.14 1999/10/09 00:00:58 ralf Exp $
 #
 # Makefile for the Linux/MIPS kernel.
 #
@@ -36,10+35,10 @@ endif
 #
 # SGIs have very different interrupt/timer hardware.
 #
-ifndef CONFIG_SGI_IP22
-  ifndef CONFIG_DECSTATION
-    ifndef CONFIG_BAGET_MIPS
-      O_OBJS += time.o
+ifndef CONFIG_DECSTATION
+  ifndef CONFIG_BAGET_MIPS
+    O_OBJS += time.o
+    ifndef CONFIG_SGI_IP22
       OX_OBJS += irq.o
     endif
   endif
index 6670347..2d82d8c 100644 (file)
@@ -4,9+4,7 @@
  * in the kernel space a lot easier.  So far this handler in the released
  * kernel source is just a dummy.
  *
- * Copyright (C) 1997 Ralf Baechle
- *
- * $Id: fpe.c,v 1.3 1998/04/05 11:23:50 ralf Exp $
+ * Copyright (C) 1997, 2000 Ralf Baechle
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -24,7+22,6 @@ MODULE_SUPPORTED_DEVICE("MIPS FPU");
 
 static void do_fpe(struct pt_regs *regs, unsigned int fcr31)
 {
-       lock_kernel();
 #ifdef CONF_DEBUG_EXCEPTIONS
        show_regs(regs);
 #endif
@@ -34,7+31,6 @@ static void do_fpe(struct pt_regs *regs, unsigned int fcr31)
                goto out;
        force_sig(SIGFPE, current);
 out:
-       unlock_kernel();
 }
 
 /*
index df612cb..ea8610d 100644 (file)
        END(except_vec0_r4600)
 
        /* TLB refill, EXL == 0, R52x0 "Nevada" version */
+        /*
+         * This version has a bug workaround for the Nevada.  It seems
+         * as if under certain circumstances the move from cp0_context
+         * might produce a bogus result when the mfc0 instruction and
+         * it's consumer are in a different cacheline or a load instruction,
+         * probably any memory reference, is between them.  This is
+         * potencially slower than the R4000 version, so we use this
+         * special version.
+         */
        .set    noreorder
        .set    noat
        LEAF(except_vec0_nevada)
index 1b9774a..ee22aec 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: irixelf.c,v 1.28 2000/03/23 02:25:42 ralf Exp $
- *
+/*
  * irixelf.c: Code to load IRIX ELF executables which conform to
  *            the MIPS ABI.
  *
@@ -467,7+466,6 @@ static inline int look_for_irix_interpreter(char **name,
        return 0;
 
 dput_and_out:
-       allow_write_access(file);
        fput(file);
 out:
        kfree(*name);
@@ -771,7+769,7 @@ static int load_irix_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 #endif
 
        start_thread(regs, elf_entry, bprm->p);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        return 0;
 out:
@@ -1284,7+1282,7 @@ static int __init init_irix_binfmt(void)
        return register_binfmt(&irix_format);
 }
 
-static void __exit cleanup_module(void)
+static void __exit exit_irix_binfmt(void)
 {
        /* Remove the IRIX ELF loaders. */
        unregister_binfmt(&irix_format);
index 10ca5b1..a30ae52 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $
+/*
  * irixioctl.c: A fucking mess...
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -48,7+48,7 @@ static struct tty_struct *get_tty(int fd)
 
 static struct tty_struct *get_real_tty(struct tty_struct *tp)
 {
-       if(tp->driver.type == TTY_DRIVER_TYPE_PTY &&
+       if (tp->driver.type == TTY_DRIVER_TYPE_PTY &&
           tp->driver.subtype == PTY_TYPE_MASTER)
                return tp->link;
        else
@@ -61,7+61,6 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
        mm_segment_t old_fs;
        int error = 0;
 
-       lock_kernel();
 #ifdef DEBUG_IOCTLS
        printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
 #endif
@@ -87,7+86,7 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
                old_fs = get_fs(); set_fs(get_ds());
                error = sys_ioctl(fd, TCGETS, (unsigned long) &kt);
                set_fs(old_fs);
-               if(error)
+               if (error)
                        break;
                __put_user(kt.c_iflag, &it->c_iflag);
                __put_user(kt.c_oflag, &it->c_oflag);
@@ -106,7+105,7 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 #ifdef DEBUG_IOCTLS
                printk("TCSETS, %08lx) ", arg);
 #endif
-               if(!access_ok(VERIFY_READ, it, sizeof(*it))) {
+               if (!access_ok(VERIFY_READ, it, sizeof(*it))) {
                        error = -EFAULT;
                        break;
                }
@@ -259,6+258,5 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
 #ifdef DEBUG_IOCTLS
        printk("error=%d\n", error);
 #endif
-       unlock_kernel();
        return error;
 }
index 1bcafdf..7254ee9 100644 (file)
@@ -2,10+2,9 @@
  * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatable or what?!?!
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- * $Id: irixsig.c,v 1.13 1999/10/09 00:00:58 ralf Exp $
+ * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 2000 Silicon Graphics, Inc.
  */
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 
 asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
                          int options, unsigned long *ru);
+extern asmlinkage void syscall_trace(void);
 
 #undef DEBUG_SIG
 
@@ -131,10+131,8 @@ static void inline
 setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
                int signr, sigset_t *oldmask, siginfo_t *info)
 {
-       lock_kernel();
        printk("Aiee: setup_tr_frame wants to be written");
        do_exit(SIGSEGV);
-       unlock_kernel();
 }
 
 static inline void handle_signal(unsigned long sig, struct k_sigaction *ka,
@@ -193,7+191,7 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
@@ -266,8+264,8 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
                                /* FALLTHRU */
 
                        default:
-                               lock_kernel();
                                sigaddset(&current->signal, signr);
+                               recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
                                do_exit(exit_code);
                                /* NOTREACHED */
@@ -354,6+352,8 @@ irix_sigreturn(struct pt_regs *regs)
        /*
         * Don't let your children do this ...
         */
+       if (current->ptrace & PT_TRACESYS)
+               syscall_trace();
        __asm__ __volatile__(
                "move\t$29,%0\n\t"
                "j\tret_from_sys_call"
@@ -429,23+429,24 @@ irix_sigaction(int sig, const struct sigaction *act,
 
 asmlinkage int irix_sigpending(irix_sigset_t *set)
 {
-       lock_kernel();
+       int err;
+
        if (verify_area(VERIFY_WRITE, set, sizeof(*set)) < 0)
                return -EFAULT;
 
        /* fill in "set" with signals pending but blocked. */
        spin_lock_irq(&current->sigmask_lock);
-       __put_user(current->blocked.sig[0] & current->signal.sig[0],
-                  &set->sig[0]);
-       __put_user(current->blocked.sig[1] & current->signal.sig[1],
-                  &set->sig[1]);
-       __put_user(current->blocked.sig[2] & current->signal.sig[2],
-                  &set->sig[2]);
-       __put_user(current->blocked.sig[3] & current->signal.sig[3],
-                  &set->sig[3]);
+       err = __put_user(current->blocked.sig[0] & current->signal.sig[0],
+                        &set->sig[0]);
+       err |= __put_user(current->blocked.sig[1] & current->signal.sig[1],
+                        &set->sig[1]);
+       err |= __put_user(current->blocked.sig[2] & current->signal.sig[2],
+                        &set->sig[2]);
+       err |= __put_user(current->blocked.sig[3] & current->signal.sig[3],
+                        &set->sig[3]);
        spin_unlock_irq(&current->sigmask_lock);
 
-       return 0;
+       return err;
 }
 
 asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
@@ -453,10+454,9 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
        sigset_t oldbits, newbits;
        int error;
 
-
-       if(new) {
+       if (new) {
                error = verify_area(VERIFY_READ, new, sizeof(*new));
-               if(error)
+               if (error)
                        return error;
                __copy_from_user(&newbits, new, sizeof(unsigned long)*4);
                sigdelsetmask(&newbits, ~_BLOCKABLE);
@@ -565,7+565,6 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
        sigset_t kset;
        int i, sig, error, timeo = 0;
 
-       lock_kernel();
 #ifdef DEBUG_SIG
        printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
               current->comm, current->pid, set, info, tp);
@@ -636,7+635,6 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
        error = -EINTR;
 
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -662,44+660,45 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
        DECLARE_WAITQUEUE(wait, current);
        struct task_struct *p;
 
-       lock_kernel();
-       if(!info) {
+       if (!info) {
                retval = -EINVAL;
                goto out;
        }
        retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
        if(retval)
                goto out;
-       if(ru) {
+       if (ru) {
                retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
                if(retval)
                        goto out;
        }
-       if(options & ~(W_MASK)) {
+       if (options & ~(W_MASK)) {
                retval = -EINVAL;
                goto out;
        }
-       if(type != P_PID && type != P_PGID && type != P_ALL) {
+       if (type != P_PID && type != P_PGID && type != P_ALL) {
                retval = -EINVAL;
                goto out;
        }
        add_wait_queue(&current->wait_chldexit, &wait);
 repeat:
        flag = 0;
-       for(p = current->p_cptr; p; p = p->p_osptr) {
-               if((type == P_PID) && p->pid != pid)
+       current->state = TASK_INTERRUPTIBLE;
+       read_lock(&tasklist_lock);
+       for (p = current->p_cptr; p; p = p->p_osptr) {
+               if ((type == P_PID) && p->pid != pid)
                        continue;
-               if((type == P_PGID) && p->pgrp != pid)
+               if ((type == P_PGID) && p->pgrp != pid)
                        continue;
-               if((p->exit_signal != SIGCHLD))
+               if ((p->exit_signal != SIGCHLD))
                        continue;
                flag = 1;
-               switch(p->state) {
+               switch (p->state) {
                        case TASK_STOPPED:
                                if (!p->exit_code)
                                        continue;
                                if (!(options & (W_TRAPPED|W_STOPPED)) &&
-                                   !(p->flags & PF_PTRACED))
+                                   !(p->ptrace & PT_PTRACED))
                                        continue;
                                if (ru != NULL)
                                        getrusage(p, RUSAGE_BOTH, ru);
@@ -740,12+739,13 @@ repeat:
                                continue;
                }
        }
-       if(flag) {
+       read_unlock(&tasklist_lock);
+       if (flag) {
                retval = 0;
-               if(options & W_NOHANG)
+               if (options & W_NOHANG)
                        goto end_waitsys;
                retval = -ERESTARTSYS;
-               if(signal_pending(current))
+               if (signal_pending(current))
                        goto end_waitsys;
                current->state = TASK_INTERRUPTIBLE;
                schedule();
@@ -753,10+753,10 @@ repeat:
        }
        retval = -ECHILD;
 end_waitsys:
+       current->state = TASK_RUNNING;
        remove_wait_queue(&current->wait_chldexit, &wait);
 
 out:
-       unlock_kernel();
        return retval;
 }
 
@@ -779,8+779,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
        struct irix5_context *ctx;
        unsigned long flags;
 
-       lock_kernel();
-       if(regs->regs[2] == 1000)
+       if (regs->regs[2] == 1000)
                base = 1;
        ctx = (struct irix5_context *) regs->regs[base + 4];
 
@@ -803,7+802,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
 
        __put_user(0, &ctx->weird_graphics_thing);
        __put_user(0, &ctx->regs[0]);
-       for(i = 1; i < 32; i++)
+       for (i = 1; i < 32; i++)
                __put_user(regs->regs[i], &ctx->regs[i]);
        __put_user(regs->lo, &ctx->regs[32]);
        __put_user(regs->hi, &ctx->regs[33]);
@@ -821,7+820,6 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
        error = 0;
 
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -830,7+828,6 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
        int error, base = 0;
        struct irix5_context *ctx;
 
-       lock_kernel();
        if(regs->regs[2] == 1000)
                base = 1;
        ctx = (struct irix5_context *) regs->regs[base + 4];
@@ -841,15+838,15 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
 #endif
 
        error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
-       if(error)
+       if (error)
                goto out;
 
-       if(ctx->flags & 0x02) {
+       if (ctx->flags & 0x02) {
                /* XXX sigstack garbage, todo... */
                printk("Wheee, cannot do sigstack stuff in setcontext\n");
        }
 
-       if(ctx->flags & 0x04) {
+       if (ctx->flags & 0x04) {
                int i;
 
                /* XXX extra control block stuff... todo... */
@@ -860,7+857,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
                regs->cp0_epc = ctx->regs[35];
        }
 
-       if(ctx->flags & 0x08) {
+       if (ctx->flags & 0x08) {
                /* XXX fpu context, blah... */
                printk("Wheee, cannot restore FPU context yet...\n");
        }
@@ -868,7+865,6 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
        error = regs->regs[2];
 
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -878,7+874,6 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol
 {
        int error;
 
-       lock_kernel();
 #ifdef DEBUG_SIG
        printk("[%s:%d] irix_sigstack(%p,%p)\n",
               current->comm, current->pid, new, old);
@@ -895,8+890,8 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol
                        goto out;
        }
        error = 0;
+
 out:
-       unlock_kernel();
        return error;
 }
 
@@ -907,18+902,17 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
 {
        int error;
 
-       lock_kernel();
 #ifdef DEBUG_SIG
        printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
               current->comm, current->pid, new, old);
 #endif
-       if(new) {
+       if (new) {
                error = verify_area(VERIFY_READ, new, sizeof(*new));
                if(error)
                        goto out;
        }
 
-       if(old) {
+       if (old) {
                error = verify_area(VERIFY_WRITE, old, sizeof(*old));
                if(error)
                        goto out;
@@ -927,7+921,6 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
 
 out:
        error = 0;
-       unlock_kernel();
 
        return error;
 }
@@ -940,7+933,6 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
 {
        int error;
 
-       lock_kernel();
        error = verify_area(VERIFY_READ, pset, sizeof(*pset));
        if(error)
                goto out;
@@ -950,10+942,8 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
               pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
               sig);
 #endif
-
        error = -EINVAL;
 
 out:
-       unlock_kernel();
        return error;
 }
index 239576e..bdab19d 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: irq.c,v 1.20 2000/02/23 00:41:00 ralf Exp $
- *
+/*
  * 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.
@@ -7,7+6,7 @@
  * Code to handle x86 style IRQs plus some generic interrupt stuff.
  *
  * Copyright (C) 1992 Linus Torvalds
- * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1994 - 2000 Ralf Baechle
  */
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -267,8+266,10 @@ int i8259_setup_irq(int irq, struct irqaction * new)
        if (!shared) {
                if (is_i8259_irq(irq))
                    unmask_irq(irq);
+#if CONFIG_DDB5074 /* This has no business here  */
                else
                    nile4_enable_irq(irq_to_nile4(irq));
+#endif
        }
        restore_flags(flags);
        return 0;
@@ -343,7+344,7 @@ unsigned long probe_irq_on (void)
        /* first, enable any unassigned (E)ISA irqs */
        for (i = 15; i > 0; i--) {
                if (!irq_action[i]) {
-                       enable_irq(i);
+                       i8259_enable_irq(i);
                        irqs |= (1 << i);
                }
        }
index bfd75f6..1948a67 100644 (file)
-/* $Id: mips_ksyms.c,v 1.25 2000/02/24 00:12:40 ralf Exp $
- *
+/*
  * Export MIPS-specific functions needed for loadable modules.
  *
  * 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) 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
  */
 #include <linux/config.h>
 #include <linux/module.h>
 #include <asm/irq.h>
 #include <linux/in6.h>
 #include <linux/pci.h>
+#include <linux/ide.h>
 
 #include <asm/checksum.h>
 #include <asm/dma.h>
-#include <asm/floppy.h>
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/sgi/sgihpc.h>
 #include <asm/softirq.h>
 #include <asm/uaccess.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
@@ -50,11+52,12 @@ EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(strcat);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL_NOVERS(strpbrk);
 EXPORT_SYMBOL_NOVERS(strncat);
 EXPORT_SYMBOL_NOVERS(strnlen);
 EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strstr);
 EXPORT_SYMBOL_NOVERS(strtok);
-EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(_clear_page);
 EXPORT_SYMBOL(enable_irq);
@@ -131,4+134,9 @@ EXPORT_SYMBOL(unregister_fpe);
 EXPORT_SYMBOL(screen_info);
 #endif
 
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+EXPORT_SYMBOL(ide_ops);
+#endif
+
 EXPORT_SYMBOL(get_wchan);
+EXPORT_SYMBOL(irq_stat);
index dd96d03..4a55e23 100644 (file)
@@ -39,12+39,12 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 #endif
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED) {
+               if (current->ptrace & PT_PTRACED) {
                        res = -EPERM;
                        goto out;
                }
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                res = 0;
                goto out;
        }
@@ -76,9+76,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                     (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out_tsk;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out_tsk;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irq(&tasklist_lock);
                if (child->p_pptr != current) {
@@ -93,7+93,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out_tsk;
        }
        res = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out_tsk;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -243,9+243,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                if ((unsigned long) data > _NSIG)
                        break;
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                wake_up_process(child);
                res = 0;
@@ -269,7+269,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                res = -EIO;
                if ((unsigned long) data > _NSIG)
                        break;
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                child->exit_code = data;
                write_lock_irq(&tasklist_lock);
                REMOVE_LINKS(child);
@@ -293,8+293,8 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+                       != (PT_PTRACED|PT_TRACESYS))
                return;
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
index cb81afa..0135a6c 100644 (file)
@@ -171,6+171,7 @@ stackargs:
 
        /*
         * The stackpointer for a call with more than 4 arguments is bad.
+        * We probably should handle this case a bit more drastic.
         */
 bad_stack:
        negu    v0                              # error
index fa44ffa..809d13a 100644 (file)
@@ -76,7+76,7 @@ extern struct fd_ops no_fd_ops;
 struct fd_ops *fd_ops;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 extern struct ide_ops no_ide_ops;
 struct ide_ops *ide_ops;
 #endif
@@ -84,8+84,10 @@ struct ide_ops *ide_ops;
 extern struct rtc_ops no_rtc_ops;
 struct rtc_ops *rtc_ops;
 
+#ifdef CONFIG_PC_KEYB
 extern struct kbd_ops no_kbd_ops;
 struct kbd_ops *kbd_ops;
+#endif
 
 /*
  * Setup information
@@ -272,8+274,11 @@ void __init setup_arch(char **cmdline_p)
        ide_ops = &no_ide_ops;
 #endif
 
-       rtc_ops = &no_rtc_ops;
+#ifdef CONFIG_PC_KEYB
        kbd_ops = &no_kbd_ops;
+#endif
+       
+       rtc_ops = &no_rtc_ops;
 
        switch(mips_machgroup)
        {
index 6010678..5a99921 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: signal.c,v 1.24 2000/02/04 07:40:23 ralf Exp $
- *
+/*
  * 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.
@@ -37,6+36,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
 
+extern asmlinkage void syscall_trace(void);
+
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
        if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
@@ -265,6+266,8 @@ sys_sigreturn(struct pt_regs regs)
        /*
         * Don't let your children do this ...
         */
+       if (current->ptrace & PT_TRACESYS)
+               syscall_trace();
        __asm__ __volatile__(
                "move\t$29, %0\n\t"
                "j\tret_from_sys_call"
@@ -585,7+588,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
@@ -659,7+662,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                                /* FALLTHRU */
 
                        default:
-                               lock_kernel();
                                sigaddset(&current->signal, signr);
                                recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
index 6b1bd77..1cf4c3a 100644 (file)
@@ -1,10+1,9 @@
-/* $Id: softfp.S,v 1.1 1998/07/16 19:10:02 ralf Exp $
- *
+/*
  * 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) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2000 by Ralf Baechle
  *
  * For now it's just a crude hack good enough to run certain fp programs like
  * Mozilla.
@@ -190,15+189,15 @@ LEAF(simfp)
 #define FMT_switch(insn,opc,temp0,temp1)                               \
 insn:  srl     temp0, opc, 19;                                         \
        andi    temp0, 0x1c;                                            \
-       la      temp1, insn ## .tab;                                    \
+       la      temp1, insn##.tab;                                      \
        addu    temp0, temp1;                                           \
        lw      temp0, (temp0);                                         \
        jr      temp0;                                                  \
                                                                        \
        .data;                                                          \
-insn ## .tab:                                                          \
-       .word   insn ## .s, insn ## .d, unimp, unimp;                   \
-       .word   insn ## .w, insn ## .l, unimp, unimp;                   \
+insn##.tab:                                                            \
+       .word   insn##.s, insn##.d, unimp, unimp;                       \
+       .word   insn##.w, insn##.l, unimp, unimp;                       \
        .previous
 
        BITCH(add)
index d98507f..2afb00e 100644 (file)
-/* $Id: syscall.c,v 1.13 2000/02/04 07:40:23 ralf Exp $
- *
+/*
  * 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) 1995 - 1999 by Ralf Baechle
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
  *
  * TODO:  Implement the compatibility syscalls.
  *        Don't waste that much memory for empty entries in the syscall
 #include <linux/mman.h>
 #include <linux/sched.h>
 #include <linux/file.h>
+#include <linux/slab.h>
 #include <linux/utsname.h>
 #include <linux/unistd.h>
 #include <asm/branch.h>
index 99d7cb2..817e9c1 100644 (file)
-/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $
- *
+/*
  * sysirix.c: IRIX system call emulation.
  *
  * Copyright (C) 1996 David S. Miller
  * Copyright (C) 1997 Miguel de Icaza
  * Copyright (C) 1997, 1998 Ralf Baechle
  */
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/pagemap.h>
 #include <asm/sgialib.h>
 #include <asm/inventory.h>
 
-/* 2,526 lines of complete and utter shit coming up... */
+/* 2,191 lines of complete and utter shit coming up... */
 
 extern int max_threads;
 
@@ -59,7+57,7 @@ asmlinkage int irix_sysmp(struct pt_regs *regs)
                error = smp_num_cpus;
                break;
        default:
-               printk("SYSMP[%s:%ld]: Unsupported opcode %d\n",
+               printk("SYSMP[%s:%d]: Unsupported opcode %d\n",
                       current->comm, current->pid, (int)cmd);
                error = -EINVAL;
                break;
@@ -91,13+89,12 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
        unsigned long cmd;
        int error = 0, base = 0;
 
-       lock_kernel();
-       if(regs->regs[2] == 1000)
+       if (regs->regs[2] == 1000)
                base = 1;
        cmd = regs->regs[base + 4];
-       switch(cmd) {
+       switch (cmd) {
        case PR_MAXPROCS:
-               printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
+               printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
                       current->comm, current->pid);
                error = max_threads;
                break;
@@ -105,14+102,14 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
        case PR_ISBLOCKED: {
                struct task_struct *task;
 
-               printk("irix_prctl[%s:%ld]: Wants PR_ISBLOCKED\n",
+               printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
                       current->comm, current->pid);
+               read_lock(&tasklist_lock);
                task = find_task_by_pid(regs->regs[base + 5]);
-               if(!task) {
-                       error = -ESRCH;
-                       break;
-               }
-               error = (task->run_list.next != NULL);
+               error = -ESRCH;
+               if (error)
+                       error = (task->run_list.next != NULL);
+               read_unlock(&tasklist_lock);
                /* Can _your_ OS find this out that fast? */ 
                break;
        }
@@ -120,17+117,17 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
        case PR_SETSTACKSIZE: {
                long value = regs->regs[base + 5];
 
-               printk("irix_prctl[%s:%ld]: Wants PR_SETSTACKSIZE<%08lx>\n",
+               printk("irix_prctl[%s:%d]: Wants PR_SETSTACKSIZE<%08lx>\n",
                       current->comm, current->pid, (unsigned long) value);
-               if(value > RLIM_INFINITY)
+               if (value > RLIM_INFINITY)
                        value = RLIM_INFINITY;
-               if(capable(CAP_SYS_ADMIN)) {
+               if (capable(CAP_SYS_ADMIN)) {
                        current->rlim[RLIMIT_STACK].rlim_max =
                                current->rlim[RLIMIT_STACK].rlim_cur = value;
                        error = value;
                        break;
                }
-               if(value > current->rlim[RLIMIT_STACK].rlim_max) {
+               if (value > current->rlim[RLIMIT_STACK].rlim_max) {
                        error = -EINVAL;
                        break;
                }
@@ -140,25+137,25 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
        }
 
        case PR_GETSTACKSIZE:
-               printk("irix_prctl[%s:%ld]: Wants PR_GETSTACKSIZE\n",
+               printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
                       current->comm, current->pid);
                error = current->rlim[RLIMIT_STACK].rlim_cur;
                break;
 
        case PR_MAXPPROCS:
-               printk("irix_prctl[%s:%ld]: Wants PR_MAXPROCS\n",
+               printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
                       current->comm, current->pid);
                error = 1;
                break;
 
        case PR_UNBLKONEXEC:
-               printk("irix_prctl[%s:%ld]: Wants PR_UNBLKONEXEC\n",
+               printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_SETEXITSIG:
-               printk("irix_prctl[%s:%ld]: Wants PR_SETEXITSIG\n",
+               printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
                       current->comm, current->pid);
 
                /* We can probably play some game where we set the task
@@ -169,31+166,31 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
                break;
 
        case PR_RESIDENT:
-               printk("irix_prctl[%s:%ld]: Wants PR_RESIDENT\n",
+               printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
                       current->comm, current->pid);
                error = 0; /* Compatibility indeed. */
                break;
 
        case PR_ATTACHADDR:
-               printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDR\n",
+               printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_DETACHADDR:
-               printk("irix_prctl[%s:%ld]: Wants PR_DETACHADDR\n",
+               printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_TERMCHILD:
-               printk("irix_prctl[%s:%ld]: Wants PR_TERMCHILD\n",
+               printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_GETSHMASK:
-               printk("irix_prctl[%s:%ld]: Wants PR_GETSHMASK\n",
+               printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
                       current->comm, current->pid);
                error = -EINVAL; /* Until I have the sproc() stuff in. */
                break;
@@ -203,30+200,29 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
                break;
 
        case PR_COREPID:
-               printk("irix_prctl[%s:%ld]: Wants PR_COREPID\n",
+               printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_ATTACHADDRPERM:
-               printk("irix_prctl[%s:%ld]: Wants PR_ATTACHADDRPERM\n",
+               printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
                       current->comm, current->pid);
                error = -EINVAL;
                break;
 
        case PR_PTHREADEXIT:
-               printk("irix_prctl[%s:%ld]: Wants PR_PTHREADEXIT\n",
+               printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
                       current->comm, current->pid);
                do_exit(regs->regs[base + 5]);
 
        default:
-               printk("irix_prctl[%s:%ld]: Non-existant opcode %d\n",
+               printk("irix_prctl[%s:%d]: Non-existant opcode %d\n",
                       current->comm, current->pid, (int)cmd);
                error = -EINVAL;
                break;
        }
 
-       unlock_kernel();
        return error;
 }
 
@@ -267,81+263,83 @@ extern long prom_setenv(char *name, char *value);
 
 asmlinkage int irix_syssgi(struct pt_regs *regs)
 {
-        unsigned long cmd;
-        int retval, base = 0;
+       unsigned long cmd;
+       int retval, base = 0;
 
-        lock_kernel();
-        if(regs->regs[2] == 1000)
-                base = 1;
+       if (regs->regs[2] == 1000)
+               base = 1;
 
-        cmd = regs->regs[base + 4];
-        switch(cmd) {
-        case SGI_SYSID: {
-                char *buf = (char *) regs->regs[base + 5];
+       cmd = regs->regs[base + 4];
+       switch(cmd) {
+       case SGI_SYSID: {
+               char *buf = (char *) regs->regs[base + 5];
 
-                /* XXX Use ethernet addr.... */
-                retval = clear_user(buf, 64);
-                break;
-        }
+               /* XXX Use ethernet addr.... */
+               retval = clear_user(buf, 64);
+               break;
+       }
 #if 0
-        case SGI_RDNAME: {
-                int pid = (int) regs->regs[base + 5];
-                char *buf = (char *) regs->regs[base + 6];
-                struct task_struct *p;
-
-                retval = verify_area(VERIFY_WRITE, buf, 16);
-                if(retval)
-                        break;
-                for_each_task(p) {
-                        if(p->pid == pid)
-                                goto found0;
-                }
-                retval = -ESRCH;
-
-        found0:
-                /* XXX Need to check sizes. */
-                copy_to_user(buf, p->comm, 16);
-                retval = 0;
-                break;
-        }
-
-        case SGI_GETNVRAM: {
-                char *name = (char *) regs->regs[base+5];
-                char *buf = (char *) regs->regs[base+6];
-                char *value;
+       case SGI_RDNAME: {
+               int pid = (int) regs->regs[base + 5];
+               char *buf = (char *) regs->regs[base + 6];
+               struct task_struct *p;
+               char comm[16];
+
+               retval = verify_area(VERIFY_WRITE, buf, 16);
+               if (retval)
+                       break;
+               read_lock(&tasklist_lock);
+               p = find_task_by_pid(pid);
+               if (!p) {
+                       read_unlock(&tasklist_lock);
+                       retval = -ESRCH;
+                       break;
+               }
+               memcpy(comm, p->comm, 16);
+               read_unlock(&tasklist_lock);
+
+               /* XXX Need to check sizes. */
+               copy_to_user(buf, p->comm, 16);
+               retval = 0;
+               break;
+       }
+
+       case SGI_GETNVRAM: {
+               char *name = (char *) regs->regs[base+5];
+               char *buf = (char *) regs->regs[base+6];
+               char *value;
                return -EINVAL; /* til I fix it */
-                retval = verify_area(VERIFY_WRITE, buf, 128);
-                if (retval)
-                        break;
-                value = prom_getenv(name);
-                if (!value) {
-                        retval = -EINVAL;
-                        break;
-                }
-                /* Do I strlen() for the length? */
-                copy_to_user(buf, value, 128);
-                retval = 0;
-                break;
-        }
-
-        case SGI_SETNVRAM: {
-                char *name = (char *) regs->regs[base+5];
-                char *value = (char *) regs->regs[base+6];
+               retval = verify_area(VERIFY_WRITE, buf, 128);
+               if (retval)
+                       break;
+               value = prom_getenv(name);      /* PROM lock?  */
+               if (!value) {
+                       retval = -EINVAL;
+                       break;
+               }
+               /* Do I strlen() for the length? */
+               copy_to_user(buf, value, 128);
+               retval = 0;
+               break;
+       }
+
+       case SGI_SETNVRAM: {
+               char *name = (char *) regs->regs[base+5];
+               char *value = (char *) regs->regs[base+6];
                return -EINVAL; /* til I fix it */
-                retval = prom_setenv(name, value);
+               retval = prom_setenv(name, value);
                /* XXX make sure retval conforms to syssgi(2) */
                printk("[%s:%d] setnvram(\"%s\", \"%s\"): retval %d",
-                      current->comm, current->pid,
-                      name, value, retval);
+                      current->comm, current->pid, name, value, retval);
 /*             if (retval == PROM_ENOENT)
                        retval = -ENOENT; */
                break;                             
        }
 #endif
-       
+
        case SGI_SETPGID: {
 #ifdef DEBUG_PROCGRPS
-               printk("[%s:%ld] setpgid(%d, %d) ",
+               printk("[%s:%d] setpgid(%d, %d) ",
                       current->comm, current->pid,
                       (int) regs->regs[base + 5], (int)regs->regs[base + 6]);
 #endif
@@ -438,7+436,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
 
        case SGI_GETSID:
 #ifdef DEBUG_PROCGRPS
-               printk("[%s:%ld] getsid(%d) ", current->comm, current->pid,
+               printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
                       (int) regs->regs[base + 5]);
 #endif
                retval = sys_getsid(regs->regs[base + 5]);
@@ -463,25+461,31 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
                break;
 
        case SGI_PHYSP: {
+               unsigned long addr = regs->regs[base + 5];
+               int *pageno = (int *) (regs->regs[base + 6]);
+               struct mm_struct *mm = current->mm;
                pgd_t *pgdp;
                pmd_t *pmdp;
                pte_t *ptep;
-               unsigned long addr = regs->regs[base + 5];
-               int *pageno = (int *) (regs->regs[base + 6]);
 
                retval = verify_area(VERIFY_WRITE, pageno, sizeof(int));
-               if(retval)
+               if (retval)
                        return retval;
-               pgdp = pgd_offset(current->mm, addr);
+
+               down(&mm->mmap_sem);
+               pgdp = pgd_offset(mm, addr);
                pmdp = pmd_offset(pgdp, addr);
                ptep = pte_offset(pmdp, addr);
-               if(ptep) {
-                       if(pte_val(*ptep) & (_PAGE_VALID | _PAGE_PRESENT)) {
-                               return put_user((pte_val(*ptep) & PAGE_MASK)>>PAGE_SHIFT, pageno);
-                               return 0;
+               retval = -EINVAL;
+               if (ptep) {
+                       pte_t pte = *ptep;
+
+                       if (pte_val(pte) & (_PAGE_VALID | _PAGE_PRESENT)) {
+                               retval =  put_user((pte_val(pte) & PAGE_MASK) >>
+                                                  PAGE_SHIFT, pageno);
                        }
                }
-               retval = -EINVAL;
+               up(&mm->mmap_sem);
                break;
        }
 
@@ -490,7+494,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
                void *buffer = (void *) regs->regs [base + 6];
                int  count   = (int)    regs->regs [base + 7];
 
-               switch (arg1){
+               switch (arg1) {
                case SGI_INV_SIZEOF:
                        retval = sizeof (inventory_t);
                        break;
@@ -510,7+514,6 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
        };
 
 out:
-       unlock_kernel();
        return retval;
 }
 
@@ -532,7+535,7 @@ asmlinkage int irix_brk(unsigned long brk)
        struct mm_struct *mm = current->mm;
        int ret;
 
-       lock_kernel();
+       down(&mm->mmap_sem);
        if (brk < mm->end_code) {
                ret = -ENOMEM;
                goto out;
@@ -590,7+593,7 @@ asmlinkage int irix_brk(unsigned long brk)
        ret = 0;
 
 out:
-       unlock_kernel();
+       up(&mm->mmap_sem);
        return ret;
 }
 
@@ -612,26+615,21 @@ asmlinkage int irix_getgid(struct pt_regs *regs)
        return current->gid;
 }
 
+extern rwlock_t xtime_lock;
+
 asmlinkage int irix_stime(int value)
 {
-       int ret;
+       if (!capable(CAP_SYS_TIME))
+               return -EPERM;
 
-       lock_kernel();
-       if(!capable(CAP_SYS_TIME)) {
-               ret = -EPERM;
-               goto out;
-       }
-       cli();
+       write_lock_irq(&xtime_lock);
        xtime.tv_sec = value;
        xtime.tv_usec = 0;
        time_maxerror = MAXPHASE;
        time_esterror = MAXPHASE;
-       sti();
-       ret = 0;
+       write_unlock_irq(&xtime_lock);
 
-out:
-       unlock_kernel();
-       return ret;
+       return 0;
 }
 
 extern int do_setitimer(int which, struct itimerval *value,
@@ -641,7+639,6 @@ static inline void jiffiestotv(unsigned long jiffies, struct timeval *value)
 {
        value->tv_usec = (jiffies % HZ) * (1000000 / HZ);
        value->tv_sec = jiffies / HZ;
-       return;
 }
 
 static inline void getitimer_real(struct itimerval *value)
@@ -668,8+665,7 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds)
        struct itimerval it_new, it_old;
        unsigned int oldalarm;
 
-       lock_kernel();
-       if(!seconds) {
+       if (!seconds) {
                getitimer_real(&it_old);
                del_timer(&current->real_timer);
        } else {
@@ -679,11+675,13 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds)
                do_setitimer(ITIMER_REAL, &it_new, &it_old);
        }
        oldalarm = it_old.it_value.tv_sec;
-       /* ehhh.. We can't return 0 if we have an alarm pending.. */
-       /* And we'd better return too much than too little anyway */
+       /*
+        * ehhh.. We can't return 0 if we have an alarm pending ...
+        * And we'd better return too much than too little anyway
+        */
        if (it_old.it_value.tv_usec)
                oldalarm++;
-       unlock_kernel();
+
        return oldalarm;
 }
 
@@ -691,6+689,7 @@ asmlinkage int irix_pause(void)
 {
        current->state = TASK_INTERRUPTIBLE;
        schedule();
+
        return -EINTR;
 }
 
@@ -701,14+700,11 @@ extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
 asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
                          char *type, void *data, int datalen)
 {
-       int ret;
-
-       printk("[%s:%ld] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
+       printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
               current->comm, current->pid,
               dev_name, dir_name, flags, type, data, datalen);
-       ret = sys_mount(dev_name, dir_name, type, flags, data);
 
-       return ret;
+       return sys_mount(dev_name, dir_name, type, flags, data);
 }
 
 struct irix_statfs {
@@ -725,7+721,7 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
        int error, i;
 
        /* We don't support this feature yet. */
-       if(fs_type) {
+       if (fs_type) {
                error = -EINVAL;
                goto out;
        }
@@ -747,7+743,7 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
        __put_user(kbuf.f_bfree, &buf->f_bfree);
        __put_user(kbuf.f_files, &buf->f_files);
        __put_user(kbuf.f_ffree, &buf->f_ffree);
-       for(i = 0; i < 6; i++) {
+       for (i = 0; i < 6; i++) {
                __put_user(0, &buf->f_fname[i]);
                __put_user(0, &buf->f_fpack[i]);
        }
@@ -803,7+799,7 @@ asmlinkage int irix_setpgrp(int flags)
        int error;
 
 #ifdef DEBUG_PROCGRPS
-       printk("[%s:%ld] setpgrp(%d) ", current->comm, current->pid, flags);
+       printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
 #endif
        if(!flags)
                error = current->pgrp;
@@ -818,23+814,19 @@ asmlinkage int irix_setpgrp(int flags)
 
 asmlinkage int irix_times(struct tms * tbuf)
 {
-       int error;
+       int err = 0;
 
-       lock_kernel();
        if (tbuf) {
-               error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
-               if (error)
-                       goto out;
-               __put_user(current->times.tms_utime,&tbuf->tms_utime);
-               __put_user(current->times.tms_stime,&tbuf->tms_stime);
-               __put_user(current->times.tms_cutime,&tbuf->tms_cutime);
-               __put_user(current->times.tms_cstime,&tbuf->tms_cstime);
+               err = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+               if (err)
+                       return err;
+               err |= __put_user(current->times.tms_utime,&tbuf->tms_utime);
+               err |= __put_user(current->times.tms_stime,&tbuf->tms_stime);
+               err |= __put_user(current->times.tms_cutime,&tbuf->tms_cutime);
+               err |= __put_user(current->times.tms_cstime,&tbuf->tms_cstime);
        }
-       error = 0;
 
-out:
-       unlock_kernel();
-       return error;
+       return err;
 }
 
 asmlinkage int irix_exec(struct pt_regs *regs)
@@ -847,12+839,12 @@ asmlinkage int irix_exec(struct pt_regs *regs)
        filename = getname((char *) (long)regs->regs[base + 4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
-               goto out;
+               return error;
+
        error = do_execve(filename, (char **) (long)regs->regs[base + 5],
                          (char **) 0, regs);
        putname(filename);
 
-out:
        return error;
 }
 
@@ -861,31+853,32 @@ asmlinkage int irix_exece(struct pt_regs *regs)
        int error, base = 0;
        char *filename;
 
-       if(regs->regs[2] == 1000)
+       if (regs->regs[2] == 1000)
                base = 1;
        filename = getname((char *) (long)regs->regs[base + 4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
-               goto out;
+               return error;
        error = do_execve(filename, (char **) (long)regs->regs[base + 5],
                          (char **) (long)regs->regs[base + 6], regs);
        putname(filename);
 
-out:
        return error;
 }
 
 asmlinkage unsigned long irix_gethostid(void)
 {
-       printk("[%s:%ld]: irix_gethostid() called...\n",
+       printk("[%s:%d]: irix_gethostid() called...\n",
               current->comm, current->pid);
+
        return -EINVAL;
 }
 
 asmlinkage unsigned long irix_sethostid(unsigned long val)
 {
-       printk("[%s:%ld]: irix_sethostid(%08lx) called...\n",
+       printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
               current->comm, current->pid, val);
+
        return -EINVAL;
 }
 
@@ -929,20+922,18 @@ asmlinkage int irix_getdomainname(char *name, int len)
 {
        int error;
 
-       lock_kernel();
+       error = verify_area(VERIFY_WRITE, name, len);
+       if (error)
+               return error;
+
+       down_read(&uts_sem);
        if(len > (__NEW_UTS_LEN - 1))
                len = __NEW_UTS_LEN - 1;
-       error = verify_area(VERIFY_WRITE, name, len);
-       if(error)
-               goto out;
-       if(copy_to_user(name, system_utsname.domainname, len)) {
-               error = -EFAULT;
-               goto out;
-       }
        error = 0;
+       if (copy_to_user(name, system_utsname.domainname, len))
+               error = -EFAULT;
+       up_read(&uts_sem);
 
-out:
-       unlock_kernel();
        return error;
 }
 
@@ -955,7+946,7 @@ asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1,
                           unsigned long arg2, unsigned long arg3,
                           unsigned long arg4)
 {
-       switch(opcode) {
+       switch (opcode) {
        case 0:
                return sys_msgget((key_t) arg0, (int) arg1);
        case 1:
@@ -974,7+965,7 @@ asmlinkage int irix_msgsys(int opcode, unsigned long arg0, unsigned long arg1,
 asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1,
                           unsigned long arg2, unsigned long arg3)
 {
-       switch(opcode) {
+       switch (opcode) {
        case 0:
                return sys_shmat((int) arg0, (char *)arg1, (int) arg2,
                                 (unsigned long *) arg3);
@@ -992,7+983,7 @@ asmlinkage int irix_shmsys(int opcode, unsigned long arg0, unsigned long arg1,
 asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1,
                           unsigned long arg2, int arg3)
 {
-       switch(opcode) {
+       switch (opcode) {
        case 0:
                return sys_semctl((int) arg0, (int) arg1, (int) arg2,
                                  (union semun) arg3);
@@ -1006,25+997,42 @@ asmlinkage int irix_semsys(int opcode, unsigned long arg0, unsigned long arg1,
        }
 }
 
-extern asmlinkage int sys_llseek(unsigned int fd, unsigned long offset_high,
-                                unsigned long offset_low, loff_t * result,
-                                unsigned int origin);
+static inline loff_t llseek(struct file *file, loff_t offset, int origin)
+{
+       loff_t (*fn)(struct file *, loff_t, int);
+       loff_t retval;
 
-asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base)
+       fn = default_llseek;
+       if (file->f_op && file->f_op->llseek)
+        fn = file->f_op->llseek;
+       lock_kernel();
+       retval = fn(file, offset, origin);
+       unlock_kernel();
+       return retval;
+}
+
+asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow,
+                            int origin)
 {
-       mm_segment_t old_fs;
-       loff_t junk;
-       int error;
+       int retval;
+       struct file * file;
+       loff_t offset;
 
-       old_fs = get_fs(); set_fs(get_ds());
-       error = sys_llseek(fd, offhi, offlow, &junk, base);
-       set_fs(old_fs);
+       retval = -EBADF;
+       file = fget(fd);
+       if (!file)
+               goto bad;
+       retval = -EINVAL;
+       if (origin > 2)
+               goto out_putf;
 
-       if(error)
-               goto out;
-       error = (int) junk;
-out:
-       return error;
+       offset = llseek(file, ((loff_t) offhi << 32) | offlow, origin);
+       retval = (int) offset;
+
+out_putf:
+       fput(file);
+bad:
+       return retval;
 }
 
 asmlinkage int irix_sginap(int ticks)
@@ -1056,10+1064,8 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
        unsigned long retval;
 
        if (!(flags & MAP_ANONYMOUS)) {
-               if (!(file = fget(fd))) {
-                       retval = -EBADF;
-                       goto out;
-               }
+               if (!(file = fget(fd)))
+                       return -EBADF;
 
                /* Ok, bad taste hack follows, try to think in something else
                 * when reading this.  */
@@ -1083,28+1089,30 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
        if (file)
                fput(file);
 
-out:
        return retval;
 }
 
 asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
 {
-       printk("[%s:%ld] Wheee.. irix_madvise(%08lx,%d,%d)\n",
+       printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
               current->comm, current->pid, addr, len, behavior);
+
        return -EINVAL;
 }
 
 asmlinkage int irix_pagelock(char *addr, int len, int op)
 {
-       printk("[%s:%ld] Wheee.. irix_pagelock(%p,%d,%d)\n",
+       printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
               current->comm, current->pid, addr, len, op);
+
        return -EINVAL;
 }
 
 asmlinkage int irix_quotactl(struct pt_regs *regs)
 {
-       printk("[%s:%ld] Wheee.. irix_quotactl()\n",
+       printk("[%s:%d] Wheee.. irix_quotactl()\n",
               current->comm, current->pid);
+
        return -EINVAL;
 }
 
@@ -1113,14+1121,14 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
        int error;
 
 #ifdef DEBUG_PROCGRPS
-       printk("[%s:%ld] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
+       printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
               pid, pgrp);
 #endif
        if(!pid)
                pid = current->pid;
 
        /* Wheee, weird sysv thing... */
-       if((pgrp == 0) && (pid == current->pid))
+       if ((pgrp == 0) && (pid == current->pid))
                error = sys_setsid();
        else
                error = sys_setpgid(pid, pgrp);
@@ -1134,8+1142,9 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
 
 asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
 {
-       printk("[%s:%ld] Wheee.. irix_systeminfo(%d,%p,%d)\n",
+       printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
               current->comm, current->pid, cmd, buf, cnt);
+
        return -EINVAL;
 }
 
@@ -1149,22+1158,17 @@ struct iuname {
 
 asmlinkage int irix_uname(struct iuname *buf)
 {
-       int retval;
-
-       lock_kernel();
-       if(copy_to_user(system_utsname.sysname, buf->sysname, 65)
-          || copy_to_user(system_utsname.nodename, buf->nodename, 65)
-          || copy_to_user(system_utsname.release, buf->release, 65)
-          || copy_to_user(system_utsname.version, buf->version, 65)
-          || copy_to_user(system_utsname.machine, buf->machine, 65)) {
-               retval = -EFAULT;
-               goto out;
+       down_read(&uts_sem);
+       if (copy_to_user(system_utsname.sysname, buf->sysname, 65)
+           || copy_to_user(system_utsname.nodename, buf->nodename, 65)
+           || copy_to_user(system_utsname.release, buf->release, 65)
+           || copy_to_user(system_utsname.version, buf->version, 65)
+           || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+               return -EFAULT;
        }
-       retval = 1;
+       up_read(&uts_sem);
 
-out:
-       unlock_kernel();
-       return retval;
+       return 1;
 }
 
 #undef DEBUG_XSTAT
@@ -1260,7+1264,7 @@ asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
        int retval;
 
 #ifdef DEBUG_XSTAT
-       printk("[%s:%ld] Wheee.. irix_xstat(%d,%s,%p) ",
+       printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
               current->comm, current->pid, version, filename, statbuf);
 #endif
        switch(version) {
@@ -1309,7+1313,7 @@ asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
        int error;
 
 #ifdef DEBUG_XSTAT
-       printk("[%s:%ld] Wheee.. irix_lxstat(%d,%s,%p) ",
+       printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
               current->comm, current->pid, version, filename, statbuf);
 #endif
        switch(version) {
@@ -1358,7+1362,7 @@ asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
        int error;
 
 #ifdef DEBUG_XSTAT
-       printk("[%s:%ld] Wheee.. irix_fxstat(%d,%d,%p) ",
+       printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
               current->comm, current->pid, version, fd, statbuf);
 #endif
        switch(version) {
@@ -1406,26+1410,27 @@ asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev)
 {
        int retval;
 
-       printk("[%s:%ld] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
+       printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
               current->comm, current->pid, ver, filename, mode, (int) dev);
+
        switch(ver) {
        case 2:
                retval = sys_mknod(filename, mode, dev);
-               goto out;
+               break;
 
        default:
                retval = -EINVAL;
-               goto out;
+               break;
        };
 
-out:
        return retval;
 }
 
 asmlinkage int irix_swapctl(int cmd, char *arg)
 {
-       printk("[%s:%ld] Wheee.. irix_swapctl(%d,%p)\n",
+       printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
               current->comm, current->pid, cmd, arg);
+
        return -EINVAL;
 }
 
@@ -1443,7+1448,7 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
        struct statfs kbuf;
        int error, i;
 
-       printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
+       printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
               current->comm, current->pid, fname, buf);
        error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
        if (error)
@@ -1468,11+1473,11 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
 #else
        __put_user(kbuf.f_fsid.val[0], &buf->f_fsid);
 #endif
-       for(i = 0; i < 16; i++)
+       for (i = 0; i < 16; i++)
                __put_user(0, &buf->f_basetype[i]);
        __put_user(0, &buf->f_flag);
        __put_user(kbuf.f_namelen, &buf->f_namemax);
-       for(i = 0; i < 32; i++)
+       for (i = 0; i < 32; i++)
                __put_user(0, &buf->f_fstr[i]);
 
        error = 0;
@@ -1489,7+1494,7 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
        struct file *file;
        int error, i;
 
-       printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
+       printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
               current->comm, current->pid, fd, buf);
 
        error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
@@ -1530,15+1535,17 @@ out:
 
 asmlinkage int irix_priocntl(struct pt_regs *regs)
 {
-       printk("[%s:%ld] Wheee.. irix_priocntl()\n",
+       printk("[%s:%d] Wheee.. irix_priocntl()\n",
               current->comm, current->pid);
+
        return -EINVAL;
 }
 
 asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
 {
-       printk("[%s:%ld] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
+       printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
               current->comm, current->pid, pid, sig, code, val);
+
        return -EINVAL;
 }
 
@@ -1549,7+1556,7 @@ asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
 {
        int retval;
 
-       if(size1) {
+       if (size1) {
                retval = -EINVAL;
                goto out;
        }
@@ -1563,7+1570,7 @@ asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2)
 {
        int retval;
 
-       if(size1) {
+       if (size1) {
                retval = -EINVAL;
                goto out;
        }
@@ -1649,7+1656,7 @@ out:
 
 asmlinkage int irix_dmi(struct pt_regs *regs)
 {
-       printk("[%s:%ld] Wheee.. irix_dmi()\n",
+       printk("[%s:%d] Wheee.. irix_dmi()\n",
               current->comm, current->pid);
 
        return -EINVAL;
@@ -1658,7+1665,7 @@ asmlinkage int irix_dmi(struct pt_regs *regs)
 asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
                          int off1, int off2)
 {
-       printk("[%s:%ld] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
+       printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
               current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
 
        return -EINVAL;
@@ -1667,7+1674,7 @@ asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
 asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
                           int off1, int off2)
 {
-       printk("[%s:%ld] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
+       printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
               current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
 
        return -EINVAL;
@@ -1677,7+1684,7 @@ asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1,
                                unsigned long arg2, unsigned long arg3,
                                unsigned long arg4, unsigned long arg5)
 {
-       printk("[%s:%ld] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
+       printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
               "%08lx,%08lx)\n",
               current->comm, current->pid, cmd, arg0, arg1, arg2,
               arg3, arg4, arg5);
@@ -1702,7+1709,7 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
        struct statfs kbuf;
        int error, i;
 
-       printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
+       printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
               current->comm, current->pid, fname, buf);
        error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
        if(error)
@@ -1748,7+1755,7 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
        struct file *file;
        int error, i;
 
-       printk("[%s:%ld] Wheee.. irix_fstatvfs(%d,%p)\n",
+       printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
               current->comm, current->pid, fd, buf);
 
        error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
@@ -1789,13+1796,13 @@ out:
 
 asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
 {
-       int error;
+       int err;
 
-       printk("[%s:%ld] irix_getmountid(%s, %p)\n",
+       printk("[%s:%d] irix_getmountid(%s, %p)\n",
               current->comm, current->pid, fname, midbuf);
-       error = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
-       if(error)
-               goto out;
+       err = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
+       if (err)
+               return err;
 
        /*
         * The idea with this system call is that when trying to determine
@@ -1803,21+1810,20 @@ asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
         * fsid of the filesystem to try and make the right decision, but
         * we don't have this so for now. XXX
         */
-       __put_user(0, &midbuf[0]);
-       __put_user(0, &midbuf[1]);
-       __put_user(0, &midbuf[2]);
-       __put_user(0, &midbuf[3]);
-       error = 0;
+       err |= __put_user(0, &midbuf[0]);
+       err |= __put_user(0, &midbuf[1]);
+       err |= __put_user(0, &midbuf[2]);
+       err |= __put_user(0, &midbuf[3]);
 
-out:
-       return error;
+       return err;
 }
 
 asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
                           unsigned long arg, unsigned long sp, int slen)
 {
-       printk("[%s:%ld] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
+       printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
               current->comm, current->pid, entry, mask, arg, sp, slen);
+
        return -EINVAL;
 }
 
@@ -1879,7+1885,7 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count
        int error;
 
 #ifdef DEBUG_GETDENTS
-       printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm,
+       printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
               current->pid, fd, dirent, count, eob);
 #endif
        error = -EBADF;
@@ -1979,11+1985,11 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
                goto out;
 
        error = -EFAULT;
-       if(!access_ok(VERIFY_WRITE, dirent, cnt))
+       if (!access_ok(VERIFY_WRITE, dirent, cnt))
                goto out_f;
 
        error = -EINVAL;
-       if(cnt < (sizeof(struct irix_dirent64) + 255))
+       if (cnt < (sizeof(struct irix_dirent64) + 255))
                goto out_f;
 
        buf.curr = (struct irix_dirent64 *) dirent;
@@ -2026,12+2032,12 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
                goto out;
 
        error = -EFAULT;
-       if(!access_ok(VERIFY_WRITE, dirent, cnt) ||
-          !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
+       if (!access_ok(VERIFY_WRITE, dirent, cnt) ||
+           !access_ok(VERIFY_WRITE, eob, sizeof(*eob)))
                goto out_f;
 
        error = -EINVAL;
-       if(cnt < (sizeof(struct irix_dirent64) + 255))
+       if (cnt < (sizeof(struct irix_dirent64) + 255))
                goto out_f;
 
        *eob = 0;
@@ -2063,44+2069,44 @@ asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long a
 {
        int retval;
 
-       switch(op) {
+       switch (op) {
        case 1:
                /* Reboot */
-               printk("[%s:%ld] irix_uadmin: Wants to reboot...\n",
+               printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 2:
                /* Shutdown */
-               printk("[%s:%ld] irix_uadmin: Wants to shutdown...\n",
+               printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 4:
                /* Remount-root */
-               printk("[%s:%ld] irix_uadmin: Wants to remount root...\n",
+               printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 8:
                /* Kill all tasks. */
-               printk("[%s:%ld] irix_uadmin: Wants to kill all tasks...\n",
+               printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 256:
                /* Set magic mushrooms... */
-               printk("[%s:%ld] irix_uadmin: Wants to set magic mushroom[%d]...\n",
+               printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
                       current->comm, current->pid, (int) func);
                retval = -EINVAL;
                goto out;
 
        default:
-               printk("[%s:%ld] irix_uadmin: Unknown operation [%d]...\n",
+               printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
                       current->comm, current->pid, (int) op);
                retval = -EINVAL;
                goto out;
@@ -2122,20+2128,20 @@ asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
 
        case 2:
                /* ustat() */
-               printk("[%s:%ld] irix_utssys: Wants to do ustat()\n",
+               printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 3:
                /* fusers() */
-               printk("[%s:%ld] irix_utssys: Wants to do fusers()\n",
+               printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        default:
-               printk("[%s:%ld] irix_utssys: Wants to do unknown type[%d]\n",
+               printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
                       current->comm, current->pid, (int) type);
                retval = -EINVAL;
                goto out;
@@ -2157,7+2163,7 @@ asmlinkage int irix_fcntl(int fd, int cmd, int arg)
        int retval;
 
 #ifdef DEBUG_FCNTL
-       printk("[%s:%ld] irix_fcntl(%d, %d, %d) ", current->comm,
+       printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
               current->pid, fd, cmd, arg);
 #endif
        if (cmd == IRIX_F_ALLOCSP){
@@ -2176,26+2182,26 @@ asmlinkage int irix_ulimit(int cmd, int arg)
 
        switch(cmd) {
        case 1:
-               printk("[%s:%ld] irix_ulimit: Wants to get file size limit.\n",
+               printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 2:
-               printk("[%s:%ld] irix_ulimit: Wants to set file size limit.\n",
+               printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 3:
-               printk("[%s:%ld] irix_ulimit: Wants to get brk limit.\n",
+               printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        case 4:
 #if 0
-               printk("[%s:%ld] irix_ulimit: Wants to get fd limit.\n",
+               printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
@@ -2204,13+2210,13 @@ asmlinkage int irix_ulimit(int cmd, int arg)
                goto out;
 
        case 5:
-               printk("[%s:%ld] irix_ulimit: Wants to get txt offset.\n",
+               printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
                       current->comm, current->pid);
                retval = -EINVAL;
                goto out;
 
        default:
-               printk("[%s:%ld] irix_ulimit: Unknown command [%d].\n",
+               printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
                       current->comm, current->pid, cmd);
                retval = -EINVAL;
                goto out;
@@ -2221,7+2227,7 @@ out:
 
 asmlinkage int irix_unimp(struct pt_regs *regs)
 {
-       printk("irix_unimp [%s:%ld] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
+       printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
               "a3=%08lx\n", current->comm, current->pid,
               (int) regs->regs[2], (int) regs->regs[3],
               regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
index 1602013..7d34f2d 100644 (file)
@@ -5,9+5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
- *
- * $Id: sysmips.c,v 1.8 2000/02/05 06:47:08 ralf Exp $
+ * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -51,45+49,48 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
 {
        int     *p;
        char    *name;
-       int     flags, tmp, len, retval;
+       int     flags, tmp, len, retval, errno;
+
+       switch(cmd) {
+       case SETNAME: {
+               char nodename[__NEW_UTS_LEN + 1];
 
-       lock_kernel();
-       switch(cmd)
-       {
-       case SETNAME:
-               retval = -EPERM;
                if (!capable(CAP_SYS_ADMIN))
-                       goto out;
+                       return -EPERM;
 
                name = (char *) arg1;
-               len = strlen_user(name);
-
-               retval = len;
-               if (len < 0)
-                       goto out;
 
-               retval = -EINVAL;
-               if (len == 0 || len > __NEW_UTS_LEN)
-                       goto out;
+               len = strncpy_from_user(nodename, name, sizeof(nodename));
+               if (len < 0) 
+                       return -EFAULT;
 
-               /* Fiiiixmeeee...  */
-               copy_from_user(system_utsname.nodename, name, len);
-               system_utsname.nodename[len] = '\0';
-               retval = 0;
-               goto out;
+               down_write(&uts_sem);
+               strncpy(system_utsname.nodename, name, len);
+               up_write(&uts_sem);
+               system_utsname.nodename[len] = '\0'; 
+               return 0;
+       }
 
-       case MIPS_ATOMIC_SET:
+       case MIPS_ATOMIC_SET: {
                /* This is broken in case of page faults and SMP ...
-                  Risc/OS fauls after maximum 20 tries with EAGAIN.  */
+                   Risc/OS faults after maximum 20 tries with EAGAIN.  */
+               unsigned int tmp;
+
                p = (int *) arg1;
-               retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
-               if (retval)
-                       goto out;
+               errno = verify_area(VERIFY_WRITE, p, sizeof(*p));
+               if (errno)
+                       return errno;
+               errno = 0;
                save_and_cli(flags);
-               retval = *p;
-               *p = arg2;
+               errno |= __get_user(tmp, p);
+               errno |= __put_user(arg2, p);
                restore_flags(flags);
-               goto out;
+
+               if (errno)
+                       return tmp;
+
+               return tmp;             /* This is broken ...  */ 
+        }
 
        case MIPS_FIXADE:
                tmp = current->thread.mflags & ~3;
@@ -112,7+113,6 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
        }
 
 out:
-       unlock_kernel();
        return retval;
 }
 
index ea36ed5..8de389a 100644 (file)
@@ -1,7+1,6 @@
-/* $Id: time.c,v 1.14 2000/01/26 00:07:44 ralf Exp $
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *  Copyright (C) 1996, 1997, 1998  Ralf Baechle
+/*
+ * Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ * Copyright (C) 1996 - 2000  Ralf Baechle
  *
  * This file contains the time handling details for PC-style clocks as
  * found in some MIPS systems.
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <linux/timex.h>
 
 extern volatile unsigned long lost_ticks;
+unsigned long r4k_interval = 0;
+extern rwlock_t xtime_lock;
 
 /*
  * Change this if you have some constant time drift
@@ -219,7+221,7 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
 
-       save_and_cli(flags);
+       read_lock_irqsave (&xtime_lock, flags);
        *tv = xtime;
        tv->tv_usec += do_gettimeoffset();
 
@@ -230,7+232,7 @@ void do_gettimeofday(struct timeval *tv)
        if (lost_ticks)
                tv->tv_usec += USECS_PER_JIFFY;
 
-       restore_flags(flags);
+       read_unlock_irqrestore (&xtime_lock, flags);
 
        if (tv->tv_usec >= 1000000) {
                tv->tv_usec -= 1000000;
@@ -240,7+242,7 @@ void do_gettimeofday(struct timeval *tv)
 
 void do_settimeofday(struct timeval *tv)
 {
-       cli();
+       write_lock_irq (&xtime_lock);
        /* This is revolting. We need to set the xtime.tv_usec
         * correctly. However, the value in this location is
         * is value at the last tick.
@@ -259,7+261,7 @@ void do_settimeofday(struct timeval *tv)
        time_status |= STA_UNSYNC;
        time_maxerror = NTP_PHASE_LIMIT;
        time_esterror = NTP_PHASE_LIMIT;
-       sti();
+       write_unlock_irq (&xtime_lock);
 }
 
 /*
@@ -355,7+357,6 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
             dist = period / 4;
        }
 #endif
-#ifdef CONFIG_PROFILE
        if(!user_mode(regs)) {
                if (prof_buffer && current->pid) {
                        extern int _stext;
@@ -373,7+374,6 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        atomic_inc((atomic_t *)&prof_buffer[pc]);
                }
        }
-#endif
        do_timer(regs);
 
        /*
@@ -381,22+381,26 @@ timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
         * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
         * called as close as possible to 500 ms before the new second starts.
         */
+       read_lock (&xtime_lock); 
        if ((time_status & STA_UNSYNC) == 0 &&
            xtime.tv_sec > last_rtc_update + 660 &&
            xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
-           xtime.tv_usec <= 500000 + ((unsigned) tick) / 2)
+           xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
          if (set_rtc_mmss(xtime.tv_sec) == 0)
            last_rtc_update = xtime.tv_sec;
          else
            last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+       }
        /* As we return to user mode fire off the other CPU schedulers.. this is 
           basically because we don't yet share IRQ's around. This message is
           rigged to be safe on the 386 - basically it's a hack, so don't look
           closely for now.. */
        /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
+       read_unlock (&xtime_lock); 
 }
 
-static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static inline void 
+r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        unsigned int count;
 
@@ -408,6+412,18 @@ static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        timerhi += (count < timerlo);   /* Wrap around */
        timerlo = count;
 
+#ifdef CONFIG_SGI_IP22
+       /* Since we don't get anything but r4k timer interrupts, we need to
+        * set this up so that we'll get one next time. Fortunately since we
+        * have timerhi/timerlo, we don't care so much if we miss one. So
+        * we need only ask for the next in r4k_interval counts. On other
+        * archs we have a real timer, so we don't want this.
+        */
+       write_32bit_cp0_register (CP0_COMPARE, 
+                                 (unsigned long) (count + r4k_interval));
+        kstat.irqs[0][irq]++;
+#endif
+
        timer_interrupt(irq, dev_id, regs);
 
        if (!jiffies)
@@ -421,6+437,12 @@ static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        }
 }
 
+void indy_r4k_timer_interrupt (struct pt_regs *regs)
+{
+       static const int INDY_R4K_TIMER_IRQ = 7;
+       r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
+}
+
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
@@ -500,7+522,7 @@ void (*board_time_init)(struct irqaction *irq);
 
 void __init time_init(void)
 {
-       unsigned int epoch, year, mon, day, hour, min, sec;
+       unsigned int epoch = 0, year, mon, day, hour, min, sec;
        int i;
 
        /* The Linux interpretation of the CMOS clock register contents:
@@ -543,8+565,10 @@ void __init time_init(void)
        }
        year += epoch;
 
+       write_lock_irq (&xtime_lock);
        xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
        xtime.tv_usec = 0;
+       write_unlock_irq (&xtime_lock);
 
        init_cycle_counter();
 
index 4972885..1d8bb4b 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko Exp $
- *
+/*
  * 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.
@@ -209,7+208,7 @@ extern void __die(const char * str, struct pt_regs * regs, const char *where,
                printk(" in %s, line %ld", where, line);
        printk(":\n");
        show_regs(regs);
-       printk("Process %s (pid: %ld, stackpage=%08lx)\n",
+       printk("Process %s (pid: %d, stackpage=%08lx)\n",
                current->comm, current->pid, (unsigned long) current);
        show_stack((unsigned int *) regs->regs[29]);
        show_trace((unsigned int *) regs->regs[29]);
@@ -230,7+229,7 @@ void __die_if_kernel(const char * str, struct pt_regs * regs, const char *where,
 extern const struct exception_table_entry __start___dbe_table[];
 extern const struct exception_table_entry __stop___dbe_table[];
 
-static void __declare_dbe_table(void)
+void __declare_dbe_table(void)
 {
        __asm__ __volatile__(
        ".section\t__dbe_table,\"a\"\n\t"
@@ -332,7+331,6 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                return;
        }
 #endif
-       lock_kernel();
        if (fcr31 & 0x20000) {
                /* Retry instruction with flush to zero ...  */
                if (!(fcr31 & (1<<24))) {
@@ -344,7+342,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                                "ctc1\t%0,$31"
                                : /* No outputs */
                                : "r" (fcr31));
-                       goto out;
+                       return;
                }
                pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
                if (get_user(insn, (unsigned int *)pc)) {
@@ -358,12+356,9 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        }
 
        if (compute_return_epc(regs))
-               goto out;
+               return;
        //force_sig(SIGFPE, current);
        printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
-
-out:
-       unlock_kernel();
 }
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -430,17+425,15 @@ void do_ri(struct pt_regs *regs)
 {
        unsigned int opcode;
 
-       lock_kernel();
        if (!get_insn_opcode(regs, &opcode)) {
                if ((opcode & OPCODE) == LL)
                        simulate_ll(regs, opcode);
                if ((opcode & OPCODE) == SC)
                        simulate_sc(regs, opcode);
        } else {
-       printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+       printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
               current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
        }
-       unlock_kernel();
        if (compute_return_epc(regs))
                return;
        force_sig(SIGILL, current);
@@ -526,10+519,8 @@ void simulate_sc(struct pt_regs *regp, unsigned int opcode)
 
 void do_ri(struct pt_regs *regs)
 {
-       lock_kernel();
-       printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+       printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
               current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
-       unlock_kernel();
        if (compute_return_epc(regs))
                return;
        force_sig(SIGILL, current);
index 6048472..844c83c 100644 (file)
        $(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS = csum_partial.o csum_partial_copy.o floppy-std.o \
-         floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
-         rtc-no.o memcpy.o memset.o strlen_user.o strncpy_user.o \
-         strnlen_user.o watch.o
+
+L_OBJS = csum_partial.o csum_partial_copy.o \
+          rtc-std.o rtc-no.o memcpy.o memset.o  watch.o\
+          strlen_user.o strncpy_user.o strnlen_user.o
 
 ifdef CONFIG_CPU_R3000
   L_OBJS += r3k_dump_tlb.o 
@@ -20,4+20,16 @@ else
   L_OBJS += dump_tlb.o 
 endif
 
+ifdef CONFIG_BLK_DEV_FD
+  L_OBJS += floppy-no.o floppy-std.o
+endif
+
+ifdef CONFIG_IDE
+  L_OBJS += ide-std.o ide-no.o
+endif
+
+ifdef CONFIG_PC_KEYB
+  L_OBJS += kbd-std.o kbd-no.o
+endif
+
 include $(TOPDIR)/Rules.make
index 34ee459..f6b6720 100644 (file)
@@ -47,7+47,7 @@ dump_tlb(int first, int last)
                        printk("Index: %2d ", i);
 
                        printk("va=%08lx asid=%08lx"
-                              "  [pa=%06lx n=%d d=%d v=%d g=%ld]",
+                              "  [pa=%06lx n=%d d=%d v=%d g=%d]",
                               (entryhi & 0xffffe000),
                               entryhi & 0xfc0,
                               entrylo0 & PAGE_MASK,
index e2d74fd..1d93088 100644 (file)
@@ -1,10+1,9 @@
-/* $Id: fault.c,v 1.15 2000/02/04 07:40:23 ralf Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
  */
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -47,9+46,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
        struct vm_area_struct * vma;
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       int si_code = SEGV_MAPERR;
        unsigned long fixup;
+       siginfo_t info;
 
+       info.si_code = SEGV_MAPERR;
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -75,7+75,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
  * we can handle it..
  */
 good_area:
-       si_code = SEGV_ACCERR;
+       info.si_code = SEGV_ACCERR;
 
        if (write) {
                if (!(vma->vm_flags & VM_WRITE))
@@ -114,7+114,6 @@ bad_area:
        up(&mm->mmap_sem);
 
        if (user_mode(regs)) {
-               struct siginfo si;
                tsk->thread.cp0_badvaddr = address;
                tsk->thread.error_code = write;
 #if 0
@@ -126,10+125,11 @@ bad_area:
                       (unsigned long) regs->cp0_epc,
                       (unsigned long) regs->regs[31]);
 #endif
-               si.si_signo = SIGSEGV;
-               si.si_code = si_code;
-               si.si_addr = (void *) address;
-               force_sig_info(SIGSEGV, &si, tsk);
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               /* info.si_code has been set above */
+               info.si_addr = (void *) address;
+               force_sig_info(SIGSEGV, &info, tsk);
                return;
        }
 
@@ -177,7+177,11 @@ do_sigbus:
         * or user mode.
         */
        tsk->thread.cp0_badvaddr = address;
-       force_sig(SIGBUS, tsk);
+       info.si_code = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = BUS_ADRERR;
+       info.si_addr = (void *) address;
+       force_sig_info(SIGBUS, &info, tsk);
 
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
index bc7a36d..b1fde51 100644 (file)
@@ -256,12+256,16 @@ void __init paging_init(void)
        max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
        low = max_low_pfn;
 
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
        if (low < max_dma)
                zones_size[ZONE_DMA] = low;
        else {
                zones_size[ZONE_DMA] = max_dma;
                zones_size[ZONE_NORMAL] = low - max_dma;
        }
+#else
+       zones_size[ZONE_DMA] = low;
+#endif
 
        free_area_init(zones_size);
 }
index 2e699b4..dcf1e8a 100644 (file)
@@ -151,15+151,15 @@ unsigned long __init r3k_cache_size(unsigned long ca_flags)
 
 static void __init probe_dcache(void)
 {
-       dcache_size = r3k_cache_size(ST0_DE);
+       dcache_size = r3k_cache_size(ST0_ISC);
        printk("Primary data cache %dkb, linesize 4 bytes\n",
                dcache_size >> 10);
 }
 
 static void __init probe_icache(void)
 {
-       icache_size = r3k_cache_size(ST0_DE|ST0_CE);
-       printk("Primary instruction cache %dkb, linesize 8 bytes\n",
+       icache_size = r3k_cache_size(ST0_ISC|ST0_SWC);
+       printk("Primary instruction cache %dkb, linesize 4 bytes\n",
                icache_size >> 10);
 }
 
@@ -174,43+174,43 @@ static void r3k_flush_icache_range(unsigned long start, unsigned long size)
        save_and_cli(flags);
 
        /* isolate cache space */
-       write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC);
+       write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
 
-       for (i = 0; i < size; i += 0x100) {
+       for (i = 0; i < size; i += 0x080) {
                asm (   "sb\t$0,0x000(%0)\n\t"
+                       "sb\t$0,0x004(%0)\n\t"
                        "sb\t$0,0x008(%0)\n\t"
+                       "sb\t$0,0x00c(%0)\n\t"
                        "sb\t$0,0x010(%0)\n\t"
+                       "sb\t$0,0x014(%0)\n\t"
                        "sb\t$0,0x018(%0)\n\t"
-                       "sb\t$0,0x020(%0)\n\t"
+                       "sb\t$0,0x01c(%0)\n\t"
+                       "sb\t$0,0x020(%0)\n\t"
+                       "sb\t$0,0x024(%0)\n\t"
                        "sb\t$0,0x028(%0)\n\t"
+                       "sb\t$0,0x02c(%0)\n\t"
                        "sb\t$0,0x030(%0)\n\t"
+                       "sb\t$0,0x034(%0)\n\t"
                        "sb\t$0,0x038(%0)\n\t"
-                       "sb\t$0,0x040(%0)\n\t"
+                       "sb\t$0,0x03c(%0)\n\t"
+                       "sb\t$0,0x040(%0)\n\t"
+                       "sb\t$0,0x044(%0)\n\t"
                        "sb\t$0,0x048(%0)\n\t"
+                       "sb\t$0,0x04c(%0)\n\t"
                        "sb\t$0,0x050(%0)\n\t"
+                       "sb\t$0,0x054(%0)\n\t"
                        "sb\t$0,0x058(%0)\n\t"
-                       "sb\t$0,0x060(%0)\n\t"
+                       "sb\t$0,0x05c(%0)\n\t"
+                       "sb\t$0,0x060(%0)\n\t"
+                       "sb\t$0,0x064(%0)\n\t"
                        "sb\t$0,0x068(%0)\n\t"
+                       "sb\t$0,0x06c(%0)\n\t"
                        "sb\t$0,0x070(%0)\n\t"
+                       "sb\t$0,0x074(%0)\n\t"
                        "sb\t$0,0x078(%0)\n\t"
-                       "sb\t$0,0x080(%0)\n\t"
-                       "sb\t$0,0x088(%0)\n\t"
-                       "sb\t$0,0x090(%0)\n\t"
-                       "sb\t$0,0x098(%0)\n\t"
-                       "sb\t$0,0x0a0(%0)\n\t"
-                       "sb\t$0,0x0a8(%0)\n\t"
-                       "sb\t$0,0x0b0(%0)\n\t"
-                       "sb\t$0,0x0b8(%0)\n\t"
-                       "sb\t$0,0x0c0(%0)\n\t"
-                       "sb\t$0,0x0c8(%0)\n\t"
-                       "sb\t$0,0x0d0(%0)\n\t"
-                       "sb\t$0,0x0d8(%0)\n\t"
-                       "sb\t$0,0x0e0(%0)\n\t"
-                       "sb\t$0,0x0e8(%0)\n\t"
-                       "sb\t$0,0x0f0(%0)\n\t"
-                       "sb\t$0,0x0f8(%0)\n\t"
+                       "sb\t$0,0x07c(%0)\n\t"
                        : : "r" (p) );
-               p += 0x100;
+               p += 0x080;
        }
 
        restore_flags(flags);
@@ -221,13+221,13 @@ static void r3k_flush_dcache_range(unsigned long start, unsigned long size)
        unsigned long i, flags;
        volatile unsigned char *p = (char *)start;
 
-       if (size > icache_size)
-               size = icache_size;
+       if (size > dcache_size)
+               size = dcache_size;
 
        save_and_cli(flags);
 
        /* isolate cache space */
-       write_32bit_cp0_register(CP0_STATUS, (ST0_DE|flags)&~ST0_IEC);
+       write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|flags)&~ST0_IEC);
 
        for (i = 0; i < size; i += 0x080) {
                asm (   "sb\t$0,0x000(%0)\n\t"
@@ -376,7+376,7 @@ static void r3k_flush_cache_sigtramp(unsigned long addr)
 
        save_and_cli(flags);
 
-       write_32bit_cp0_register(CP0_STATUS, (ST0_DE|ST0_CE|flags)&~ST0_IEC);
+       write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC);
 
        asm (   "sb\t$0,0x000(%0)\n\t"
                "sb\t$0,0x008(%0)\n\t"
index 2024e9d..003866a 100644 (file)
@@ -108,7+108,8 @@ remove_mapping (struct task_struct *task, unsigned long start, unsigned long end
 
 void *vmalloc_uncached (unsigned long size)
 {
-       return vmalloc_prot (size, PAGE_KERNEL_UNCACHED);
+       return __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM,
+                         PAGE_KERNEL_UNCACHED);
 }
 
 static inline void free_pte(pte_t page)
index 760e9fe..6eb3f17 100644 (file)
@@ -1,4+1,4 @@
-# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $
+#
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
 #
        $(CC) $(CFLAGS) -c $< -o $*.o
 
 OBJS  = indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o \
-        system.o indy_timer.o indyIRQ.o reset.o setup.o time.o
+        system.o indyIRQ.o reset.o setup.o time.o
 ifdef CONFIG_SGI_PROM_CONSOLE
 OBJS += promcon.o
 endif
index fd8e2a1..14d20f0 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $
+/*
  * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
  *            Guiness.
  *
 
        /* Wheee, a timer interrupt. */
        move    a0, sp
-       jal     indy_timer_interrupt
+       jal     indy_r4k_timer_interrupt
         nop                            # delay slot
 
        j       ret_from_irq
index f70d31d..afd52c3 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: setup.c,v 1.29 2000/01/27 01:05:23 ralf Exp $
- *
+/*
  * setup.c: SGI specific setup, including init of the feature struct.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
@@ -37,6+36,8 @@ static int remote_debug = 0;
 extern void console_setup(char *);
 #endif
 
+extern unsigned long r4k_interval; /* Cycle counter ticks per 1/HZ seconds */
+
 extern struct rtc_ops indy_rtc_ops;
 void indy_reboot_setup(void);
 void sgi_volume_set(unsigned char);
@@ -136,6+137,98 @@ int __init page_is_ram(unsigned long pagenr)
        return 0;
 }
 
+void (*board_time_init)(struct irqaction *irq);
+
+static unsigned long dosample(volatile unsigned char *tcwp,
+                              volatile unsigned char *tc2p)
+{
+        unsigned long ct0, ct1;
+        unsigned char msb, lsb;
+
+        /* Start the counter. */
+        *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN);
+        *tc2p = (SGINT_TCSAMP_COUNTER & 0xff);
+        *tc2p = (SGINT_TCSAMP_COUNTER >> 8);
+
+        /* Get initial counter invariant */
+        ct0 = read_32bit_cp0_register(CP0_COUNT);
+
+        /* Latch and spin until top byte of counter2 is zero */
+        do {
+                *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT);
+                lsb = *tc2p;
+                msb = *tc2p;
+                ct1 = read_32bit_cp0_register(CP0_COUNT);
+        } while(msb);
+
+        /* Stop the counter. */
+        *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST);
+
+        /* Return the difference, this is how far the r4k counter increments
+         * for every 1/HZ seconds. We round off the the nearest 1 MHz of
+        * master clock (= 1000000 / 100 / 2 = 5000 count).
+         */
+        return ((ct1 - ct0) / 5000) * 5000;
+}
+
+#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
+
+void sgi_time_init (struct irqaction *irq) {
+       /* Here we need to calibrate the cycle counter to at least be close.
+        * We don't need to actually register the irq handler because that's
+        * all done in indyIRQ.S.
+        */
+        struct sgi_ioc_timers *p;
+        volatile unsigned char *tcwp, *tc2p;
+       unsigned long r4k_ticks[3];
+       unsigned long r4k_next;
+
+        /* Figure out the r4k offset, the algorithm is very simple
+         * and works in _all_ cases as long as the 8254 counter
+         * register itself works ok (as an interrupt driving timer
+         * it does not because of bug, this is why we are using
+         * the onchip r4k counter/compare register to serve this
+         * purpose, but for r4k_offset calculation it will work
+         * ok for us).  There are other very complicated ways
+         * of performing this calculation but this one works just
+         * fine so I am not going to futz around. ;-)
+         */
+        p = ioc_timers;
+        tcwp = &p->tcword;
+        tc2p = &p->tcnt2;
+
+        printk("Calibrating system timer... ");
+        dosample(tcwp, tc2p);                   /* First sample. */
+        dosample(tcwp, tc2p);                   /* Eat one.     */
+        r4k_ticks[0] = dosample(tcwp, tc2p);      /* Second sample. */
+       dosample(tcwp, tc2p);                   /* Eat another. */
+       r4k_ticks[1] += dosample (tcwp, tc2p);  /* Third sample. */
+
+       if (r4k_ticks[0] != r4k_ticks[1]) {
+               printk ("warning: timer counts differ, retrying...");
+               dosample (tcwp, tc2p);
+               r4k_ticks[2] = dosample (tcwp, tc2p);
+               if (r4k_ticks[2] == r4k_ticks[0] 
+                   || r4k_ticks[2] == r4k_ticks[1])
+                       r4k_interval = r4k_ticks[2];
+               else {
+                       printk ("disagreement, using average...");
+                       r4k_interval = (r4k_ticks[0] + r4k_ticks[1] 
+                                       + r4k_ticks[2]) / 3;
+               }
+       } else
+               r4k_interval = r4k_ticks[0];
+
+        printk("%d [%d.%02d MHz CPU]\n", (int) r4k_interval, 
+               (int) (r4k_interval / 5000), (int) (r4k_interval % 5000) / 50);
+
+       /* Set ourselves up for future interrupts */
+        r4k_next = (read_32bit_cp0_register(CP0_COUNT) + r4k_interval);
+        write_32bit_cp0_register(CP0_COMPARE, r4k_next);
+        set_cp0_status(ST0_IM, ALLINTS);
+       sti ();
+}
+
 void __init sgi_setup(void)
 {
 #ifdef CONFIG_SERIAL_CONSOLE
@@ -147,6+240,7 @@ void __init sgi_setup(void)
 
 
        irq_setup = sgi_irq_setup;
+       board_time_init = sgi_time_init;
 
        /* Init the INDY HPC I/O controller.  Need to call this before
         * fucking with the memory controller because it needs to know the
@@ -229,5+323,5 @@ void __init sgi_setup(void)
 #ifdef CONFIG_VIDEO_VINO
        init_vino();
 #endif
+
 }
-__initcall(rs_init);
dissimilarity index 82%
index 355f1c4..ea85b75 100644 (file)
-/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $
- * time.c: Generic SGI time_init() code, this will dispatch to the
- *         appropriate per-architecture time/counter init code.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-#include <linux/init.h>
-
-extern void indy_timer_init(void);
-
-void __init time_init(void)
-{
-       /* XXX assume INDY for now XXX */
-       indy_timer_init();
-}
+/*
+ * time.c: Generic SGI handler for (spurious) 8254 interrupts
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <asm/sgialib.h>
+
+void indy_8254timer_irq(void)
+{
+        int cpu = smp_processor_id();
+        int irq = 4;
+
+        irq_enter(cpu);
+        kstat.irqs[0][irq]++;
+        printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
+        prom_getchar();
+        prom_imode();
+        irq_exit(cpu);
+}
index cfbc4b3..cd6a869 100644 (file)
-/* $Id: pci.c,v 1.9 1999/12/04 03:59:00 ralf Exp $
- *
+/*
  * 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.
  *
  * SNI specific PCI support for RM200/RM300.
  *
- * Copyright (C) 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1997 - 2000 Ralf Baechle
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/types.h>
 #include <asm/byteorder.h>
@@ -23,10+23,11 @@ do {                                                                         \
                return -1;                                                   \
        *(volatile u32 *)PCIMT_CONFIG_ADDRESS =                              \
                 ((dev->bus->number    & 0xff) << 0x10) |                    \
-                ((dev->dev_fn & 0xff) << 0x08) |                            \
+                ((dev->devfn & 0xff) << 0x08) |                             \
                 (where  & 0xfc);                                            \
 } while(0);
 
+#if 0
 /* To do:  Bring this uptodate ...  */
 static void pcimt_pcibios_fixup (void)
 {
@@ -62,6+63,7 @@ static void pcimt_pcibios_fixup (void)
                }
        }
 }
+#endif
 
 /*
  * We can't address 8 and 16 bit words directly.  Instead we have to
@@ -150,4+152,67 @@ struct pci_ops sni_pci_ops = {
        pcimt_write_config_dword
 };
 
+void __init
+pcibios_fixup_bus(struct pci_bus *b)
+{
+}
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                       struct resource *res, int resource)
+{
+       u32 new, check;
+       int reg;
+
+       new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+       if (resource < 6) {
+               reg = PCI_BASE_ADDRESS_0 + 4*resource;
+       } else if (resource == PCI_ROM_RESOURCE) {
+               res->flags |= PCI_ROM_ADDRESS_ENABLE;
+               new |= PCI_ROM_ADDRESS_ENABLE;
+               reg = dev->rom_base_reg;
+       } else {
+               /* Somebody might have asked allocation of a non-standard resource */
+               return;
+       }
+       
+       pci_write_config_dword(dev, reg, new);
+       pci_read_config_dword(dev, reg, &check);
+       if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+               printk(KERN_ERR "PCI: Error while updating region "
+                      "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+                      new, check);
+       }
+}
+
+void __init pcibios_init(void)
+{
+       struct pci_ops *ops = &sni_pci_ops;
+
+       pci_scan_bus(0, ops, NULL);
+}
+
+int __init pcibios_enable_device(struct pci_dev *dev)
+{
+       /* Not needed, since we enable all devices at startup.  */
+       return 0;
+}
+
+void __init
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+}
+
+char * __init
+pcibios_setup(char *str)
+{
+       /* Nothing to do for now.  */
+
+       return str;
+}
+
+struct pci_fixup pcibios_fixups[] = {
+       { 0 }
+};
+
 #endif /* CONFIG_PCI */
index 767e2fc..f174c7e 100644 (file)
-/* $Id: setup.c,v 1.13 1999/12/04 03:59:00 ralf Exp $
- *
+/*
  * Setup pointers to hardware-dependent routines.
  *
  * 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) 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
  */
 #include <asm/ptrace.h>
 #include <linux/config.h>
 #include <linux/console.h>
 #include <linux/fb.h>
 #include <linux/pc_keyb.h>
+#include <linux/ide.h>
 
 #include <asm/bcache.h>
 #include <asm/bootinfo.h>
 #include <asm/keyboard.h>
-#include <asm/ide.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/processor.h>
@@ -78,7+77,6 @@ static void __init sni_rm200_pci_time_init(struct irqaction *irq)
 }
 
 unsigned char aux_device_present;
-extern struct pci_ops sni_pci_ops;
 extern unsigned char sni_map_isa_cache;
 
 /*
@@ -110,6+108,7 @@ int __init page_is_ram(unsigned long pagenr)
 
 void __init sni_rm200_pci_setup(void)
 {
+#if 0 /* XXX Tag me deeper  */
        tag *atag;
 
        /*
@@ -135,6+134,7 @@ void __init sni_rm200_pci_setup(void)
                                ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
                }
        }
+#endif
 
        sni_pcimt_detect();
        sni_pcimt_sc_init();
@@ -168,7+168,6 @@ void __init sni_rm200_pci_setup(void)
         * the I/O port space ...
         */
        request_region(0xcfc,0x04,"PCI config data");
-       pci_ops = &sni_pci_ops;
 
 #ifdef CONFIG_BLK_DEV_IDE
        ide_ops = &std_ide_ops;
index 94cfc08..6b6c39c 100644 (file)
@@ -12,17+12,19 @@ TARGET      := $(TOPDIR)/include/asm-$(ARCH)/offset.h
 .S.o:
        $(CC) $(CFLAGS) -c $< -o $*.o
 
-all: $(TARGET)
-
 $(TARGET): offset.h
        cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
 
 offset.h: offset.s
        sed -n '/^@@@/s///p' $^ >$@
 
-offset.s: offset.c
+offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h
 
 clean:
        rm -f offset.[hs] $(TARGET).new
+       
+mrproper:      
+       rm -f offset.[hs] $(TARGET).new
+       rm -f $(TARGET)
 
 include $(TOPDIR)/Rules.make
index 218c22e..b37fabe 100644 (file)
@@ -86,8+86,12 @@ SUBDIRS       += arch/mips64/sgi-ip27 arch/mips64/arc
 # must be 16kb aligned or the handling of the current variable will break.
 #
 #LOADADDR      += 0xa80000000001c000
+ifdef CONFIG_MAPPED_KERNEL
+LOADADDR      += 0xc001c000
+else
 LOADADDR      += 0x8001c000
 endif
+endif
 
 #
 # Some machines like the Indy need 32-bit ELF binaries for booting purposes.
@@ -126,8+130,13 @@ else
 64bit-bfd = elf64-bigmips
 endif
 
+ifdef CONFIG_MAPPED_KERNEL
+vmlinux.64: vmlinux
+       $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@
+else
 vmlinux.64: vmlinux
        $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@
+endif
 
 zImage: vmlinux
        @$(MAKEBOOT) zImage
@@ -144,6+153,11 @@ archclean:
        rm -f vmlinux.64
 
 archmrproper:
+       @$(MAKEBOOT) mrproper
+       $(MAKE) -C arch/$(ARCH)/tools mrproper
 
 archdep:
+       if [ ! -f $(TOPDIR)/include/asm-$(ARCH)/offset.h ]; then \
+        touch $(TOPDIR)/include/asm-$(ARCH)/offset.h; \
+       fi;
        @$(MAKEBOOT) dep
index ab2d553..732d6db 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: identify.c,v 1.5 1999/11/19 20:35:21 ralf Exp $
- *
+/*
  * 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.
@@ -39,7+38,7 @@ static struct smatch mach_table[] = {
 int prom_flags;
 
 static struct smatch * __init
-string_to_mach(char *s)
+string_to_mach(const char *s)
 {
        int i;
     
index 58d4835..1e88dd6 100644 (file)
 
 #undef DEBUG
 
-extern char _end;
-
 struct linux_mdesc * __init
 ArcGetMemoryDescriptor(struct linux_mdesc *Current)
 {
index 0789186..5362f77 100644 (file)
@@ -38,6+38,9 @@ dep:
 clean:
        rm -f vmlinux.ecoff
 
+mrproper:
+       rm -f vmlinux.ecoff addinitrd elf2ecoff
+
 dummy:
 
 include $(TOPDIR)/Rules.make
index b940127..70e375f 100644 (file)
@@ -17,6+17,10 @@ bool 'Support for SGI IP27' CONFIG_SGI_IP27
 if [ "$CONFIG_SGI_IP27" = "y" ]; then
    bool '  IP27 N-Mode' CONFIG_SGI_SN0_N_MODE
    bool '  Discontiguous Memory Support' CONFIG_DISCONTIGMEM
+   bool '  NUMA support' CONFIG_NUMA
+   bool '  Mapped kernel support' CONFIG_MAPPED_KERNEL
+   bool '  Kernel text replication support' CONFIG_REPLICATE_KTEXT
+   bool '  Exception handler replication support' CONFIG_REPLICATE_EXHANDLERS
    bool '  Multi-Processing support (Experimental)' CONFIG_SMP
    #bool '  IP27 XXL' CONFIG_SGI_SN0_XXL
 fi
@@ -40,6+44,7 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then
    define_bool CONFIG_ARC32 y
    define_bool CONFIG_BOARD_SCACHE y
    define_bool CONFIG_ARC_MEMORY y
+   define_bool CONFIG_SGI y
 fi
 
 if [ "$CONFIG_SGI_IP27" = "y" ]; then
index cef645c..ba39829 100644 (file)
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
 # CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
 # CONFIG_SMP is not set
 CONFIG_BOOT_ELF64=y
 CONFIG_ARC64=y
@@ -53,12+57,15 @@ CONFIG_BINFMT_ELF32=y
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
 CONFIG_PCI_NAMES=y
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -66,16+73,14 @@ CONFIG_PCI_NAMES=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -110,6+115,7 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 
 #
 # Telephony Support
@@ -308,6+314,7 @@ CONFIG_SERIAL_CONSOLE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
@@ -342,6+349,7 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
@@ -420,6+428,5 @@ CONFIG_KCORE_ELF=y
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
-# CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_REMOTE_DEBUG is not set
 # CONFIG_MAGIC_SYSRQ is not set
index 85e7ace..ef422eb 100644 (file)
@@ -16,6+16,7 @@ CONFIG_BOOT_ELF32=y
 CONFIG_ARC32=y
 CONFIG_BOARD_SCACHE=y
 CONFIG_ARC_MEMORY=y
+CONFIG_SGI=y
 # CONFIG_ISA is not set
 # CONFIG_PCI is not set
 # CONFIG_SBUS is not set
@@ -50,6+51,11 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_MODULES is not set
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -57,16+63,14 @@ CONFIG_BINFMT_ELF=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -101,6+105,7 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 
 #
 # Telephony Support
@@ -228,6+233,7 @@ CONFIG_VT_CONSOLE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
@@ -262,6+268,7 @@ CONFIG_VT_CONSOLE=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
index cef645c..ba39829 100644 (file)
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
 # CONFIG_DISCONTIGMEM is not set
+# CONFIG_NUMA is not set
+# CONFIG_MAPPED_KERNEL is not set
+# CONFIG_REPLICATE_KTEXT is not set
+# CONFIG_REPLICATE_EXHANDLERS is not set
 # CONFIG_SMP is not set
 CONFIG_BOOT_ELF64=y
 CONFIG_ARC64=y
@@ -53,12+57,15 @@ CONFIG_BINFMT_ELF32=y
 #
 # Loadable module support
 #
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+# CONFIG_MODULES is not set
 CONFIG_PCI_NAMES=y
 
 #
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -66,16+73,14 @@ CONFIG_PCI_NAMES=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-
-#
-# Additional Block Devices
-#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -110,6+115,7 @@ CONFIG_SKB_LARGE=y
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 
 #
 # Telephony Support
@@ -308,6+314,7 @@ CONFIG_SERIAL_CONSOLE=y
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
@@ -342,6+349,7 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
@@ -420,6+428,5 @@ CONFIG_KCORE_ELF=y
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
-# CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_REMOTE_DEBUG is not set
 # CONFIG_MAGIC_SYSRQ is not set
index e1edfc6..e6ed31c 100644 (file)
 #
 
 .S.o:
-       $(CC) $(CFLAGS) -c $< -o $*.o
+       $(CC) $(CFLAGS) $(CFLAGS_$@) -c $< -o $*.o
 
 all:   kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
 O_OBJS := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \
-          r4k_genex.o r4k_switch.o r4k_tlb_debug.o r4k_tlb_glue.o scall_64.o \
-          semaphore.o setup.o signal.o softfp.o syscall.o traps.o unaligned.o
+          r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \
+          scall_64.o semaphore.o setup.o signal.o softfp.o syscall.o \
+          traps.o unaligned.o
 OX_OBJS := mips64_ksyms.o
 
 ifdef CONFIG_MIPS32_COMPAT
@@ -29,6+30,9 @@ ifdef CONFIG_SMP
 O_OBJS += smp.o
 endif
 
+CFLAGS_r4k_genex.o := -P
+CFLAGS_r4k_tlb_glue.o := -P
+
 clean:
 
 include $(TOPDIR)/Rules.make
index cc19d31..c7c4744 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/processor.h>
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
+#include <asm/pgtable.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn0/hubni.h>
+#include <asm/sn/klkernvars.h>
+
+       .macro  ARC64_TWIDDLE_PC
+#if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL)
+       /* We get launched at a XKPHYS address but the kernel is linked to
+          run at a KSEG0 address, so jump there.  */
+       la      t0, \@f
+       jr      t0
+\@:
+#endif
+       .endm
 
-#define ARC64_TWIDDLE_PC \
-#ifdef CONFIG_ARC64 \
-       /* We get launched at a XKPHYS address but the kernel is linked to \
-          run at a KSEG0 address, so jump there.  */ \
-       la      t0, 1f \
-       jr      t0 \
-1: \
+       /*
+        * outputs the local nasid into t1.
+        */
+       .macro GET_NASID_ASM
+       dli     t1, LOCAL_HUB_ADDR(NI_STATUS_REV_ID)
+       ld      t1, (t1)
+       and     t1, NSRI_NODEID_MASK
+       dsrl    t1, NSRI_NODEID_SHFT
+       .endm
+
+       /*
+        * inputs are the text nasid in t1, data nasid in t2.
+        */
+       .macro MAPPED_KERNEL_SETUP_TLB
+#ifdef CONFIG_MAPPED_KERNEL
+       /*
+        * This needs to read the nasid - assume 0 for now.
+        * Drop in 0xffffffffc0000000 in tlbhi, 0+VG in tlblo_0,
+        * 0+DVG in tlblo_1.
+        */
+       dli     t0, 0xffffffffc0000000
+       dmtc0   t0, CP0_ENTRYHI
+       li      t0, 0x1c000             # Offset of text into node memory
+       dsll    t1, NASID_SHFT          # Shift text nasid into place
+       dsll    t2, NASID_SHFT          # Same for data nasid
+       or      t1, t1, t0              # Physical load address of kernel text
+       or      t2, t2, t0              # Physical load address of kernel data
+       dsrl    t1, 12                  # 4K pfn
+       dsrl    t2, 12                  # 4K pfn
+       dsll    t1, 6                   # Get pfn into place
+       dsll    t2, 6                   # Get pfn into place
+       li      t0, ((_PAGE_GLOBAL|_PAGE_VALID| _CACHE_CACHABLE_COW) >> 6)
+       or      t0, t0, t1
+       mtc0    t0, CP0_ENTRYLO0        # physaddr, VG, cach exlwr
+       li      t0, ((_PAGE_GLOBAL|_PAGE_VALID| _PAGE_DIRTY|_CACHE_CACHABLE_COW) >> 6)
+       or      t0, t0, t2
+       mtc0    t0, CP0_ENTRYLO1        # physaddr, DVG, cach exlwr
+       li      t0, 0x1ffe000           # MAPPED_KERN_TLBMASK, TLBPGMASK_16M
+       mtc0    t0, CP0_PAGEMASK
+       li      t0, 0                   # KMAP_INX
+       mtc0    t0, CP0_INDEX
+       li      t0, 1
+       mtc0    t0, CP0_WIRED
+       tlbwi
+#else
+       mtc0    zero, CP0_WIRED
 #endif
+       .endm
 
        .text
 
@@ -38,11+91,15 @@ EXPORT(_stext)
 
 NESTED(kernel_entry, 16, sp)                   # kernel entry point
 
-       ARC64_TWIDDLE_PC
-
        ori     sp, 0xf                         # align stack on 16 byte.
        xori    sp, 0xf
 
+       GET_NASID_ASM
+       move    t2, t1                          # text and data are here
+       MAPPED_KERNEL_SETUP_TLB
+
+       ARC64_TWIDDLE_PC
+
        /* Note that all firmware passed argument registers still
           have their values.  */
        jal     prom_init                       # initialize firmware
@@ -75,6+132,14 @@ NESTED(kernel_entry, 16, sp)                        # kernel entry point
        END(kernel_entry)
 
 NESTED(bootstrap, 16, sp)
+       GET_NASID_ASM
+       li      t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + KLDIR_OFF_POINTER + K0BASE
+       dsll    t1, NASID_SHFT
+       or      t0, t0, t1
+       ld      t0, 0(t0)                       # t0 points to kern_vars struct
+       lh      t1, KV_RO_NASID_OFFSET(t0)
+       lh      t2, KV_RW_NASID_OFFSET(t0)
+       MAPPED_KERNEL_SETUP_TLB
        ARC64_TWIDDLE_PC
        CLI
        mfc0    t0, CP0_STATUS
@@ -89,20+154,25 @@ NESTED(bootstrap, 16, sp)
 
        .comm   kernelsp, 8, 8                  # current stackpointer
 
+#undef PAGE_SIZE
 #define PAGE_SIZE      0x1000
 
        .macro  page name, order=0
        .globl  \name
-       .org    . + (PAGE_SIZE << \order)
 \name: .size   \name, (PAGE_SIZE << \order)
+       .org    . + (PAGE_SIZE << \order)
        .type   \name, @object
        .endm
 
-       .align  12
        .data
+       .align  12
 
        page    swapper_pg_dir, 1
-       page    invalid_pte_table, 1
+       page    invalid_pte_table, 0
        page    invalid_pmd_table, 1
-       page    empty_bad_page_table, 1
-       page    empty_bad_page
+       page    empty_bad_page_table, 0
+       page    empty_bad_pmd_table, 1
+       page    kptbl, KPTBL_PAGE_ORDER
+       .globl  ekptbl
+       page    kpmdtbl, 0
+ekptbl:
index 45c9cf5..8717486 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: ioctl32.c,v 1.1 2000/04/05 00:43:25 ulfc Exp $
+/*
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 2000 Silicon Graphics, Inc.
@@ -35,23+35,6 @@ struct timeval32 {
 #define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
 #define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
 
-static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-       struct timeval32 *up = (struct timeval32 *)arg;
-       struct timeval ktv;
-       mm_segment_t old_fs = get_fs();
-       int err;
-
-       set_fs(KERNEL_DS);
-       err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
-       set_fs(old_fs);
-       if(!err) {
-               err = put_user(ktv.tv_sec, &up->tv_sec);
-               err |= __put_user(ktv.tv_usec, &up->tv_usec);
-       }
-       return err;
-}
-
 struct ifmap32 {
        unsigned int mem_start;
        unsigned int mem_end;
index 10ddb58..70746da 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: linux32.c,v 1.14 2000/03/23 00:30:53 ulfc Exp $
- * 
+/* 
  * Conversion between 32-bit and 64-bit native system calls.
  *
  * Copyright (C) 2000 Silicon Graphics, Inc.
 #include <linux/time.h>
 #include <linux/poll.h>
 #include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/filter.h>
 
 #include <asm/uaccess.h>
 #include <asm/mman.h>
 
 #define A(__x) ((unsigned long)(__x))
 
-#if 1
-static inline int
-putstat(struct stat32 *ubuf, struct stat *kbuf)
-{
-       int err;
-       
-       err = put_user (kbuf->st_dev, &ubuf->st_dev);
-       err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
-       err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
-       err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
-       err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
-       err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
-       err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
-       err |= __put_user (kbuf->st_size, &ubuf->st_size);
-       err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
-       err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
-       err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
-       err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
-       err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
-       return err;
-}
-
-extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
-
-asmlinkage int
-sys32_newstat(char * filename, struct stat32 *statbuf)
-{
-       int ret;
-       struct stat s;
-       mm_segment_t old_fs = get_fs();
-       
-       set_fs (KERNEL_DS);
-       ret = sys_newstat(filename, &s);
-       set_fs (old_fs);
-       if (putstat (statbuf, &s))
-               return -EFAULT;
-       return ret;
-}
-
-extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
-
-asmlinkage int
-sys32_newlstat(char * filename, struct stat32 *statbuf)
-{
-       int ret;
-       struct stat s;
-       mm_segment_t old_fs = get_fs();
-       
-       set_fs (KERNEL_DS);
-       ret = sys_newlstat(filename, &s);
-       set_fs (old_fs);
-       if (putstat (statbuf, &s))
-               return -EFAULT;
-       return ret;
-}
-
-extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
-
-asmlinkage int
-sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
-{
-       int ret;
-       struct stat s;
-       mm_segment_t old_fs = get_fs();
-       
-       set_fs (KERNEL_DS);
-       ret = sys_newfstat(fd, &s);
-       set_fs (old_fs);
-       if (putstat (statbuf, &s))
-               return -EFAULT;
-       return ret;
-}
-#else
 /*
  * Revalidate the inode. This is required for proper NFS attribute caching.
  */
@@ -105,8+33,10 @@ static __inline__ int
 do_revalidate(struct dentry *dentry)
 {
        struct inode * inode = dentry->d_inode;
+
        if (inode->i_op && inode->i_op->revalidate)
                return inode->i_op->revalidate(dentry);
+
        return 0;
 }
 
@@ -127,21+57,22 @@ static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
        tmp.st_atime = inode->i_atime;
        tmp.st_mtime = inode->i_mtime;
        tmp.st_ctime = inode->i_ctime;
-/*
- * st_blocks and st_blksize are approximated with a simple algorithm if
- * they aren't supported directly by the filesystem. The minix and msdos
- * filesystems don't keep track of blocks, so they would either have to
- * be counted explicitly (by delving into the file itself), or by using
- * this simple algorithm to get a reasonable (although not 100% accurate)
- * value.
- */
 
-/*
- * Use minix fs values for the number of direct and indirect blocks.  The
- * count is now exact for the minix fs except that it counts zero blocks.
- * Everything is in units of BLOCK_SIZE until the assignment to
- * tmp.st_blksize.
- */
+       /*
+        * st_blocks and st_blksize are approximated with a simple algorithm if
+        * they aren't supported directly by the filesystem. The minix and msdos
+        * filesystems don't keep track of blocks, so they would either have to
+        * be counted explicitly (by delving into the file itself), or by using
+        * this simple algorithm to get a reasonable (although not 100%
+        * accurate) value.
+        */
+
+       /*
+        * Use minix fs values for the number of direct and indirect blocks.
+        * The count is now exact for the minix fs except that it counts zero
+        * blocks.  Everything is in units of BLOCK_SIZE until the assignment
+        * to tmp.st_blksize.
+        */
 #define D_B   7
 #define I_B   (BLOCK_SIZE / sizeof(unsigned short))
 
@@ -163,53+94,49 @@ static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
                tmp.st_blocks = inode->i_blocks;
                tmp.st_blksize = inode->i_blksize;
        }
+
        return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
 }
+
 asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
-       struct dentry * dentry;
+       struct nameidata nd;
        int error;
 
-       lock_kernel();
-       dentry = namei(filename);
-
-       error = PTR_ERR(dentry);
-       if (!IS_ERR(dentry)) {
-               error = do_revalidate(dentry);
+       error = user_path_walk(filename, &nd);
+       if (!error) {
+               error = do_revalidate(nd.dentry);
                if (!error)
-                       error = cp_new_stat32(dentry->d_inode, statbuf);
+                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
 
-               dput(dentry);
+               path_release(&nd);
        }
-       unlock_kernel();
+
        return error;
 }
-asmlinkage int sys32_newlstat(char *filename, struct stat32 * statbuf)
+
+asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
-       struct dentry * dentry;
+       struct nameidata nd;
        int error;
 
-       lock_kernel();
-       dentry = lnamei(filename);
-
-       error = PTR_ERR(dentry);
-       if (!IS_ERR(dentry)) {
-               error = do_revalidate(dentry);
+       error = user_path_walk_link(filename, &nd);
+       if (!error) {
+               error = do_revalidate(nd.dentry);
                if (!error)
-                       error = cp_new_stat32(dentry->d_inode, statbuf);
+                       error = cp_new_stat32(nd.dentry->d_inode, statbuf);
 
-               dput(dentry);
+               path_release(&nd);
        }
-       unlock_kernel();
+
        return error;
 }
 
-asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
+asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
 {
        struct file * f;
        int err = -EBADF;
 
-       lock_kernel();
        f = fget(fd);
        if (f) {
                struct dentry * dentry = f->f_dentry;
@@ -219,10+146,10 @@ asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
                        err = cp_new_stat32(dentry->d_inode, statbuf);
                fput(f);
        }
-       unlock_kernel();
+
        return err;
 }
-#endif
+
 asmlinkage int sys_mmap2(void) {return 0;}
 
 asmlinkage long sys_truncate(const char * path, unsigned long length);
@@ -232,7+159,7 @@ asmlinkage int sys_truncate64(const char *path, unsigned int high,
 {
        if ((int)high < 0)
                return -EINVAL;
-       return sys_truncate(path, (high << 32) | low);
+       return sys_truncate(path, ((long) high << 32) | low);
 }
 
 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
@@ -242,28+169,7 @@ asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
 {
        if ((int)high < 0)
                return -EINVAL;
-       return sys_ftruncate(fd, (high << 32) | low);
-}
-
-asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
-
-asmlinkage int sys_stat64(char * filename, struct stat *statbuf)
-{
-       return sys_newstat(filename, statbuf);
-}
-
-asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
-
-asmlinkage int sys_lstat64(char * filename, struct stat *statbuf)
-{
-       return sys_newlstat(filename, statbuf);
-}
-
-asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
-
-asmlinkage int sys_fstat64(unsigned int fd, struct stat *statbuf)
-{
-       return sys_newfstat(fd, statbuf);
+       return sys_ftruncate(fd, ((long) high << 32) | low);
 }
 
 #if 0
@@ -304,7+210,8 @@ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
                int len;
                unsigned long pos;
 
-               if (get_user(str, argv+argc) || !str || !(len = strnlen_user((char *)A(str), bprm->p))) 
+               if (get_user(str, argv+argc) || !str ||
+                    !(len = strnlen_user((char *)A(str), bprm->p))) 
                        return -EFAULT;
                if (bprm->p < len) 
                        return -E2BIG; 
@@ -338,9+245,11 @@ int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
                        if (bytes_to_copy > len) {
                                bytes_to_copy = len;
                                if (new)
-                                       memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);
+                                       memset(kaddr+offset+len, 0,
+                                              PAGE_SIZE-offset-len);
                        }
-                       err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy);
+                       err = copy_from_user(kaddr + offset, (char *)A(str),
+                                            bytes_to_copy);
                        flush_page_to_ram(page);
                        kunmap(page);
 
@@ -970,7+879,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
        tot_len = 0;
        i = count;
        ivp = iov;
-       while(i > 0) {
+       while (i > 0) {
                u32 len;
                u32 buf;
 
@@ -1038,6+947,7 @@ do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
        }
        if (iov != iovstack)
                kfree(iov);
+
        return retval;
 }
 
@@ -1045,22+955,19 @@ asmlinkage long
 sys32_readv(int fd, struct iovec32 *vector, u32 count)
 {
        struct file *file;
-       long ret = -EBADF;
+       ssize_t ret;
 
-       lock_kernel();
+       ret = -EBADF;
        file = fget(fd);
-       if(!file)
+       if (!file)
                goto bad_file;
+       if (file->f_op && (file->f_mode & FMODE_READ) &&
+           (file->f_op->readv || file->f_op->read))
+               ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
 
-       if(!(file->f_mode & 1))
-               goto out;
-
-       ret = do_readv_writev32(VERIFY_WRITE, file,
-                               vector, count);
-out:
        fput(file);
+
 bad_file:
-       unlock_kernel();
        return ret;
 }
 
@@ -1068,22+975,18 @@ asmlinkage long
 sys32_writev(int fd, struct iovec32 *vector, u32 count)
 {
        struct file *file;
-       int ret = -EBADF;
+       ssize_t ret;
 
-       lock_kernel();
+       ret = -EBADF;
        file = fget(fd);
        if(!file)
                goto bad_file;
-
-       if(!(file->f_mode & 2))
-               goto out;
-
-       ret = do_readv_writev32(VERIFY_READ, file,
-                               vector, count);
-out:
+       if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+           (file->f_op->writev || file->f_op->write))
+               ret = do_readv_writev32(VERIFY_READ, file, vector, count);
        fput(file);
+
 bad_file:
-       unlock_kernel();
        return ret;
 }
 
@@ -1303,3+1206,134 @@ sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
        }
        return ret;
 }
+
+struct tms32 {
+       int tms_utime;
+       int tms_stime;
+       int tms_cutime;
+       int tms_cstime;
+};
+
+extern asmlinkage long sys_times(struct tms * tbuf);
+asmlinkage long sys32_times(struct tms32 *tbuf)
+{
+       struct tms t;
+       long ret;
+       mm_segment_t old_fs = get_fs();
+       int err;
+
+       set_fs(KERNEL_DS);
+       ret = sys_times(tbuf ? &t : NULL);
+       set_fs(old_fs);
+       if (tbuf) {
+               err = put_user (t.tms_utime, &tbuf->tms_utime);
+               err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+               err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+               err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+               if (err)
+                       ret = -EFAULT;
+       }
+       return ret;
+}
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+                                    char *optval, int optlen);
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+                               char *optval, int optlen)
+{
+       if (optname == SO_ATTACH_FILTER) {
+               struct sock_fprog32 {
+                       __u16 len;
+                       __u32 filter;
+               } *fprog32 = (struct sock_fprog32 *)optval;
+               struct sock_fprog kfprog;
+               struct sock_filter *kfilter;
+               unsigned int fsize;
+               mm_segment_t old_fs;
+               __u32 uptr;
+               int ret;
+
+               if (get_user(kfprog.len, &fprog32->len) ||
+                   __get_user(uptr, &fprog32->filter))
+                       return -EFAULT;
+               kfprog.filter = (struct sock_filter *)A(uptr);
+               fsize = kfprog.len * sizeof(struct sock_filter);
+               kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+               if (kfilter == NULL)
+                       return -ENOMEM;
+               if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+                       kfree(kfilter);
+                       return -EFAULT;
+               }
+               kfprog.filter = kfilter;
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               ret = sys_setsockopt(fd, level, optname,
+                                    (char *)&kfprog, sizeof(kfprog));
+               set_fs(old_fs);
+               kfree(kfilter);
+               return ret;
+       }
+       return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+struct flock32 {
+       short l_type;
+       short l_whence;
+       __kernel_off_t32 l_start;
+       __kernel_off_t32 l_len;
+       __kernel_pid_t32 l_pid;
+       short __unused;
+};
+
+static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+       int err;
+       
+       err = get_user(kfl->l_type, &ufl->l_type);
+       err |= __get_user(kfl->l_whence, &ufl->l_whence);
+       err |= __get_user(kfl->l_start, &ufl->l_start);
+       err |= __get_user(kfl->l_len, &ufl->l_len);
+       err |= __get_user(kfl->l_pid, &ufl->l_pid);
+       return err;
+}
+
+static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+       int err;
+       
+       err = __put_user(kfl->l_type, &ufl->l_type);
+       err |= __put_user(kfl->l_whence, &ufl->l_whence);
+       err |= __put_user(kfl->l_start, &ufl->l_start);
+       err |= __put_user(kfl->l_len, &ufl->l_len);
+       err |= __put_user(kfl->l_pid, &ufl->l_pid);
+       return err;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case F_GETLK:
+       case F_SETLK:
+       case F_SETLKW:
+               {
+                       struct flock f;
+                       mm_segment_t old_fs;
+                       long ret;
+                       
+                       if(get_flock(&f, (struct flock32 *)arg))
+                               return -EFAULT;
+                       old_fs = get_fs(); set_fs (KERNEL_DS);
+                       ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+                       set_fs (old_fs);
+                       if(put_flock(&f, (struct flock32 *)arg))
+                               return -EFAULT;
+                       return ret;
+               }
+       default:
+               return sys_fcntl(fd, cmd, (unsigned long)arg);
+       }
+}
index 5b77f30..c65f058 100644 (file)
-/* $Id: mips64_ksyms.c,v 1.8 2000/02/24 00:12:41 ralf Exp $
- *
+/*
  * Export MIPS64-specific functions needed for loadable modules.
  *
  * 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) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/in6.h>
 #include <linux/pci.h>
 
-#include <asm/checksum.h>
 #include <asm/dma.h>
 #include <asm/floppy.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/softirq.h>
 #include <asm/uaccess.h>
+#include <asm/checksum.h>
 
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_user_nocheck_asm(char *__to,
index b8a0b32..22ce0ed 100644 (file)
@@ -7,6+7,7 @@
  * Copyright (C) 1994 - 1999 by Ralf Baechle and others.
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
index a048810..579fc88 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: ptrace.c,v 1.1 1999/12/04 03:59:00 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-/* Tracing a 32-bit process with a 64-bit strace and vice verca will not
-   work.  I don't know how to fix this.  */
-
+/*
+ * Tracing a 32-bit process with a 64-bit strace and vice versa will not
+ * work.  I don't know how to fix this.
+ */
 asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
 {
        struct task_struct *child;
        int ret;
 
        lock_kernel();
-#if 0
-       printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
-              (int) request, (int) pid, (unsigned long) addr,
-              (unsigned long) data);
-#endif
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -79,9+74,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out_tsk;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out_tsk;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irq(&tasklist_lock);
                if (child->p_pptr != current) {
@@ -96,7+91,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                goto out_tsk;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out_tsk;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -104,7+99,6 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
        }
        if (child->p_pptr != current)
                goto out_tsk;
-
        switch (request) {
        /* when I and D space are separate, these will need to be fixed. */
        case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -116,7+110,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                ret = -EIO;
                if (copied != sizeof(tmp))
                        break;
-               ret = put_user(tmp, (unsigned int *) data);
+               ret = put_user(tmp, (unsigned int *) (unsigned long) data);
                break;
        }
 
@@ -179,7+173,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                        ret = -EIO;
                        goto out_tsk;
                }
-               ret = put_user(tmp, (unsigned *) data);
+               ret = put_user(tmp, (unsigned *) (unsigned long) data);
                break;
                }
        /* when I and D space are separate, this will have to be fixed. */
@@ -248,9+242,9 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                if ((unsigned int) data > _NSIG)
                        break;
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                wake_up_process(child);
                ret = 0;
@@ -274,7+268,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        break;
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                child->exit_code = data;
                write_lock_irq(&tasklist_lock);
                REMOVE_LINKS(child);
@@ -312,10+306,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
        ret = -EPERM;
        if (request == PTRACE_TRACEME) {
                /* are we already being traced? */
-               if (current->flags & PF_PTRACED)
+               if (current->ptrace & PT_PTRACED)
                        goto out;
                /* set the ptrace bit in the process flags. */
-               current->flags |= PF_PTRACED;
+               current->ptrace |= PT_PTRACED;
                ret = 0;
                goto out;
        }
@@ -345,9+339,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out_tsk;
                /* the same process cannot be attached many times */
-               if (child->flags & PF_PTRACED)
+               if (child->ptrace & PT_PTRACED)
                        goto out_tsk;
-               child->flags |= PF_PTRACED;
+               child->ptrace |= PT_PTRACED;
 
                write_lock_irq(&tasklist_lock);
                if (child->p_pptr != current) {
@@ -362,7+356,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                goto out_tsk;
        }
        ret = -ESRCH;
-       if (!(child->flags & PF_PTRACED))
+       if (!(child->ptrace & PT_PTRACED))
                goto out_tsk;
        if (child->state != TASK_STOPPED) {
                if (request != PTRACE_KILL)
@@ -514,9+508,9 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                if ((unsigned long) data > _NSIG)
                        break;
                if (request == PTRACE_SYSCALL)
-                       child->flags |= PF_TRACESYS;
+                       child->ptrace |= PT_TRACESYS;
                else
-                       child->flags &= ~PF_TRACESYS;
+                       child->ptrace &= ~PT_TRACESYS;
                child->exit_code = data;
                wake_up_process(child);
                ret = 0;
@@ -540,7+534,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                ret = -EIO;
                if ((unsigned long) data > _NSIG)
                        break;
-               child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+               child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
                child->exit_code = data;
                write_lock_irq(&tasklist_lock);
                REMOVE_LINKS(child);
@@ -566,9+560,10 @@ out:
 
 asmlinkage void syscall_trace(void)
 {
-       if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-                       != (PF_PTRACED|PF_TRACESYS))
+       if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+           != (PT_PTRACED|PT_TRACESYS))
                return;
+
        current->exit_code = SIGTRAP;
        current->state = TASK_STOPPED;
        notify_parent(current, SIGCHLD);
diff --git a/arch/mips64/kernel/r4k_tlb.S b/arch/mips64/kernel/r4k_tlb.S
new file mode 100644 (file)
index 0000000..2a77eb9
--- /dev/null
@@ -0,0 +1,133 @@
+/* $Id: r4k_tlb.S,v 1.3 2000/06/30 00:48:29 kanoj Exp $
+ *
+ * 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) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ */
+#include <linux/threads.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/stackframe.h>
+
+       .data
+       .comm   pgd_current, NR_CPUS * 8, 8
+
+       /*
+        * After this macro runs we have a pointer to the pte of the address
+        * that caused the fault in in PTR.
+        */
+
+       .macro  LOAD_PTE2, ptr, tmp
+#ifdef CONFIG_SMP
+       mfc0    \tmp, CP0_CONTEXT
+       dla     \ptr, pgd_current
+       dsrl    \tmp, 23
+       daddu   \ptr, \tmp
+#else
+       dla     \ptr, pgd_current
+#endif
+       dmfc0   \tmp, CP0_BADVADDR
+       ld      \ptr, (\ptr)
+       bltz    \tmp, kaddr
+        dsrl   \tmp, (PGDIR_SHIFT-3)           # get pgd offset in bytes
+       andi    \tmp, ((PTRS_PER_PGD - 1)<<3)
+       daddu   \ptr, \tmp                      # add in pgd offset
+       dmfc0   \tmp, CP0_BADVADDR
+       ld      \ptr, (\ptr)                    # get pmd pointer
+       dsrl    \tmp, (PMD_SHIFT-3)             # get pmd offset in bytes
+       andi    \tmp, ((PTRS_PER_PMD - 1)<<3)
+       daddu   \ptr, \tmp                      # add in pmd offset
+       dmfc0   \tmp, CP0_XCONTEXT
+       ld      \ptr, (\ptr)                    # get pte pointer
+       andi    \tmp, 0xff0                     # get pte offset
+       daddu   \ptr, \tmp
+       .endm
+
+       /*
+        * This places the even/odd pte pair in the page table at the pte
+        * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1.
+        */
+       .macro  PTE_RELOAD, pte0, pte1
+       dsrl    \pte0, 6                        # convert to entrylo0
+       dmtc0   \pte0, CP0_ENTRYLO0             # load it
+       dsrl    \pte1, 6                        # convert to entrylo1
+       dmtc0   \pte1, CP0_ENTRYLO1             # load it
+       .endm
+
+       .text
+       .set    noreorder
+       .set    mips3
+
+       .align  5
+FEXPORT(except_vec0)
+       .set    noat
+1:     b       1b
+        nop
+
+       /* TLB refill handler for the R10000.
+        * Attention:  We may only use 32 instructions.
+        */
+
+       .align  5
+FEXPORT(except_vec1_r10k)
+       .set    noat
+       LOAD_PTE2 k1 k0
+       ld      k0, 0(k1)                       # get even pte
+       ld      k1, 8(k1)                       # get odd pte
+       PTE_RELOAD k0 k1
+       nop
+       tlbwr
+       eret
+kaddr:
+       dla     k0, handle_vmalloc_address      # MAPPED kernel needs this
+       jr      k0
+        nop
+
+       .align  5
+FEXPORT(handle_vmalloc_address)
+       .set    noat
+       /*
+        * First, determine that the address is in/above vmalloc range.
+        */
+       dmfc0   k0, CP0_BADVADDR
+       dli     k1, VMALLOC_START
+       sltu    k1, k0, k1
+       bne     k1, zero, not_vmalloc
+        dli    k1, VMALLOC_START
+
+       /*
+        * Now find offset into kptbl.
+        */
+       dsubu   k0, k0, k1
+       dla     k1, kptbl
+       dsrl    k0, (PAGE_SHIFT+1)              # get vpn2
+       dsll    k0, 4                           # byte offset of pte
+       daddu   k1, k1, k0
+
+       /*
+        * Determine that fault address is within vmalloc range.
+        */
+       dla     k0, ekptbl
+       sltu    k0, k1, k0
+       beq     k0, zero, not_vmalloc
+
+       /*
+        * Load cp0 registers.
+        */
+       ld      k0, 0(k1)                       # get even pte
+       ld      k1, 8(k1)                       # get odd pte
+1:
+       PTE_RELOAD k0 k1
+       nop
+       tlbwr
+       eret
+not_vmalloc:
+       daddu   k0, zero, zero
+       daddu   k1, zero, zero
+       j       1b
+       nop
index 7cf1544..a59b977 100644 (file)
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
-       __INIT
-NESTED(__xtlb_refill_debug_tramp, PT_SIZE, sp)
-       j       __xtlb_refill_debug
-       END(__xtlb_refill_debug_tramp)
-
-NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp)
-       j       __tlb_refill_debug
-       END(__tlb_refill_debug_tramp)
-       __FINIT
-
        .macro  __BUILD_cli
        CLI
        .endm
@@ -31,7+21,7 @@ NESTED(__tlb_refill_debug_tramp, PT_SIZE, sp)
        STI
        .endm
 
-       .macro  tlb_handler name interruptible
+       .macro  tlb_handler name interruptible writebit
        NESTED(__\name, PT_SIZE, sp)
        SAVE_ALL
 #if DEBUG_MIPS64
@@ -42,17+32,17 @@ ld $6, PT_R6(sp)
 ld $7, PT_R7(sp)
 ld $2, PT_R2(sp)
 #endif
-       __BUILD_\interruptible
-       dmfc0   t0, CP0_BADVADDR
-       sd      t0, PT_BVADDR(sp)
+       dmfc0   a2, CP0_BADVADDR
+       li      a1, \writebit
+       sd      a2, PT_BVADDR(sp)
        move    a0, sp
-       jal     \name
-       j       return
+       __BUILD_\interruptible
+       jal     do_page_fault
        END(__\name)
+       RESTORE_ALL
+       eret
        .endm
 
-       tlb_handler     tlb_refill_debug cli
-       tlb_handler     xtlb_refill_debug cli
-       tlb_handler     xtlb_mod_debug sti
-       tlb_handler     xtlb_tlbl_debug sti
-       tlb_handler     xtlb_tlbs_debug sti
+       tlb_handler     xtlb_mod sti 1
+       tlb_handler     xtlb_tlbl sti 0
+       tlb_handler     xtlb_tlbs sti 1
index d37fa0c..a6f7266 100644 (file)
-/* $Id: scall_o32.S,v 1.18 2000/03/27 21:04:13 ulfc Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  *
  * Hairy, the userspace application uses a different argument passing
  * convention than the kernel, so we have to translate things from o32
@@ -245,7+244,7 @@ illegal_syscall:
        sys     sys_rmdir       1                       /* 4040 */
        sys     sys_dup         1
        sys     sys_pipe        0
-       sys     sys_times       1
+       sys     sys32_times     1
        sys     sys_ni_syscall  0
        sys     sys_brk         1                       /* 4045 */
        sys     sys_setgid      1
@@ -257,7+256,7 @@ illegal_syscall:
        sys     sys_umount      2
        sys     sys_ni_syscall  0
        sys     sys32_ioctl     3
-       sys     sys_fcntl       3                       /* 4055 */
+       sys     sys32_fcntl     3                       /* 4055 */
        sys     sys_ni_syscall  2
        sys     sys_setpgid     2
        sys     sys_ni_syscall, 0
@@ -383,7+382,7 @@ illegal_syscall:
        sys     sys_send        4
        sys     sys_sendmsg     3
        sys     sys_sendto      6                       /* 4180 */
-       sys     sys_setsockopt  5
+       sys     sys32_setsockopt        5
        sys     sys_shutdown    2
        sys     sys_socket      3
        sys     sys_socketpair  4
@@ -415,9+414,9 @@ illegal_syscall:
        sys     sys_mmap2       6                       /* 4210 */
        sys     sys_truncate64  2
        sys     sys_ftruncate64 2
-       sys     sys_stat64      3
-       sys     sys_lstat64     3
-       sys     sys_fstat64     3                       /* 4210 */
+       sys     sys_newstat     3
+       sys     sys_newlstat    3
+       sys     sys_newfstat    3                       /* 4210 */
        sys     sys_pivot_root  2
        sys     sys_mincore     3
        sys     sys_madvise     3
index fe4c750..691e88d 100644 (file)
 #include <asm/io.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
+#include <asm/pgalloc.h>
 
 #ifdef CONFIG_SGI_IP27
 /* XXX Origin garbage has no business in this file  */
@@ -153,6+154,9 @@ void __init setup_arch(char **cmdline_p)
        unsigned long tmp;
        unsigned long *initrd_header;
 #endif
+       int i;
+       pmd_t *pmd = kpmdtbl;
+       pte_t *pte = kptbl;
 
        cpu_probe();
        load_mmu();
@@ -191,4+195,10 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        paging_init();
+
+       memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER);
+       memset((void *)kpmdtbl, 0, PAGE_SIZE);
+       pgd_set(swapper_pg_dir, kpmdtbl);
+       for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE)
+               pmd_val(*pmd) = (unsigned long)pte;
 }
index 97c54da..81daada 100644 (file)
-/* $Id: signal.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
- *
+/*
  * 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) 1991, 1992  Linus Torvalds
- * Copyright (C) 1994 - 1999  Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 2000  Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/sched.h>
@@ -38,6+37,8 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
 
+extern asmlinkage void syscall_trace(void);
+
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
        if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
@@ -197,8+198,6 @@ sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
                err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
                 err |= __put_user(0, &oact->sa_mask.sig[1]);
-                err |= __put_user(0, &oact->sa_mask.sig[2]);
-                err |= __put_user(0, &oact->sa_mask.sig[3]);
                err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
                 if (err)
                        return -EFAULT;
@@ -294,6+293,8 @@ sys_sigreturn(abi64_no_regargs, struct pt_regs regs)
        /*
         * Don't let your children do this ...
         */
+       if (current->ptrace & PT_TRACESYS)
+               syscall_trace();
        __asm__ __volatile__(
                "move\t$29, %0\n\t"
                "j\tret_from_sys_call"
@@ -354,7+355,7 @@ setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 
        err |= __put_user(regs->cp0_epc, &sc->sc_pc);
 
-#define save_gp_reg(i) {                                               \
+#define save_gp_reg(i) do {                                            \
        err |= __put_user(regs->regs[i], &sc->sc_regs[i]);              \
 } while(0)
        __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2);
@@ -620,7+621,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
@@ -694,7+695,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                                /* FALLTHRU */
 
                        default:
-                               lock_kernel();
                                sigaddset(&current->signal, signr);
                                recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
index 2a8e95e..047cc38 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj Exp $
- *
+/*
  * 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.
@@ -8,6+7,7 @@
  * Copyright (C) 1994 - 1999  Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -37,6+37,8 @@ extern asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs);
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
 
+extern asmlinkage void syscall_trace(void);
+
 /* 32-bit compatibility types */
 
 #define _NSIG32_BPW    32
@@ -60,7+62,7 @@ struct sigaction32 {
 /* IRIX compatible stack_t  */
 typedef struct sigaltstack32 {
        void *ss_sp;
-       size_t ss_size;
+       __kernel_size_t32 ss_size;
        int ss_flags;
 } stack32_t;
 
@@ -94,18+96,72 @@ static inline int refill_fp_context(struct sigcontext *sc)
        return err;
 }
 
+extern void __put_sigset_unknown_nsig(void);
+extern void __get_sigset_unknown_nsig(void);
+
+static inline int
+put_sigset(const sigset_t *kbuf, sigset32_t *ubuf)
+{
+       int err = 0;
+
+       if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
+               return -EFAULT;
+
+       switch (_NSIG_WORDS) {
+       default:
+               __put_sigset_unknown_nsig();
+       case 2:
+               err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
+               err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
+       case 1:
+               err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
+               err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
+       }
+
+       return err;
+}
+
+static inline int
+get_sigset(sigset_t *kbuf, const sigset32_t *ubuf)
+{
+       int err = 0;
+       unsigned long sig[4];
+
+       if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
+               return -EFAULT;
+
+       switch (_NSIG_WORDS) {
+       default:
+               __get_sigset_unknown_nsig();
+       case 2:
+               err |= __get_user (sig[3], &ubuf->sig[3]);
+               err |= __get_user (sig[2], &ubuf->sig[2]);
+               kbuf->sig[1] = sig[2] | (sig[3] << 32);
+       case 1:
+               err |= __get_user (sig[1], &ubuf->sig[1]);
+               err |= __get_user (sig[0], &ubuf->sig[0]);
+               kbuf->sig[0] = sig[0] | (sig[1] << 32);
+       }
+
+       return err;
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage inline int
 sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
 {
-       sigset_t *uset, saveset, newset;
+       sigset32_t *uset;
+       sigset_t newset, saveset;
 
-       save_static(&regs);
+#if DEBUG_MIPS64
 printk("%s called.\n", __FUNCTION__);
-       uset = (sigset_t *) regs.regs[4];
-       if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+#endif
+
+       save_static(&regs);
+       uset = (sigset32_t *) regs.regs[4];
+       if (get_sigset(&newset, uset))
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
@@ -128,19+184,22 @@ printk("%s called.\n", __FUNCTION__);
 asmlinkage int
 sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
 {
-       sigset_t *unewset, saveset, newset;
+       sigset32_t *uset;
+       sigset_t newset, saveset;
         size_t sigsetsize;
 
-       save_static(&regs);
+#if DEBUG_MIPS64
 printk("%s called.\n", __FUNCTION__);
+#endif
 
+       save_static(&regs);
        /* XXX Don't preclude handling different sized sigset_t's.  */
        sigsetsize = regs.regs[5];
-       if (sigsetsize != sizeof(sigset_t))
+       if (sigsetsize != sizeof(sigset32_t))
                return -EINVAL;
 
-       unewset = (sigset_t *) regs.regs[4];
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
+       uset = (sigset32_t *) regs.regs[4];
+       if (get_sigset(&newset, uset))
                return -EFAULT;
        sigdelsetmask(&newset, ~_BLOCKABLE);
 
@@ -172,10+231,12 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
 
                if (!access_ok(VERIFY_READ, act, sizeof(*act)))
                        return -EFAULT;
-               err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+               err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
+                                 &act->sa_handler);
                err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
                err |= __get_user(mask, &act->sa_mask.sig[0]);
-               err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer);
+               err |= __get_user((u32)(u64)new_ka.sa.sa_restorer,
+                                  &act->sa_restorer);
                if (err)
                        return -EFAULT;
 
@@ -188,12+249,14 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
                         return -EFAULT;
                err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-               err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+               err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
+                                 &oact->sa_handler);
                err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
                 err |= __put_user(0, &oact->sa_mask.sig[1]);
                 err |= __put_user(0, &oact->sa_mask.sig[2]);
                 err |= __put_user(0, &oact->sa_mask.sig[3]);
-               err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
+               err |= __put_user((u32)(u64)old_ka.sa.sa_restorer,
+                                 &oact->sa_restorer);
                 if (err)
                        return -EFAULT;
        }
@@ -204,12+267,37 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
 asmlinkage int
 sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs)
 {
-       const stack_t *uss = (const stack_t *) regs.regs[4];
-       stack_t *uoss = (stack_t *) regs.regs[5];
+       const stack32_t *uss = (const stack32_t *) regs.regs[4];
+       stack32_t *uoss = (stack32_t *) regs.regs[5];
        unsigned long usp = regs.regs[29];
-printk("%s called.\n", __FUNCTION__);
+       stack_t kss, koss;
+       int ret, err = 0;
+       mm_segment_t old_fs = get_fs();
 
-       return do_sigaltstack(uss, uoss, usp);
+       if (uss) {
+               if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+                       return -EFAULT;
+               err |= __get_user(kss.ss_sp, &uss->ss_sp);
+               err |= __get_user(kss.ss_size, &uss->ss_size);
+               err |= __get_user(kss.ss_flags, &uss->ss_flags);
+               if (err)
+                       return -EFAULT;
+       }
+
+       set_fs (KERNEL_DS);
+       ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
+       set_fs (old_fs);
+
+       if (!ret && uoss) {
+               if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
+                       return -EFAULT;
+               err |= __put_user(koss.ss_sp, &uoss->ss_sp);
+               err |= __put_user(koss.ss_size, &uoss->ss_size);
+               err |= __put_user(koss.ss_flags, &uoss->ss_flags);
+               if (err)
+                       return -EFAULT;
+       }
+       return ret;
 }
 
 static asmlinkage int
@@ -293,6+381,8 @@ printk("%s called.\n", __FUNCTION__);
        /*
         * Don't let your children do this ...
         */
+       if (current->ptrace & PT_TRACESYS)
+               syscall_trace();
        __asm__ __volatile__(
                "move\t$29, %0\n\t"
                "j\tret_from_sys_call"
@@ -610,7+700,7 @@ printk("%s: delivering signal.\n", current->comm);
                if (!signr)
                        break;
 
-               if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+               if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
                        /* Let the debugger run.  */
                        current->exit_code = signr;
                        current->state = TASK_STOPPED;
@@ -684,7+774,6 @@ printk("%s: delivering signal.\n", current->comm);
                                /* FALLTHRU */
 
                        default:
-                               lock_kernel();
                                sigaddset(&current->signal, signr);
                                recalc_sigpending(current);
                                current->flags |= PF_SIGNALED;
@@ -723,26+812,128 @@ extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set,
                                                old_sigset_t *oset);
 
 asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, 
-                                                       old_sigset_t32 *oset)
+                                old_sigset_t32 *oset)
 {
        old_sigset_t s;
        int ret;
        mm_segment_t old_fs = get_fs();
 
-       if (set && get_user (s, set)) return -EFAULT;
+       if (set && get_user (s, set))
+               return -EFAULT;
        set_fs (KERNEL_DS);
        ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
        set_fs (old_fs);
-       if (ret) return ret;
-       if (oset && put_user (s, oset)) return -EFAULT;
-       return 0;
+       if (!ret && oset && put_user (s, oset))
+               return -EFAULT;
+       return ret;
 }
 
-/* Dummies ... */
+asmlinkage long sys_sigpending(old_sigset_t *set);
+
+asmlinkage int sys32_sigpending(old_sigset_t32 *set)
+{
+       old_sigset_t pending;
+       int ret;
+       mm_segment_t old_fs = get_fs();
+
+       set_fs (KERNEL_DS);
+       ret = sys_sigpending(&pending);
+       set_fs (old_fs);
+
+       if (put_user(pending, set))
+               return -EFAULT;
+
+       return ret;
+}
+
+asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
+                                 struct sigaction32 *oact,
+                                 unsigned int sigsetsize)
+{
+       struct k_sigaction new_sa, old_sa;
+       int ret = -EINVAL;
+
+       /* XXX: Don't preclude handling different sized sigset_t's.  */
+       if (sigsetsize != sizeof(sigset_t))
+               goto out;
+
+       if (act) {
+               int err = 0;
+
+               if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+                       return -EFAULT;
+               err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
+                                 &act->sa_handler);
+               err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
+               err |= __get_user((u32)(u64)new_sa.sa.sa_restorer,
+                                 &act->sa_restorer);
+               err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
+               if (err)
+                       return -EFAULT;
+       }
+
+       ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+       if (!ret && oact) {
+               int err = 0;
+
+               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+                       return -EFAULT;
+
+               err |= __put_user((u32)(u64)new_sa.sa.sa_handler,
+                                  &oact->sa_handler);
+               err |= __put_user(new_sa.sa.sa_flags, &oact->sa_flags);
+               err |= __put_user((u32)(u64)new_sa.sa.sa_restorer,
+                                 &oact->sa_restorer);
+               err |= put_sigset(&new_sa.sa.sa_mask, &oact->sa_mask);
+               if (err)
+                       return -EFAULT;
+       }
+out:
+       return ret;
+}
+
+asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
+                                  size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
+                                   unsigned int sigsetsize)
+{
+       sigset_t old_set, new_set;
+       int ret;
+       mm_segment_t old_fs = get_fs();
+
+       if (set && get_sigset(&new_set, set))
+               return -EFAULT;
+       
+       set_fs (KERNEL_DS);
+       ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
+                                oset ? &old_set : NULL, sigsetsize);
+       set_fs (old_fs);
+
+       if (!ret && oset && put_sigset(&old_set, oset))
+               return -EFAULT;
+
+       return ret;
+}
+
+asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigpending(sigset32_t *uset, unsigned int sigsetsize)
+{
+       int ret;
+       sigset_t set;
+       mm_segment_t old_fs = get_fs();
+
+       set_fs (KERNEL_DS);
+       ret = sys_rt_sigpending(&set, sigsetsize);
+       set_fs (old_fs);
+
+       if (!ret && put_sigset(&set, uset))
+               return -EFAULT;
+
+       return ret;
+}
 
-asmlinkage void sys32_sigpending(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigaction(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigprocmask(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigpending(void) { panic(__FUNCTION__ " called."); }
 asmlinkage void sys32_rt_sigtimedwait(void) { panic(__FUNCTION__ " called."); }
 asmlinkage void sys32_rt_sigqueueinfo(void) { panic(__FUNCTION__ " called."); }
index 155b065..e1aedbb 100644 (file)
@@ -69,14+69,12 @@ static void smp_tune_scheduling (void)
 void __init smp_boot_cpus(void)
 {
        extern void allowboot(void);
-       extern int maxcpus;
 
        init_new_context(current, &init_mm);
        global_irq_holder = 0;
        current->processor = 0;
        init_idle();
        smp_tune_scheduling();
-       smp_num_cpus = maxcpus;
        allowboot();
 }
 
index be08ff0..555a11f 100644 (file)
-/* $Id: softfp.S,v 1.2 2000/03/21 23:50:42 ulfc Exp $
- *
+/*
  * 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) 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 by Silicon Graphics, Inc.
+ * Copyright (C) 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
  *
  * For now it's just a crude hack good enough to run certain fp programs like
  * Mozilla.
@@ -192,15+191,15 @@ LEAF(simfp)
 #define FMT_switch(insn,opc,temp0,temp1)                               \
 insn:  srl     temp0, opc, 18;                                         \
        andi    temp0, 0x1c;                                            \
-       la      temp1, insn ## .tab;                                    \
+       la      temp1, insn##.tab;                                      \
        daddu   temp0, temp1;                                           \
        ld      temp0, (temp0);                                         \
        jr      temp0;                                                  \
                                                                        \
        .data;                                                          \
-insn ## .tab:                                                          \
-       .dword  insn ## .s, insn ## .d, unimp, unimp;                   \
-       .dword  insn ## .w, insn ## .l, unimp, unimp;                   \
+insn##.tab:                                                            \
+       .dword  insn##.s, insn##.d, unimp, unimp;                       \
+       .dword  insn##.w, insn##.l, unimp, unimp;                       \
        .previous
 
        BITCH(add)
index 1055937..5568524 100644 (file)
-/* $Id: syscall.c,v 1.3 2000/02/04 07:40:24 ralf Exp $
- *
+/*
  * 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) 1995 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
+#include <linux/slab.h>
 #include <asm/ipc.h>
 #include <asm/cachectl.h>
 #include <asm/offset.h>
@@ -170,39+170,46 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3)
        char    *name;
        int     flags, tmp, len, errno;
 
-       switch(cmd)
-       {
-       case SETNAME:
+       switch(cmd) {
+       case SETNAME: {
+               char nodename[__NEW_UTS_LEN + 1];
+
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
                name = (char *) arg1;
-               len = strlen_user(name);
 
-               if (len == 0 || len > __NEW_UTS_LEN)
-                       return -EINVAL;
-               down(&uts_sem);
-               errno = -EFAULT;
-               if (!copy_from_user(system_utsname.nodename, name, len)) {
-                       system_utsname.nodename[len] = '\0';
-                       errno = 0;
-               }
-               up(&uts_sem);
-               return errno;
+               len = strncpy_from_user(nodename, name, sizeof(nodename));
+               if (len < 0)
+                       return -EFAULT;
 
-       case MIPS_ATOMIC_SET:
+               down_write(&uts_sem);
+               strncpy(system_utsname.nodename, name, len);
+               up_write(&uts_sem);
+               system_utsname.nodename[len] = '\0';
+               return 0;
+       }
+
+       case MIPS_ATOMIC_SET: {
                /* This is broken in case of page faults and SMP ...
-                  Risc/OS fauls after maximum 20 tries with EAGAIN.  */
+                   Risc/OS faults after maximum 20 tries with EAGAIN.  */
+               unsigned int tmp;
+
                p = (int *) arg1;
                errno = verify_area(VERIFY_WRITE, p, sizeof(*p));
                if (errno)
                        return errno;
+               errno = 0;
                save_and_cli(flags);
-               errno = *p;
-               *p = arg2;
+               errno |= __get_user(tmp, p);
+               errno |= __put_user(arg2, p);
                restore_flags(flags);
 
-               return errno;           /* This is broken ...  */
+               if (errno)
+                       return tmp;
+
+               return tmp;             /* This is broken ...  */
+       }
 
        case MIPS_FIXADE:
                tmp = current->thread.mflags & ~3;
@@ -226,7+233,7 @@ sys_sysmips(int cmd, long arg1, int arg2, int arg3)
  * This is really horribly ugly.
  */
 asmlinkage int sys_ipc (uint call, int first, int second,
-                       int third, void *ptr, long fifth)
+                       unsigned long third, void *ptr, long fifth)
 {
        int version, ret;
 
index fa58017..997aee0 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: traps.c,v 1.4 2000/01/20 23:50:27 ralf Exp $
- *
+/*
  * 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.
@@ -41,9+40,9 @@ static inline void console_verbose(void)
                console_loglevel = 15;
 }
 
-extern asmlinkage void __xtlb_mod_debug(void);
-extern asmlinkage void __xtlb_tlbl_debug(void);
-extern asmlinkage void __xtlb_tlbs_debug(void);
+extern asmlinkage void __xtlb_mod(void);
+extern asmlinkage void __xtlb_tlbl(void);
+extern asmlinkage void __xtlb_tlbs(void);
 extern asmlinkage void handle_adel(void);
 extern asmlinkage void handle_ades(void);
 extern asmlinkage void handle_ibe(void);
@@ -77,10+76,10 @@ int kstack_depth_to_print = 24;
  * This routine abuses get_user()/put_user() to reference pointers
  * with at least a bit of error checking ...
  */
-void show_stack(unsigned int *sp)
+void show_stack(unsigned long *sp)
 {
        int i;
-       unsigned int *stack;
+       unsigned long *stack;
 
        stack = sp;
        i = 0;
@@ -94,22+93,22 @@ void show_stack(unsigned int *sp)
                        break;
                }
 
-               printk(" %08lx", stackdata);
+               printk(" %016lx", stackdata);
 
                if (++i > 40) {
                        printk(" ...");
                        break;
                }
 
-               if (i % 8 == 0)
+               if (i % 4 == 0)
                        printk("\n      ");
        }
 }
 
-void show_trace(unsigned int *sp)
+void show_trace(unsigned long *sp)
 {
        int i;
-       unsigned int *stack;
+       unsigned long *stack;
        unsigned long kernel_start, kernel_end;
        unsigned long module_start, module_end;
        extern char _stext, _etext;
@@ -144,7+143,11 @@ void show_trace(unsigned int *sp)
                if ((addr >= kernel_start && addr < kernel_end) ||
                    (addr >= module_start && addr < module_end)) { 
 
-                       printk(" [<%08lx>]", addr);
+                       /* Since our kernel is still at KSEG0,
+                        * truncate the address so that ksymoops
+                        * understands it.
+                        */
+                       printk(" [<%08x>]", (unsigned int) addr);
                        if (++i > 40) {
                                printk(" ...");
                                break;
@@ -160,12+163,12 @@ void show_code(unsigned int *pc)
        printk("\nCode:");
 
        for(i = -3 ; i < 6 ; i++) {
-               unsigned long insn;
+               unsigned int insn;
                if (__get_user(insn, pc + i)) {
                        printk(" (Bad address in epc)\n");
                        break;
                }
-               printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
+               printk("%c%08x%c",(i?' ':'<'),insn,(i?' ':'>'));
        }
 }
 
@@ -180,10+183,10 @@ void die(const char * str, struct pt_regs * regs, unsigned long err)
        spin_lock_irq(&die_lock);
        printk("%s: %04lx\n", str, err & 0xffff);
        show_regs(regs);
-       printk("Process %s (pid: %ld, stackpage=%08lx)\n",
+       printk("Process %s (pid: %d, stackpage=%08lx)\n",
                current->comm, current->pid, (unsigned long) current);
-       show_stack((unsigned int *) regs->regs[29]);
-       show_trace((unsigned int *) regs->regs[29]);
+       show_stack((unsigned long *) regs->regs[29]);
+       show_trace((unsigned long *) regs->regs[29]);
        show_code((unsigned int *) regs->cp0_epc);
        printk("\n");
        spin_unlock_irq(&die_lock);
@@ -230,6+233,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
        unsigned long pc;
        unsigned int insn;
+       extern void simfp(unsigned int);
 
 #ifdef CONFIG_MIPS_FPE_MODULE
        if (fpe_handler != NULL) {
@@ -237,7+241,6 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                return;
        }
 #endif
-       lock_kernel();
        if (fcr31 & 0x20000) {
                /* Retry instruction with flush to zero ...  */
                if (!(fcr31 & (1<<24))) {
@@ -249,7+252,7 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                                "ctc1\t%0,$31"
                                : /* No outputs */
                                : "r" (fcr31));
-                       goto out;
+                       return;
                }
                pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
                if (get_user(insn, (unsigned int *)pc)) {
@@ -263,12+266,9 @@ void do_fpe(struct pt_regs *regs, unsigned long fcr31)
        }
 
        if (compute_return_epc(regs))
-               goto out;
+               return;
        //force_sig(SIGFPE, current);
        printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm);
-
-out:
-       unlock_kernel();
 }
 
 static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -327,11+327,9 @@ void do_tr(struct pt_regs *regs)
 
 void do_ri(struct pt_regs *regs)
 {
-       lock_kernel();
-       printk("Cpu%d[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+       printk("Cpu%d[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
                smp_processor_id(), current->comm, current->pid, regs->cp0_epc, 
                regs->regs[31]);
-       unlock_kernel();
        if (compute_return_epc(regs))
                return;
        force_sig(SIGILL, current);
@@ -390,7+388,7 @@ void do_reserved(struct pt_regs *regs)
         * caused by a new unknown cpu type or after another deadly
         * hard/software error.
         */
-       panic("Caught reserved exception %d - should not happen.",
+       panic("Caught reserved exception %ld - should not happen.",
              (regs->cp0_cause & 0x1f) >> 2);
 }
 
@@ -471,8+469,8 @@ static inline void go_64(void)
 
 void __init trap_init(void)
 {
-       extern char __tlb_refill_debug_tramp;
-       extern char __xtlb_refill_debug_tramp;
+       extern char except_vec0;
+       extern char except_vec1_r10k;
        extern char except_vec2_generic;
        extern char except_vec3_generic, except_vec3_r4000;
        extern void bus_error_init(void);
@@ -528,8+526,8 @@ void __init trap_init(void)
        case CPU_NEVADA:
 r4k:
                /* Debug TLB refill handler.  */
-               memcpy((void *)KSEG0, &__tlb_refill_debug_tramp, 0x80);
-               memcpy((void *)KSEG0 + 0x080, &__xtlb_refill_debug_tramp, 0x80);
+               memcpy((void *)KSEG0, &except_vec0, 0x80);
+               memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
 
                /* Cache error vector  */
                memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
@@ -542,9+540,9 @@ r4k:
                               0x100);
                }
 
-               set_except_vector(1, __xtlb_mod_debug);
-               set_except_vector(2, __xtlb_tlbl_debug);
-               set_except_vector(3, __xtlb_tlbs_debug);
+               set_except_vector(1, __xtlb_mod);
+               set_except_vector(2, __xtlb_tlbl);
+               set_except_vector(3, __xtlb_tlbs);
                set_except_vector(4, handle_adel);
                set_except_vector(5, handle_ades);
 
index a89d049..659e376 100644 (file)
@@ -3,11+3,9 @@ ENTRY(kernel_entry)
 SECTIONS
 {
   /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
   .init          : { *(.init)          } =0
   .text      :
   {
-    _ftext = . ;
     *(.text)
     *(.rodata)
     *(.rodata1)
@@ -15,9+13,9 @@ SECTIONS
     *(.gnu.warning)
   } =0
   _etext = .;
-  PROVIDE (etext = .);
 
   . = ALIGN(16384);
+  /* This for CONFIG_MAPPED_KERNEL . = . + 16777216; */
   .data.init_task : { *(.data.init_task) }
 
   /* Startup code */
@@ -65,7+63,6 @@ SECTIONS
     CONSTRUCTORS
   }
   .data1   : { *(.data1) }
-  _gp = . + 0x8000;
   .lit8 : { *(.lit8) }
   .lit4 : { *(.lit4) }
   .ctors         : { *(.ctors)   }
@@ -77,10+74,7 @@ SECTIONS
      we can shorten the on-disk segment size.  */
   .sdata     : { *(.sdata) }
   _edata  =  .;
-  PROVIDE (edata = .);
 
-  __bss_start = .;
-  _fbss = .;
   .sbss      : { *(.sbss) *(.scommon) }
   .bss       :
   {
@@ -88,7+82,6 @@ SECTIONS
    *(.bss)
    *(COMMON)
   _end = . ;
-  PROVIDE (end = .);
   }
   /* These are needed for ELF backends which have not yet been
      converted to the new style linker.  */
index abfdf54..47f638b 100644 (file)
@@ -16,7+16,6 @@ SECTIONS
   /* . = 0xa800000000300000; */
   . = 0xffffffff80300000;
   .text : {
-    _ftext = . ;
     *(.text)
     *(.rodata)
     *(.rodata1)
@@ -24,7+23,6 @@ SECTIONS
     *(.gnu.warning)
   } = 0
   _etext = .;
-  PROVIDE (etext = .);
 
   . = ALIGN(16384);
   .data.init_task : { *(.data.init_task) }
@@ -74,7+72,6 @@ SECTIONS
     CONSTRUCTORS
   }
   .data1   : { *(.data1) }
-  _gp = . + 0x8000;
   .lit8 : { *(.lit8) }
   .lit4 : { *(.lit4) }
   .ctors         : { *(.ctors)   }
@@ -86,10+83,7 @@ SECTIONS
      we can shorten the on-disk segment size.  */
   .sdata     : { *(.sdata) }
   _edata  =  .;
-  PROVIDE (edata = .);
 
-  __bss_start = .;
-  _fbss = .;
   .sbss      : { *(.sbss) *(.scommon) }
   .bss       :
   {
@@ -97,7+91,6 @@ SECTIONS
    *(.bss)
    *(COMMON)
   _end = . ;
-  PROVIDE (end = .);
   }
   /* These are needed for ELF backends which have not yet been
      converted to the new style linker.  */
index 4d0de2b..7ac575a 100644 (file)
@@ -133,28+133,28 @@ dump_list_process(struct task_struct *t, void *address)
        pgd_t   *page_dir, *pgd;
        pmd_t   *pmd;
        pte_t   *pte, page;
-       unsigned int addr;
+       unsigned long addr;
        unsigned long val;
 
-       addr = (unsigned int) address;
+       addr = (unsigned long) address;
 
-       printk("Addr                 == %08x\n", addr);
-       printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
+       printk("Addr                 == %08lx\n", addr);
+       printk("tasks->mm.pgd        == %08lx\n", (unsigned long) t->mm->pgd);
 
        page_dir = pgd_offset(t->mm, 0);
-       printk("page_dir == %08x\n", (unsigned int) page_dir);
+       printk("page_dir == %08lx\n", (unsigned long) page_dir);
 
        pgd = pgd_offset(t->mm, addr);
-       printk("pgd == %08x, ", (unsigned int) pgd);
+       printk("pgd == %08lx, ", (unsigned long) pgd);
 
        pmd = pmd_offset(pgd, addr);
-       printk("pmd == %08x, ", (unsigned int) pmd);
+       printk("pmd == %08lx, ", (unsigned long) pmd);
 
        pte = pte_offset(pmd, addr);
-       printk("pte == %08x, ", (unsigned int) pte);
+       printk("pte == %08lx, ", (unsigned long) pte);
 
        page = *pte;
-       printk("page == %08x\n", (unsigned int) pte_val(page));
+       printk("page == %08lx\n", (unsigned long) pte_val(page));
 
        val = pte_val(page);
        if (val & _PAGE_PRESENT) printk("present ");
index 88dbfdb..4fa0f6b 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/keyboard.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/mc146818rtc.h>
 #include <asm/pgtable.h>
 
 /*
index 7e4d412..8854430 100644 (file)
@@ -458,7+458,6 @@ void __init ld_mmu_andes(void)
        _user_mode = andes_user_mode;
 
         flush_cache_all();
-        write_32bit_cp0_register(CP0_WIRED, 0);
 
        /*
         * You should never change this register:
index e31c825..204419e 100644 (file)
-/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $
- *
+/*
  * 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) 1995, 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 by Silicon Graphics
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 by Silicon Graphics, Inc.
  */
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -41,7+40,8 @@ extern void die(char *, struct pt_regs *, unsigned long write);
 asmlinkage void
 dodebug(abi64_no_regargs, struct pt_regs regs)
 {
-       printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
+       printk("Got syscall %ld, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2],
+              smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
 }
 
 asmlinkage void
@@ -68,9+68,10 @@ do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address)
        struct vm_area_struct * vma;
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
-       int si_code = SEGV_MAPERR;
        unsigned long fixup;
+       siginfo_t info;
 
+       info.si_code = SEGV_MAPERR;
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
@@ -96,7+97,7 @@ do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address)
  * we can handle it..
  */
 good_area:
-       si_code = SEGV_ACCERR;
+       info.si_code = SEGV_ACCERR;
 
        if (write) {
                if (!(vma->vm_flags & VM_WRITE))
@@ -134,8+135,14 @@ good_area:
 bad_area:
        up(&mm->mmap_sem);
 
+       /*
+        * Quickly check for vmalloc range faults.
+        */
+       if ((!vma) && (address >= VMALLOC_START) && (address < VMALLOC_END)) {
+               printk("Fix vmalloc invalidate fault\n");
+               while(1);
+       }
        if (user_mode(regs)) {
-               struct siginfo si;
                tsk->thread.cp0_badvaddr = address;
                tsk->thread.error_code = write;
 #if 0
@@ -147,10+154,11 @@ bad_area:
                       (unsigned long) regs->cp0_epc,
                       (unsigned long) regs->regs[31]);
 #endif
-               si.si_signo = SIGSEGV;
-               si.si_code = si_code;
-               si.si_addr = (void *) address;
-               force_sig_info(SIGSEGV, &si, tsk);
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               /* info.si_code has been set above */
+               info.si_addr = (void *) address;
+               force_sig_info(SIGSEGV, &info, tsk);
                return;
        }
 
@@ -174,8+182,9 @@ no_context:
         * terminate things with extreme prejudice.
         */
        printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at "
-              "address %08lx, epc == %08lx, ra == %08lx\n",
-              smp_processor_id(), address, regs->cp0_epc, regs->regs[31]);
+              "address %08lx, epc == %08x, ra == %08x\n",
+              smp_processor_id(), address, (unsigned int) regs->cp0_epc,
+               (unsigned int) regs->regs[31]);
        die("Oops", regs, write);
        do_exit(SIGKILL);
 
@@ -198,7+207,11 @@ do_sigbus:
         * or user mode.
         */
        tsk->thread.cp0_badvaddr = address;
-       force_sig(SIGBUS, tsk);
+       info.si_code = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = BUS_ADRERR;
+       info.si_addr = (void *) address;
+       force_sig_info(SIGBUS, &info, tsk);
 
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
index 42dece5..c518f96 100644 (file)
@@ -56,7+56,7 @@ void __bad_pte(pmd_t *pmd)
 void __bad_pmd(pgd_t *pgd)
 {
        printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
-       pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
+       pgd_set(pgd, empty_bad_pmd_table);
 }
 
 void pgd_init(unsigned long page)
@@ -93,7+93,7 @@ pgd_t *get_pgd_slow(void)
        return ret;
 }
 
-void pmd_init(unsigned long addr)
+void pmd_init(unsigned long addr, unsigned long pagetable)
 {
        unsigned long *p, *end;
 
@@ -101,14+101,14 @@ void pmd_init(unsigned long addr)
        end = p + PTRS_PER_PMD;
 
        while (p < end) {
-               p[0] = (unsigned long) invalid_pte_table;
-               p[1] = (unsigned long) invalid_pte_table;
-               p[2] = (unsigned long) invalid_pte_table;
-               p[3] = (unsigned long) invalid_pte_table;
-               p[4] = (unsigned long) invalid_pte_table;
-               p[5] = (unsigned long) invalid_pte_table;
-               p[6] = (unsigned long) invalid_pte_table;
-               p[7] = (unsigned long) invalid_pte_table;
+               p[0] = (unsigned long)pagetable;
+               p[1] = (unsigned long)pagetable;
+               p[2] = (unsigned long)pagetable;
+               p[3] = (unsigned long)pagetable;
+               p[4] = (unsigned long)pagetable;
+               p[5] = (unsigned long)pagetable;
+               p[6] = (unsigned long)pagetable;
+               p[7] = (unsigned long)pagetable;
                p += 8;
        }
 }
@@ -120,7+120,7 @@ pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
        pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, 1);
        if (pgd_none(*pgd)) {
                if (pmd) {
-                       pmd_init((unsigned long)pmd);
+                       pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
                        pgd_set(pgd, pmd);
                        return pmd + offset;
                }
@@ -161,7+161,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
        pte_t *page;
 
-       page = (pte_t *) __get_free_pages(GFP_KERNEL, 1);
+       page = (pte_t *) __get_free_pages(GFP_KERNEL, 0);
        if (pmd_none(*pmd)) {
                if (page) {
                        clear_page(page);
@@ -171,7+171,7 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
                pmd_set(pmd, BAD_PAGETABLE);
                return NULL;
        }
-       free_pages((unsigned long)page, 1);
+       free_pages((unsigned long)page, 0);
        if (pmd_bad(*pmd)) {
                __bad_pte(pmd);
                return NULL;
@@ -246,21+246,6 @@ unsigned long setup_zero_pages(void)
        return 1UL << order;
 }
 
-extern inline void pte_init(unsigned long page)
-{
-       unsigned long *p, *end, bp;
-
-       bp = pte_val(BAD_PAGE);
-       p = (unsigned long *) page;
-       end = p + (2 * PTRS_PER_PTE);
-
-       while (p < end) {
-               p[0] = p[1] = p[2] = p[3] =
-               p[4] = p[5] = p[6] = p[7] = bp;
-               p += 8;
-       }
-}
-
 /*
  * BAD_PAGE is the page that is used for page faults when linux
  * is out-of-memory. Older versions of linux just did a
@@ -276,33+261,17 @@ extern inline void pte_init(unsigned long page)
  */
 pmd_t * __bad_pmd_table(void)
 {
-       extern pmd_t invalid_pmd_table[PTRS_PER_PMD];
-       unsigned long page;
-
-       page = (unsigned long) invalid_pmd_table;
-       pmd_init(page);
-
-       return (pmd_t *) page;
+       return empty_bad_pmd_table;
 }
 
 pte_t * __bad_pagetable(void)
 {
-       extern char empty_bad_page_table[PAGE_SIZE];
-       unsigned long page;
-
-       page = (unsigned long) empty_bad_page_table;
-       pte_init(page);
-
-       return (pte_t *) page;
+       return empty_bad_page_table;
 }
 
 pte_t __bad_page(void)
 {
-       extern char empty_bad_page[PAGE_SIZE];
-       unsigned long page = (unsigned long) empty_bad_page;
-
-       clear_page((void *)page);
-       return pte_mkdirty(mk_pte_phys(__pa(page), PAGE_SHARED));
+       return __pte(0);
 }
 
 void show_mem(void)
@@ -337,7+306,7 @@ void show_mem(void)
 #ifndef CONFIG_DISCONTIGMEM
 /* References to section boundaries */
 
-extern char _ftext, _etext, _fdata, _edata;
+extern char _stext, _etext, _fdata, _edata;
 extern char __init_begin, __init_end;
 
 void __init paging_init(void)
@@ -347,8+316,10 @@ void __init paging_init(void)
 
        /* Initialize the entire pgd.  */
        pgd_init((unsigned long)swapper_pg_dir);
-       pmd_init((unsigned long)invalid_pmd_table);
-       memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
+       pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+       memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
+       pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table);
+       memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
 
        max_dma =  virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
        low = max_low_pfn;
@@ -384,7+355,7 @@ void __init mem_init(void)
                                reservedpages++;
                }
 
-       codesize =  (unsigned long) &_etext - (unsigned long) &_ftext;
+       codesize =  (unsigned long) &_etext - (unsigned long) &_stext;
        datasize =  (unsigned long) &_edata - (unsigned long) &_fdata;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
index c2b9c40..2b3ca03 100644 (file)
@@ -2545,7+2545,6 @@ void __init ld_mmu_r4xx0(void)
        _user_mode = r4k_user_mode;
 
        flush_cache_all();
-       write_32bit_cp0_register(CP0_WIRED, 0);
 
        /*
         * You should never change this register:
index 7505e0c..82aa098 100644 (file)
 #include <linux/tty.h>
 
 #include <asm/addrspace.h>
+#include <asm/mmu_context.h>
 #include <asm/bcache.h>
 #include <asm/keyboard.h>
 #include <asm/irq.h>
@@ -125,6+126,7 @@ void __init ip22_setup(void)
 #ifdef CONFIG_SERIAL_CONSOLE
        char *ctype;
 #endif
+       TLBMISS_HANDLER_SETUP();
 
        /* Init the INDY HPC I/O controller.  Need to call this before
         * fucking with the memory controller because it needs to know the
index c15231c..162eb72 100644 (file)
 L_TARGET = ip27.a
 L_OBJS  = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \
          ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \
-         ip27-timer.o ip27-init.o ip27-nmi.o
+         ip27-timer.o ip27-init.o ip27-nmi.o ip27-klnuma.o
 
 include $(TOPDIR)/Rules.make
index b4b594b..fade5a7 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: ip27-berr.c,v 1.1 2000/01/20 22:50:29 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/sn/sn0/hub.h>
 #include <asm/uaccess.h>
 
+extern void dump_tlb_addr(unsigned long addr);
+extern void dump_tlb_all(void);
+
 extern asmlinkage void handle_ibe(void);
 extern asmlinkage void handle_dbe(void);
 
index 7e412cb..1afd32d 100644 (file)
@@ -1,4+1,3 @@
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <asm/sn/launch.h>
 #include <asm/sn/sn_private.h>
 #include <asm/sn/sn0/ip27.h>
+#include <asm/sn/mapped_kernel.h>
 
 #define CPU_NONE               (cpuid_t)-1
 
 #define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit))
 
 cpumask_t      boot_cpumask;
-static volatile cpumask_t boot_barrier;
 hubreg_t       region_mask = 0;
 static int     fine_mode = 0;
 int            maxcpus;
 static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
 static cnodemask_t hub_init_mask;
+static atomic_t numstarted = ATOMIC_INIT(1);
+nasid_t master_nasid = INVALID_NASID;
 
 cnodeid_t      nasid_to_compact_node[MAX_NASIDS];
 nasid_t                compact_to_nasid_node[MAX_COMPACT_NODES];
@@ -160,19+161,6 @@ cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes)
        return(highest + 1);
 }
 
-void alloc_cpupda(int i)
-{
-       cnodeid_t       node;
-       nasid_t         nasid;
-
-       node = get_cpu_cnode(i);
-       nasid = COMPACT_TO_NASID_NODEID(node);
-
-       cputonasid(i) = nasid;
-       cputocnode(i) = node;
-       cputoslice(i) = get_cpu_slice(i);
-}
-
 int cpu_enabled(cpuid_t cpu)
 {
        if (cpu == CPU_NONE)
@@ -180,19+168,11 @@ int cpu_enabled(cpuid_t cpu)
        return (CPUMASK_TSTB(boot_cpumask, cpu) != 0);
 }
 
-void initpdas(void)
-{
-       cpuid_t i;
-
-       for (i = 0; i < maxcpus; i++)
-               if (cpu_enabled(i))
-                       alloc_cpupda(i);
-}
-
 void mlreset (void)
 {
        int i;
 
+       master_nasid = get_nasid();
        fine_mode = is_fine_dirmode();
 
        /*
@@ -202,11+182,12 @@ void mlreset (void)
        CPUMASK_CLRALL(boot_cpumask);
        maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
        printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
-       initpdas();
 
        gen_region_mask(&region_mask, numnodes);
        CNODEMASK_CLRALL(hub_init_mask);
 
+       setup_replication_mask(numnodes);
+
        /*
         * Set all nodes' calias sizes to 8k
         */
@@ -221,7+202,11 @@ void mlreset (void)
                 * thinks it is a node 0 address.
                 */
                REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+               REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
+#else
                REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
+#endif
 
 #ifdef LATER
                /*
@@ -283,6+268,7 @@ void sn_mp_setup(void)
 
 void per_hub_init(cnodeid_t cnode)
 {
+       extern void pcibr_setup(cnodeid_t);
        cnodemask_t     done;
 
        spin_lock(&hub_mask_lock);
@@ -290,16+276,35 @@ void per_hub_init(cnodeid_t cnode)
        if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
                /* Turn our bit on in the mask. */
                CNODEMASK_SETB(hub_init_mask, cnode);
-       }
-       spin_unlock(&hub_mask_lock);
-
-       /*
-        * Do the actual initialization if it hasn't been done yet.
-        * We don't need to hold a lock for this work.
-        */
-       if (!done) {
+               /*
+                * Do the actual initialization if it hasn't been done yet.
+                * We don't need to hold a lock for this work.
+                */
                hub_rtc_init(cnode);
+               pcibr_setup(cnode); 
+#ifdef CONFIG_REPLICATE_EXHANDLERS
+               /*
+                * If this is not a headless node initialization, 
+                * copy over the caliased exception handlers.
+                */
+               if (get_compact_nodeid() == cnode) {
+                       extern char except_vec0, except_vec1_r10k;
+                       extern char except_vec2_generic, except_vec3_generic;
+
+                       memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic,
+                                                               0x80);
+                       memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+                                                               0x80);
+                       memcpy((void *)KSEG0, &except_vec0, 0x80);
+                       memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
+                       memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+                       memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
+                                                               0x100);
+                       flush_cache_all();
+               }
+#endif
        }
+       spin_unlock(&hub_mask_lock);
 }
 
 /*
@@ -318,10+323,11 @@ void per_cpu_init(void)
        extern void install_cpu_nmi_handler(int slice);
        extern void load_mmu(void);
        static int is_slave = 0;
-       cpuid_t cpu = getcpuid();
+       int cpu = smp_processor_id();
        cnodeid_t cnode = get_compact_nodeid();
 
        current_cpu_data.asid_cache = ASID_FIRST_VERSION;
+       TLBMISS_HANDLER_SETUP();
 #if 0
        intr_init();
 #endif
@@ -331,7+337,7 @@ void per_cpu_init(void)
        if (smp_processor_id()) /* master can't do this early, no kmalloc */
                install_cpuintr(cpu);
        /* Install our NMI handler if symmon hasn't installed one. */
-       install_cpu_nmi_handler(cputoslice(smp_processor_id()));
+       install_cpu_nmi_handler(cputoslice(cpu));
 #if 0
        install_tlbintr(cpu);
 #endif
@@ -343,9+349,10 @@ void per_cpu_init(void)
                set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX);
                sti();
                load_mmu();
-       }
-       if (is_slave == 0)
+               atomic_inc(&numstarted);
+       } else {
                is_slave = 1;
+       }
 }
 
 cnodeid_t get_compact_nodeid(void)
@@ -362,6+369,24 @@ cnodeid_t get_compact_nodeid(void)
 
 #ifdef CONFIG_SMP
 
+/*
+ * Takes as first input the PROM assigned cpu id, and the kernel
+ * assigned cpu id as the second.
+ */
+static void alloc_cpupda(cpuid_t cpu, int cpunum)
+{
+       cnodeid_t       node;
+       nasid_t         nasid;
+
+       node = get_cpu_cnode(cpu);
+       nasid = COMPACT_TO_NASID_NODEID(node);
+
+       cputonasid(cpunum) = nasid;
+       cputocnode(cpunum) = node;
+       cputoslice(cpunum) = get_cpu_slice(cpu);
+       cpu_data[cpunum].p_cpuid = cpu;
+}
+
 void __init smp_callin(void)
 {
 #if 0
@@ -380,10+405,10 @@ int __init start_secondary(void)
        return cpu_idle();
 }
 
-static atomic_t numstarted = ATOMIC_INIT(0);
+static volatile cpumask_t boot_barrier;
+
 void cboot(void)
 {
-       atomic_inc(&numstarted);
        CPUMASK_CLRB(boot_barrier, getcpuid()); /* needs atomicity */
        per_cpu_init();
 #if 0
@@ -399,22+424,24 @@ void cboot(void)
 void allowboot(void)
 {
        int             num_cpus = 0;
-       cpuid_t         cpu;
+       cpuid_t         cpu, mycpuid = getcpuid();
        cnodeid_t       cnode;
        extern void     bootstrap(void);
 
        sn_mp_setup();
        /* Master has already done per_cpu_init() */
-       install_cpuintr(getcpuid());
+       install_cpuintr(smp_processor_id());
 #if 0
        bte_lateinit();
        ecc_init();
 #endif
 
+       replicate_kernel_text(numnodes);
        boot_barrier = boot_cpumask;
        /* Launch slaves. */
        for (cpu = 0; cpu < maxcpus; cpu++) {
-               if (cpu == smp_processor_id()) {
+               if (cpu == mycpuid) {
+                       alloc_cpupda(cpu, num_cpus);
                        num_cpus++;
                        /* We're already started, clear our bit */
                        CPUMASK_CLRB(boot_barrier, cpu);
@@ -433,6+460,7 @@ void allowboot(void)
                        p = init_task.prev_task;
                        sprintf(p->comm, "%s%d", "Idle", num_cpus);
                        init_tasks[num_cpus] = p;
+                       alloc_cpupda(cpu, num_cpus);
                        p->processor = num_cpus;
                        p->has_cpu = 1; /* we schedule the first task manually */
                        del_from_runqueue(p);
@@ -448,10+476,10 @@ void allowboot(void)
                         * created idle process, gp to the proc struct
                         * (so that current-> works).
                         */
-                       LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), 
-                               (launch_proc_t)bootstrap, 0, 
-                               (void *)((unsigned long)p+KERNEL_STACK_SIZE - 32),
-                               (void *)p);
+                       LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus), 
+                               (launch_proc_t)MAPPED_KERN_RW_TO_K0(bootstrap),
+                               0, (void *)((unsigned long)p + 
+                               KERNEL_STACK_SIZE - 32), (void *)p);
 
                        /*
                         * Now optimistically set the mapping arrays. We
@@ -461,13+489,18 @@ void allowboot(void)
                        __cpu_number_map[cpu] = num_cpus;
                        __cpu_logical_map[num_cpus] = cpu;
                        num_cpus++;
-                       /* smp_num_cpus++; Do after smp_send_reschedule works */
+                       /*
+                        * Wait this cpu to start up and initialize its hub,
+                        * and discover the io devices it will control.
+                        * 
+                        * XXX: We really want to fire up launch all the CPUs
+                        * at once.  We have to preserve the order of the
+                        * devices on the bridges first though.
+                        */
+                       while(atomic_read(&numstarted) != num_cpus);
                }
        }
 
-       /* while(atomic_read(&numstarted) != (maxcpus - num_cpus)) */
-       if (maxcpus > 1) while(atomic_read(&numstarted) == 0);
-       printk("Holding %d cpus slave\n", atomic_read(&numstarted));
 
 #ifdef LATER
        Wait logic goes here.
@@ -484,6+517,7 @@ void allowboot(void)
        cpu_io_setup();
        init_mfhi_war();
 #endif
+       smp_num_cpus = num_cpus;
 }
 
 #else /* CONFIG_SMP */
index 4ffd7f9..36a656c 100644 (file)
@@ -1,11+1,9 @@
-/* $Id: ip27-irq.c,v 1.9 2000/03/14 01:39:27 ralf Exp $
- *
+/*
  * ip27-irq.c: Highlevel interrupt handling for IP27 architecture.
  *
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/errno.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
+#include <linux/irq.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
 irq_cpustat_t irq_stat [NR_CPUS];
 
 extern asmlinkage void ip27_irq(void);
+extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[];
 int (*irq_cannonicalize)(int irq);
-int intr_connect_level(cpuid_t cpu, int bit);
-int intr_disconnect_level(cpuid_t cpu, int bit);
+int intr_connect_level(int cpu, int bit);
+int intr_disconnect_level(int cpu, int bit);
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
@@ -76,15+75,17 @@ unsigned long spurious_count = 0;
  * we need to map irq's up to at least bit 7 of the INT_MASK0_A register
  * since bits 0-6 are pre-allocated for other purposes.
  */
-#define IRQ_TO_SWLEVEL(i)      i + 7
-#define SWLEVEL_TO_IRQ(s)      s - 7
+#define IRQ_TO_SWLEVEL(cpu, i) i + 7
+#define SWLEVEL_TO_IRQ(cpu, s) s - 7
 /*
- * use these macros to get the encoded nasid, widget id, and real irq
+ * use these macros to get the encoded nasid and widget id
  * from the irq value
  */
-#define NASID_FROM_IRQ(i)       ((i >> 16)&(0xff))
-#define WID_FROM_IRQ(i)          ((i >> 8)&(0xff))
-#define IRQ_FROM_IRQ(i)               ((i)&(0xff))
+#define IRQ_TO_BUS(i)                  irq_to_bus[(i)]
+#define IRQ_TO_CPU(i)                  bus_to_cpu[IRQ_TO_BUS(i)]
+#define NASID_FROM_PCI_IRQ(i)          bus_to_nid[IRQ_TO_BUS(i)]
+#define WID_FROM_PCI_IRQ(i)            bus_to_wid[IRQ_TO_BUS(i)]
+#define        SLOT_FROM_PCI_IRQ(i)            irq_to_slot[i]
 
 void disable_irq(unsigned int irq_nr)
 {
@@ -104,7+105,7 @@ int get_irq_list(char *buf)
        int i, len = 0;
        struct irqaction * action;
 
-       for (i = 0 ; i < 32 ; i++) {
+       for (i = 0 ; i < NR_IRQS ; i++) {
                action = irq_action[i];
                if (!action) 
                        continue;
@@ -126,20+127,18 @@ int get_irq_list(char *buf)
  * do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts
  * have their own specific handlers).
  */
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+static void do_IRQ(cpuid_t thiscpu, int irq, struct pt_regs * regs)
 {
        struct irqaction *action;
-       int do_random, cpu;
+       int do_random;
 
-       cpu = smp_processor_id();
-       irq_enter(cpu, irq);
-       kstat.irqs[cpu][irq]++;
+       irq_enter(thiscpu, irq);
+       kstat.irqs[thiscpu][irq]++;
 
        action = *(irq + irq_action);
        if (action) {
                if (!(action->flags & SA_INTERRUPT))
                        __sti();
-               action = *(irq + irq_action);
                do_random = 0;
                do {
                        do_random |= action->flags;
@@ -150,7+149,7 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
                        add_interrupt_randomness(irq);
                __cli();
        }
-       irq_exit(cpu, irq);
+       irq_exit(thiscpu, irq);
 
        /* unmasking and bottom half handling is done magically for us. */
 }
@@ -171,31+170,46 @@ static int ms1bit(unsigned long x)
 
        return b + (int) (x >> 1);
 }
-       
-/* For now ...  */
+
+/*
+ * This code is unnecessarily complex, because we do SA_INTERRUPT
+ * intr enabling. Basically, once we grab the set of intrs we need
+ * to service, we must mask _all_ these interrupts; firstly, to make
+ * sure the same intr does not intr again, causing recursion that 
+ * can lead to stack overflow. Secondly, we can not just mask the
+ * one intr we are do_IRQing, because the non-masked intrs in the
+ * first set might intr again, causing multiple servicings of the
+ * same intr. This effect is mostly seen for intercpu intrs.
+ * Kanoj 05.13.00
+ */
 void ip27_do_irq(struct pt_regs *regs)
 {
        int irq, swlevel;
        hubreg_t pend0, mask0;
-       int pi_int_mask0 = ((cputoslice(smp_processor_id()) == 0) ?
+       cpuid_t thiscpu = smp_processor_id();
+       int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ?
                                        PI_INT_MASK0_A : PI_INT_MASK0_B);
 
        /* copied from Irix intpend0() */
        while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & 
                                (mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) {
-               pend0 &= mask0;
-               do {
-                       swlevel = ms1bit(pend0);
-                       LOCAL_HUB_S(pi_int_mask0, mask0 & ~(1 << swlevel));
-                       LOCAL_HUB_CLR_INTR(swlevel);
-                       /* "map" swlevel to irq */
-                       irq = SWLEVEL_TO_IRQ(swlevel);
-                       do_IRQ(irq, regs);
-                       /* reset INT_MASK0 register */
+               pend0 &= mask0;         /* Pick intrs we should look at */
+               if (pend0) {
+                       /* Prevent any of the picked intrs from recursing */
+                       LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0));
+                       do {
+                               swlevel = ms1bit(pend0);
+                               LOCAL_HUB_CLR_INTR(swlevel);
+                               /* "map" swlevel to irq */
+                               irq = SWLEVEL_TO_IRQ(thiscpu, swlevel);
+                               do_IRQ(thiscpu, irq, regs);
+                               /* clear bit in pend0 */
+                               pend0 ^= 1ULL << swlevel;
+                       } while(pend0);
+                       /* Now allow the set of serviced intrs again */
                        LOCAL_HUB_S(pi_int_mask0, mask0);
-                       /* clear bit in pend0 */
-                       pend0 ^= 1ULL << swlevel;
-               } while (pend0);
+                       LOCAL_HUB_L(PI_INT_PEND0);
+               }
        }
 }
 
@@ -203,69+217,38 @@ void ip27_do_irq(struct pt_regs *regs)
 /* Startup one of the (PCI ...) IRQs routes over a bridge.  */
 static unsigned int bridge_startup(unsigned int irq)
 {
-        bridge_t *bridge;
-        int pin, swlevel;
-        int real_irq = IRQ_FROM_IRQ(irq);
-
-       DBG("bridge_startup(): irq= 0x%x  real_irq= %d\n", irq, real_irq);
-        bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
-
-        /* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
-           setup in _my_ Origin.  */
-
-        if (irq != real_irq)            /* pci device interrupt */
-                switch (real_irq) {
-                        case IRQ_FROM_IRQ(IOC3_ETH_INT):        pin = 2; break;
-                       default:                  pin = real_irq; break;
-                }
-        else
-                switch (real_irq) {
-                        case CPU_RESCHED_A_IRQ:
-                        case CPU_RESCHED_B_IRQ:
-                        case CPU_CALL_A_IRQ:
-                        case CPU_CALL_B_IRQ:
-                                                return 0;
-                        default:                panic("bridge_startup: whoops? %d\n", irq);
-                }
-
-        /*
-         * "map" irq to a swlevel greater than 6 since the first 6 bits
-         * of INT_PEND0 are taken
-         */
-        swlevel = IRQ_TO_SWLEVEL(real_irq);
-        intr_connect_level(smp_processor_id(), swlevel);
-
-        bridge->b_int_addr[pin].addr = 0x20000 | swlevel;
-        bridge->b_int_enable |= (1 << pin);
-       /* set more stuff in int_enable reg */
+       bridgereg_t device;
+       bridge_t *bridge;
+       int pin, swlevel;
+       cpuid_t cpu;
+       nasid_t master = NASID_FROM_PCI_IRQ(irq);
+
+        bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq));
+       pin = SLOT_FROM_PCI_IRQ(irq);
+       cpu = IRQ_TO_CPU(irq);
+
+       DBG("bridge_startup(): irq= 0x%x  pin=%d\n", irq, pin);
+       /*
+        * "map" irq to a swlevel greater than 6 since the first 6 bits
+        * of INT_PEND0 are taken
+        */
+       swlevel = IRQ_TO_SWLEVEL(cpu, irq);
+       intr_connect_level(cpu, swlevel);
+
+       bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8));
+       bridge->b_int_enable |= (1 << pin);
+       /* more stuff in int_enable reg */
        bridge->b_int_enable |= 0x7ffffe00;
 
-        if (real_irq < 2 || real_irq==4 || real_irq==5) {
-                bridgereg_t device;
-#if 0
-                /*
-                 * Allocate enough RRBs on the bridge for the DMAs.
-                 * Right now allocating 2 RRBs on the normal channel
-                 * and 2 on the virtual channel for slot 0 on the bus.
-                 * And same for slot 1, to get ioc3 eth working.
-                 */
-                Not touching b_even_resp          /* boot doesn't go far */
-                bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */
-                bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */
-                bridge->b_even_resp = 0xcc88;     /* breaks eth0 */
-#endif
-                /* Turn on bridge swapping */
-                device = bridge->b_device[real_irq].reg;
-                device |= BRIDGE_DEV_SWAP_DIR;
-                bridge->b_device[real_irq].reg = device;
-                /*
-                 * Associate interrupt pin with device
-                 * XXX This only works if b_int_device is initialized to 0!
-                 */
-                device = bridge->b_int_device;
-                device |= (pin << (real_irq*3));
-                bridge->b_int_device = device;
-        }
+       /*
+        * XXX This only works if b_int_device is initialized to 0!
+        * We program the bridge to have a 1:1 mapping between devices
+        * (slots) and intr pins.
+        */
+       device = bridge->b_int_device;
+       device |= (pin << (pin*3));
+       bridge->b_int_device = device;
+
         bridge->b_widget.w_tflush;                      /* Flush */
 
         return 0;       /* Never anything pending.  */
@@ -274,70+257,25 @@ static unsigned int bridge_startup(unsigned int irq)
 /* Shutdown one of the (PCI ...) IRQs routes over a bridge.  */
 static unsigned int bridge_shutdown(unsigned int irq)
 {
-        bridge_t *bridge;
-        int pin, swlevel;
-        int real_irq = IRQ_FROM_IRQ(irq);
-        struct irqaction **p;
+       bridge_t *bridge;
+       int pin, swlevel;
 
-        bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
+       bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), 
+                                            WID_FROM_PCI_IRQ(irq));
        DBG("bridge_shutdown: irq 0x%x\n", irq);
-        /* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
-           setup in _my_ Origin.  */
-
-        if (irq != real_irq)            /* pci device interrupt */
-                switch (real_irq) {
-                        case IRQ_FROM_IRQ(IOC3_ETH_INT):        pin = 2; break;
-                       default:                  pin = real_irq; break;
-                }
-        else
-                switch (real_irq) {
-                        case CPU_RESCHED_A_IRQ:
-                        case CPU_RESCHED_B_IRQ:
-                        case CPU_CALL_A_IRQ:
-                        case CPU_CALL_B_IRQ:
-                                                return 0;
-                        default:                panic("bridge_startup: whoops?");
-                }
-
-        /*
-         * map irq to a swlevel greater than 6 since the first 6 bits
-         * of INT_PEND0 are taken
-         */
-        swlevel = IRQ_TO_SWLEVEL(real_irq);
-        intr_disconnect_level(smp_processor_id(), swlevel);
-
-        bridge->b_int_enable &= ~(1 << pin);
-        bridge->b_widget.w_tflush;                      /* Flush */
+       pin = SLOT_FROM_PCI_IRQ(irq);
 
-        return 0;       /* Never anything pending.  */
-}
+       /*
+        * map irq to a swlevel greater than 6 since the first 6 bits
+        * of INT_PEND0 are taken
+        */
+       swlevel = IRQ_TO_SWLEVEL(cpu, irq);
+       intr_disconnect_level(smp_processor_id(), swlevel);
 
-static void bridge_init(void)
-{
-       bridge_t *bridge;
-       nasid_t   nasid;
-        char    wid;
-        int     bus;
-
-        nasid = get_nasid();
-
-        for (bus=0; bus<num_bridges; bus++) {
-          bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus],bus_to_wid[bus]);          
-          /* Hmm...  IRIX sets additional bits in the address which are
-             documented as reserved in the bridge docs ...  */
-          bridge->b_int_mode = 0x0;                     /* Don't clear ints */
-#if 0
-          bridge->b_wid_int_upper = 0x000a8000;           /* Ints to node 0 */
-          bridge->b_wid_int_lower = 0x01000090;
-          bridge->b_dir_map = 0xa00000;                 /* DMA */
-#endif /* shouldn't lower= 0x01800090 ??? */
-          bridge->b_wid_int_upper = 0x000a8000;           /* Ints to widget A */
-          bridge->b_wid_int_lower = 0x01800090;
-          bridge->b_dir_map = 0xa00000;                   /* DMA */
-
-          bridge->b_int_enable = 0;
-          bridge->b_widget.w_tflush;                    /* Flush */
-        }
+       bridge->b_int_enable &= ~(1 << pin);
+       bridge->b_widget.w_tflush;                      /* Flush */
+
+       return 0;       /* Never anything pending.  */
 }
 
 void irq_debug(void)
@@ -346,8+284,8 @@ void irq_debug(void)
 
        printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status);
        printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable);
-       printk("PI_INT_PEND0   = 0x%x\n", LOCAL_HUB_L(PI_INT_PEND0));
-       printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A));
+       printk("PI_INT_PEND0   = 0x%lx\n", LOCAL_HUB_L(PI_INT_PEND0));
+       printk("PI_INT_MASK0_A = 0x%lx\n", LOCAL_HUB_L(PI_INT_MASK0_A));
 }
 
 int setup_irq(unsigned int irq, struct irqaction *new)
@@ -357,11+295,15 @@ int setup_irq(unsigned int irq, struct irqaction *new)
        unsigned long flags;
 
        DBG("setup_irq: 0x%x\n", irq);
+       if (irq >= NR_IRQS) {
+               printk("IRQ array overflow %d\n", irq);
+               while(1);
+       }
        if (new->flags & SA_SAMPLE_RANDOM)
                rand_initialize_irq(irq);
 
        save_and_cli(flags);
-       p = irq_action + IRQ_FROM_IRQ(irq);
+       p = irq_action + irq;
        if ((old = *p) != NULL) {
                /* Can't share interrupts unless both agree to */
                if (!(old->flags & new->flags & SA_SHIRQ)) {
@@ -379,7+321,7 @@ int setup_irq(unsigned int irq, struct irqaction *new)
 
        *p = new;
 
-       if (!shared) {
+       if ((!shared) && (irq >= BASE_PCI_IRQ)) {
                bridge_startup(irq);
        }
        restore_flags(flags);
@@ -395,8+337,6 @@ int request_irq(unsigned int irq,
        struct irqaction *action;
 
        DBG("request_irq(): irq= 0x%x\n", irq);
-       if (IRQ_FROM_IRQ(irq) > 9)
-               return -EINVAL;
        if (!handler)
                return -EINVAL;
 
@@ -424,18+364,18 @@ void free_irq(unsigned int irq, void *dev_id)
        struct irqaction * action, **p;
        unsigned long flags;
 
-       if (IRQ_FROM_IRQ(irq) > 9) {
+       if (irq >= NR_IRQS) {
                printk("Trying to free IRQ%d\n", irq);
                return;
        }
-       for (p = IRQ_FROM_IRQ(irq) + irq_action; (action = *p) != NULL; p = &action->next) {
+       for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
                if (action->dev_id != dev_id)
                        continue;
 
                /* Found it - now free it */
                save_and_cli(flags);
                *p = action->next;
-               if (!irq[irq_action])
+               if (irq >= BASE_PCI_IRQ)
                        bridge_shutdown(irq);
                restore_flags(flags);
                kfree(action);
@@ -465,7+405,6 @@ void __init init_IRQ(void)
 {
        irq_cannonicalize = indy_irq_cannonicalize;
 
-       bridge_init();
        set_except_vector(0, ip27_irq);
 }
 
@@ -675,7+614,7 @@ static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit,
        return hub_intmasks;
 }
 
-int intr_connect_level(cpuid_t cpu, int bit)
+int intr_connect_level(int cpu, int bit)
 {
        int ip;
        int slice = cputoslice(cpu);
@@ -701,7+640,7 @@ int intr_connect_level(cpuid_t cpu, int bit)
        return(0);
 }
 
-int intr_disconnect_level(cpuid_t cpu, int bit)
+int intr_disconnect_level(int cpu, int bit)
 {
        int ip;
        int slice = cputoslice(cpu);
@@ -728,11+667,14 @@ void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs)
        /* Nothing, the return from intr will work for us */
 }
 
-void install_cpuintr(cpuid_t cpu)
+extern void smp_call_function_interrupt(void);
+
+void install_cpuintr(int cpu)
 {
-       int irq;
-       extern void smp_call_function_interrupt(void);
+#ifdef CONFIG_SMP
+#if (CPUS_PER_NODE == 2)
        static int done = 0;
+       int irq;
 
        /*
         * This is a hack till we have a pernode irqlist. Currently,
@@ -740,15+682,13 @@ void install_cpuintr(cpuid_t cpu)
         * cpu irqs.
         */
 
-#ifdef CONFIG_SMP
-#if (CPUS_PER_NODE == 2)
        irq = CPU_RESCHED_A_IRQ + cputoslice(cpu);
-       intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+       intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq));
        if (done == 0)
        if (request_irq(irq, handle_resched_intr, 0, "resched", 0))
                panic("intercpu intr unconnectible\n");
        irq = CPU_CALL_A_IRQ + cputoslice(cpu);
-       intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+       intr_connect_level(cpu, IRQ_TO_SWLEVEL(cpu, irq));
        if (done == 0)
        if (request_irq(irq, smp_call_function_interrupt, 0,
                                                "callfunc", 0))
@@ -766,12+706,12 @@ void install_cpuintr(cpuid_t cpu)
        done = 1;
        /* HACK ENDS */
 #else /* CPUS_PER_NODE */
-       << Bomb!  Must redefine this for more than 2 CPUS. >>
+#error Must redefine this for more than 2 CPUS.
 #endif /* CPUS_PER_NODE */
 #endif /* CONFIG_SMP */
 }
 
-void install_tlbintr(cpuid_t cpu)
+void install_tlbintr(int cpu)
 {
        int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu);
 
index fac7c9d..bfa1767 100644 (file)
@@ -61,7+61,7 @@ lboard_t * find_lboard(lboard_t *start, unsigned char brd_type)
        return (lboard_t *)NULL;
 }
 
-cnodeid_t get_cpu_cnode(int cpu)
+cnodeid_t get_cpu_cnode(cpuid_t cpu)
 {
        return CPUID_TO_COMPACT_NODEID(cpu);
 }
diff --git a/arch/mips64/sgi-ip27/ip27-klnuma.c b/arch/mips64/sgi-ip27/ip27-klnuma.c
new file mode 100644 (file)
index 0000000..84d1a54
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mmzone.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/sn/types.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/mmzone.h>
+#include <asm/sn/klkernvars.h>
+#include <asm/sn/mapped_kernel.h>
+#include <asm/sn/sn_private.h>
+
+#define CPUMASK_CLRALL(p)      (p) = 0
+#define CPUMASK_SETB(p, bit)   (p) |= 1 << (bit)
+#define CPUMASK_TSTB(p, bit)   ((p) & (1ULL << (bit)))
+
+extern char _end;
+static cpumask_t ktext_repmask;
+
+/*
+ * XXX - This needs to be much smarter about where it puts copies of the
+ * kernel.  For example, we should never put a copy on a headless node,
+ * and we should respect the topology of the machine.
+ */
+void __init setup_replication_mask(int maxnodes)
+{
+       static int      numa_kernel_replication_ratio;
+       cnodeid_t       cnode;
+
+       /* Set only the master cnode's bit.  The master cnode is always 0. */
+       CPUMASK_CLRALL(ktext_repmask);
+       CPUMASK_SETB(ktext_repmask, 0);
+
+       numa_kernel_replication_ratio = 0;
+#ifdef CONFIG_REPLICATE_KTEXT
+#ifndef CONFIG_MAPPED_KERNEL
+#error Kernel replication works with mapped kernel support. No calias support.
+#endif
+       numa_kernel_replication_ratio = 1;
+#endif
+
+       for (cnode = 1; cnode < numnodes; cnode++) {
+               /* See if this node should get a copy of the kernel */
+               if (numa_kernel_replication_ratio &&
+                   !(cnode % numa_kernel_replication_ratio)) {
+
+                       /* Advertise that we have a copy of the kernel */
+                       CPUMASK_SETB(ktext_repmask, cnode);
+               }
+       }
+
+       /* Set up a GDA pointer to the replication mask. */
+       GDA->g_ktext_repmask = &ktext_repmask;
+}
+
+
+static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
+{
+       kern_vars_t *kvp;
+       cnodeid_t client_cnode;
+
+       client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
+       
+       kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars);
+
+       KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
+
+       kvp->kv_magic = KV_MAGIC;
+
+       kvp->kv_ro_nasid = server_nasid;
+       kvp->kv_rw_nasid = master_nasid;
+       kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid);
+       kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid);
+       printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid);
+}
+
+/* XXX - When the BTE works, we should use it instead of this. */
+static __init void copy_kernel(nasid_t dest_nasid)
+{
+       extern char _stext, _etext;
+       unsigned long dest_kern_start, source_start, source_end, kern_size;
+
+       source_start = (unsigned long)&_stext;
+       source_end = (unsigned long)&_etext;
+       kern_size = source_end - source_start;
+
+       dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start),
+                                           dest_nasid);
+       memcpy((void *)dest_kern_start, (void *)source_start, kern_size);
+}
+
+void __init replicate_kernel_text(int maxnodes)
+{
+       cnodeid_t cnode;
+       nasid_t client_nasid;
+       nasid_t server_nasid;
+
+       server_nasid = master_nasid;
+
+       /* Record where the master node should get its kernel text */
+       set_ktext_source(master_nasid, master_nasid);
+
+       for (cnode = 1; cnode < maxnodes; cnode++) {
+               client_nasid = COMPACT_TO_NASID_NODEID(cnode);
+
+               /* Check if this node should get a copy of the kernel */
+               if (CPUMASK_TSTB(ktext_repmask, cnode)) {
+                       server_nasid = client_nasid;
+                       copy_kernel(server_nasid);
+               }
+
+               /* Record where this node should get its kernel text */
+               set_ktext_source(client_nasid, server_nasid);
+       }
+}
+
+/*
+ * Return pfn of first free page of memory on a node. PROM may allocate
+ * data structures on the first couple of pages of the first slot of each 
+ * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
+ */
+pfn_t node_getfirstfree(cnodeid_t cnode)
+{
+       unsigned long loadbase = CKSEG0;
+       nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
+       unsigned long offset;
+
+#ifdef CONFIG_MAPPED_KERNEL
+       loadbase = CKSSEG + 16777216;
+#endif
+       offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase;
+       if (cnode == 0)
+               return (offset >> PAGE_SHIFT);
+       else if (CPUMASK_TSTB(ktext_repmask, cnode))
+               return (TO_NODE(nasid, offset) >> PAGE_SHIFT);
+       else
+               return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> 
+                                                               PAGE_SHIFT);
+}
+
index fe27984..4900ff7 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/sn/arch.h>
 #include <asm/mmzone.h>
 
-typedef unsigned long pfn_t;                   /* into <asm/sn/types.h> */
-#define KDM_TO_PHYS(x) ((x) & TO_PHYS_MASK)    /* into asm/addrspace.h */
-
-extern char _end;
+/* ip27-klnuma.c   */
+extern pfn_t node_getfirstfree(cnodeid_t cnode);
 
 #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define SLOT_IGNORED   0xffff
@@ -38,7+35,6 @@ extern char _end;
 short slot_lastfilled_cache[MAX_COMPACT_NODES];
 unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS];
 static pfn_t numpages;
-static pfn_t pagenr = 0;
 
 plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES];
 bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES];
@@ -46,26+42,11 @@ bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES];
 int numa_debug(void)
 {
        printk("NUMA debug\n");
-       BUG();
+       *(int *)0 = 0;
        return(0);
 }
 
 /*
- * Return pfn of first free page of memory on a node. PROM may allocate
- * data structures on the first couple of pages of the first slot of each 
- * node. If this is the case, getfirstfree(node) > getslotstart(node, 0).
- */
-pfn_t node_getfirstfree(cnodeid_t cnode)
-{
-       nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
-
-       if (cnode == 0)
-               return (KDM_TO_PHYS(PAGE_ALIGN((unsigned long)(&_end)) - 
-                                       (CKSEG0 - K0BASE)) >> PAGE_SHIFT);
-       return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT);
-}
-
-/*
  * Return the number of pages of memory provided by the given slot
  * on the specified node.
  */
@@ -261,6+242,8 @@ prom_free_prom_memory (void)
 
 #ifdef CONFIG_DISCONTIGMEM
 
+static pfn_t pagenr = 0;
+
 void __init paging_init(void)
 {
        cnodeid_t node;
@@ -268,8+251,10 @@ void __init paging_init(void)
 
        /* Initialize the entire pgd.  */
        pgd_init((unsigned long)swapper_pg_dir);
-       pmd_init((unsigned long)invalid_pmd_table);
-       memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
+       pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
+       memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
+       pmd_init((unsigned long)empty_bad_pmd_table, (unsigned long)empty_bad_page_table);
+       memset((void *)empty_bad_page_table, 0, sizeof(pte_t) * PTRS_PER_PTE);
 
        for (node = 0; node < numnodes; node++) {
                pfn_t start_pfn = slot_getbasepfn(node, 0);
@@ -287,7+272,7 @@ void __init paging_init(void)
 
 void __init mem_init(void)
 {
-       extern char _ftext, _etext, _fdata, _edata;
+       extern char _stext, _etext, _fdata, _edata;
        extern char __init_begin, __init_end;
        extern unsigned long totalram_pages;
        extern unsigned long setup_zero_pages(void);
@@ -367,7+352,7 @@ void __init mem_init(void)
                }
        }
 
-       codesize =  (unsigned long) &_etext - (unsigned long) &_ftext;
+       codesize =  (unsigned long) &_etext - (unsigned long) &_stext;
        datasize =  (unsigned long) &_edata - (unsigned long) &_fdata;
        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
index 3511c62..baf8d70 100644 (file)
@@ -145,6+145,10 @@ cont_nmi_dump(void)
                                        cpu = CNODE_TO_CPU_BASE(node);
                                        for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) {
                                                CPUMASK_SETB(nmied_cpus, cpu);
+                                               /* 
+                                                * cputonasid, cputoslice
+                                                * needs kernel cpuid
+                                                */
                                                SEND_NMI((cputonasid(cpu)), (cputoslice(cpu)));
                                        }
                                }
index 75d966d..b4cd6ca 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: ip27-pci.c,v 1.8 2000/02/16 01:07:30 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
 #include <asm/sn/sn0/hub.h>
 
 /*
+ * Max #PCI busses we can handle; ie, max #PCI bridges.
+ */
+#define MAX_PCI_BUSSES         20
+
+/*
+ * Max #PCI devices (like scsi controllers) we handle on a bus.
+ */
+#define MAX_DEVICES_PER_PCIBUS 8
+
+/*
+ * No locking needed until PCI initialization is done parallely.
+ */
+int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS];
+int lastirq = BASE_PCI_IRQ;
+
+/*
+ * Translate from irq to software PCI bus number and PCI slot.
+ */
+int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS];
+
+/*
  * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
  * not really documented, so right now I can't write code which uses it.
  * Therefore we use type 0 accesses for now even though they won't work
@@ -123,13+144,12 @@ static struct pci_ops bridge_pci_ops = {
 void __init pcibios_init(void)
 {
        struct pci_ops *ops = &bridge_pci_ops;
-       nasid_t nid = get_nasid();
        int     i;
 
        ioport_resource.end = ~0UL;
 
        for (i=0; i<num_bridges; i++) {
-               printk("PCI: Probing PCI hardware on host bus %2d, node %d.\n", i, nid);
+               printk("PCI: Probing PCI hardware on host bus %2d.\n", i);
                pci_scan_bus(i, ops, NULL);
        }
 }
@@ -154,15+174,36 @@ pci_swizzle(struct pci_dev *dev, u8 *pinp)
        return PCI_SLOT(dev->devfn);
 }
 
-/* XXX This should include the node ID into the final interrupt number.  */
+/*
+ * All observed requests have pin == 1. We could have a global here, that
+ * gets incremented and returned every time - unfortunately, pci_map_irq
+ * may be called on the same device over and over, and need to return the
+ * same value. On o2000, pin can be 0 or 1, and PCI slots can be [0..7]. 
+ *
+ * A given PCI device, in general, should be able to intr any of the cpus
+ * on any one of the hubs connected to its xbow.
+ */
 static int __init
 pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       int rv;
-       rv = (slot + (((pin-1) & 1) << 2)) & 7;
-       rv |= (bus_to_wid[dev->bus->number] << 8);
-       rv |= (bus_to_nid[dev->bus->number] << 16);
-       return rv;
+       if ((dev->bus->number >= MAX_PCI_BUSSES) || (pin != 1) || \
+                                       (slot >= MAX_DEVICES_PER_PCIBUS)) {
+               printk("Increase supported PCI busses %d,%d,%d\n", \
+                                               dev->bus->number, slot, pin);
+               while(1);
+       }
+
+       /*
+        * Already assigned? Then return previously assigned value ...
+        */
+       if (irqstore[dev->bus->number][slot])
+               return(irqstore[dev->bus->number][slot]);
+       else {
+               lastirq++;      /* IOC3_ETH_INT hack */
+               irq_to_bus[lastirq] = dev->bus->number;
+               irq_to_slot[lastirq] = slot;
+               return(irqstore[dev->bus->number][slot] = lastirq);
+       }
 }
 
 void __init
@@ -222,8+263,41 @@ pcibios_setup(char *str)
 }
 
 static void __init
+pci_disable_swapping(struct pci_dev *dev)
+{
+       unsigned int bus_id = (unsigned) dev->bus->number;
+       bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
+                                    bus_to_wid[bus_id]);
+       int             slot = PCI_SLOT(dev->devfn);
+       bridgereg_t     devreg;
+
+       devreg = bridge->b_device[slot].reg;
+       devreg &= ~BRIDGE_DEV_SWAP_DIR;         /* turn off byte swapping */
+       bridge->b_device[slot].reg = devreg;
+
+       bridge->b_widget.w_tflush;              /* Flush */
+}
+
+static void __init
+pci_enable_swapping(struct pci_dev *dev)
+{
+       unsigned int bus_id = (unsigned) dev->bus->number;
+       bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
+                                    bus_to_wid[bus_id]);
+       int             slot = PCI_SLOT(dev->devfn);
+       bridgereg_t     devreg;
+
+       devreg = bridge->b_device[slot].reg;
+       devreg |= BRIDGE_DEV_SWAP_DIR;          /* turn on byte swapping */
+       bridge->b_device[slot].reg = devreg;
+
+       bridge->b_widget.w_tflush;              /* Flush */
+}
+
+static void __init
 pci_fixup_ioc3(struct pci_dev *d)
 {
+       unsigned int bus_id = (unsigned) d->bus->number;
        int i;
 
        /* IOC3 only decodes 0x20 bytes of the config space, so we end up
@@ -232,6+306,9 @@ pci_fixup_ioc3(struct pci_dev *d)
           use INTA.  */
        printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name);
 
+       d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]);
+       d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]);
+
        for (i = 1; i <= PCI_ROM_RESOURCE; i++) {
                d->resource[i].start = 0UL;
                d->resource[i].end = 0UL;
@@ -240,6+317,8 @@ pci_fixup_ioc3(struct pci_dev *d)
        d->subsystem_vendor = 0;
        d->subsystem_device = 0;
        d->irq = 1;
+
+       pci_disable_swapping(d);
 }
 
 static void __init
@@ -247,24+326,25 @@ pci_fixup_isp1020(struct pci_dev *d)
 {
        unsigned short command;
 
+       d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32);
        printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name);
 
        /* Configure device to allow bus mastering, i/o and memory mapping. 
         * Older qlogicisp driver expects to have the IO space enable 
-        * bit set. Things stop working if we program the controllers as not having
-        * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
+        * bit set. Things stop working if we program the controllers as not 
+        * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
         */
 
-       /* only turn on scsi's on main bus */
-       if (d->bus->number == 0) {
-               pci_set_master(d);
-               pci_read_config_word(d, PCI_COMMAND, &command);
-               command |= PCI_COMMAND_MEMORY;
-               command |= PCI_COMMAND_IO;
-               pci_write_config_word(d, PCI_COMMAND, command);
-               d->resource[1].flags |= 1;
-       }
+       pci_set_master(d);
+       pci_read_config_word(d, PCI_COMMAND, &command);
+       command |= PCI_COMMAND_MEMORY;
+       command |= PCI_COMMAND_IO;
+       pci_write_config_word(d, PCI_COMMAND, command);
+       d->resource[1].flags |= 1;
+
+       pci_enable_swapping(d);
 }
+
 static void __init
 pci_fixup_isp2x00(struct pci_dev *d)
 {
@@ -280,7+360,7 @@ pci_fixup_isp2x00(struct pci_dev *d)
        printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name);
 
        /* set the resource struct for this device */
-       start = (u32) bridge;   /* yes, we want to lose the upper 32 bits here */
+       start = (u32) (u64)bridge;      /* yes, we want to lose the upper 32 bits here */
        start |= BRIDGE_DEVIO(slot);
 
        d->resource[0].start = start;
@@ -298,12+378,10 @@ pci_fixup_isp2x00(struct pci_dev *d)
        /* point device(x) to it appropriate small window */
        devreg &= ~BRIDGE_DEV_OFF_MASK;
        devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK;
-
-       /* turn on byte swapping in direct map mode (how we currently run dma's) */
-       devreg |= BRIDGE_DEV_SWAP_DIR;          /* turn on byte swapping */
-
        bridge->b_device[slot].reg = devreg;
 
+       pci_enable_swapping(d);
+
        /* set card's base addr reg */
        //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001);
        //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000);
@@ -317,7+395,6 @@ pci_fixup_isp2x00(struct pci_dev *d)
        pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start);
        //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000));
 
-
        /* set cache line size */
        pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080);
 
@@ -329,7+406,7 @@ pci_fixup_isp2x00(struct pci_dev *d)
        /* set host error field */
        bridge->b_int_host_err = 0x44;
        bridge->b_wid_tflush;
-               
+
        bridge->b_wid_tflush;           /* wait until Bridge PIO complete */
        for (i=0; i<8; i++)
                printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg);
index 388fb60..40eff73 100644 (file)
-/* $Id$
- *
+/*
  * 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.
  *
  * Reset an IP27.
  *
- * Copyright (C) 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/sgialib.h>
-#include <asm/sgi/sgihpc.h>
-#include <asm/sgi/sgint23.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/gda.h>
@@ -30,10+27,14 @@ void machine_restart(char *command) __attribute__((noreturn));
 void machine_halt(void) __attribute__((noreturn));
 void machine_power_off(void) __attribute__((noreturn));
 
+#define noreturn while(1);                             /* Silence gcc.  */
+
 /* XXX How to pass the reboot command to the firmware??? */
 void machine_restart(char *command)
 {
+#if 0
        int i;
+#endif
 
        printk("Reboot started from CPU %d\n", smp_processor_id());
 #ifdef CONFIG_SMP
@@ -42,20+43,31 @@ void machine_restart(char *command)
 #if 0
        for (i = 0; i < numnodes; i++)
                REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, 
-                                                       PROMOP_RESTART);
+                                                       PROMOP_REBOOT);
 #else
        LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
 #endif
+       noreturn;
 }
 
 void machine_halt(void)
 {
-       ArcEnterInteractiveMode();
+       int i;
+
+#ifdef CONFIG_SMP
+       smp_send_stop();
+#endif
+       for (i = 0; i < numnodes; i++)
+               REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, 
+                                                       PROMOP_RESTART);
+       LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+       noreturn;
 }
 
 void machine_power_off(void)
 {
        /* To do ...  */
+       noreturn;
 }
 
 void ip27_reboot_setup(void)
index 74381a5..fbd8d1f 100644 (file)
-/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 ralf Exp $
- *
+/*
  * 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.
  *
  * SGI IP27 specific setup.
  *
- * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copyright (C) 1999 Silcon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sn0/addrs.h>
 #include <asm/sn/sn0/hubni.h>
 #include <asm/pci/bridge.h>
 #include <asm/paccess.h>
 #include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hubio.h>
 
 /* Check against user dumbness.  */
 #ifdef CONFIG_VT
@@ -101,27+104,32 @@ static void __init verify_mode(void)
 #define XXBOW_WIDGET_PART_NUM   0xd000          /* Xbridge */
 #define BASE_XBOW_PORT         8     /* Lowest external port */
 
-static void __init pcibr_setup(void)
+unsigned int bus_to_cpu[256];
+
+void __init pcibr_setup(cnodeid_t nid)
 {
-       int                     i;
+       int                     i, start, num, masterwid;
        bridge_t                *bridge; 
        volatile u64            hubreg;
-       nasid_t                 nasid;
+       nasid_t                 nasid, masternasid;
        xwidget_part_num_t      partnum;
        widgetreg_t             widget_id;
+       static spinlock_t       pcibr_setup_lock = SPIN_LOCK_UNLOCKED;
 
-       num_bridges = 0;
        /*
         * find what's on our local node
         */
-       nasid = 0;
-       hubreg = LOCAL_HUB_L(IIO_LLP_CSR);
+       spin_lock(&pcibr_setup_lock);
+       start = num_bridges;            /* Remember where we start from */
+       nasid = COMPACT_TO_NASID_NODEID(nid);
+       hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
        if (hubreg & IIO_LLP_CSR_IS_UP) {
                /* link is up */
                widget_id = *(volatile widgetreg_t *)
                         (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
                partnum = XWIDGET_PART_NUM(widget_id);
-               printk("pcibr_setup(): found partnum= 0x%x ", partnum);
+               printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x",
+                                       smp_processor_id(), nasid, partnum);
                if (partnum == BRIDGE_WIDGET_PART_NUM) {
                        /*
                         * found direct connected bridge so must be Origin200
@@ -130,8+138,7 @@ static void __init pcibr_setup(void)
                        num_bridges = 1;
                        bus_to_wid[0] = 0x8;
                        bus_to_nid[0] = 0;
-               }
-               if (partnum == XBOW_WIDGET_PART_NUM) {
+               } else if (partnum == XBOW_WIDGET_PART_NUM) {
                        lboard_t *brd;
                        klxbow_t *xbow_p;
                        /*
@@ -144,11+151,32 @@ static void __init pcibr_setup(void)
                                    KLTYPE_MIDPLANE8)) == NULL)
                                printk("argh\n");
                        else
-                               printk("brd= 0x%x\n", brd);
+                               printk("brd = 0x%lx\n", (unsigned long) brd);
                        if ((xbow_p = (klxbow_t *)
                             find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
                                printk("argh\n");
                        else {
+                          /*
+                           * Okay, here's a xbow. Lets arbitrate and find
+                           * out if we should initialize it. Set hub connected
+                           * at highest or lowest widget as master.
+                           * This algo needs to change a little for headless
+                           * nodes.
+                           */
+#ifdef WIDGET_A
+                          i = HUB_WIDGET_ID_MAX + 1;
+                          do {
+                               i--;
+                          } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#else
+                          i = HUB_WIDGET_ID_MIN - 1;
+                          do {
+                               i++;
+                          } while (!XBOW_PORT_TYPE_HUB(xbow_p, i));
+#endif
+                          masterwid = i;
+                          masternasid = XBOW_PORT_NASID(xbow_p, i);
+                          if (nasid == masternasid)
                           for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) {
                                if (!XBOW_PORT_IS_ENABLED(xbow_p, i))
                                        continue;
@@ -165,8+193,7 @@ static void __init pcibr_setup(void)
                                }
                           }
                        }
-               }
-               if (partnum == XXBOW_WIDGET_PART_NUM) {
+               } else if (partnum == XXBOW_WIDGET_PART_NUM) {
                        /*
                         * found xbridge, assume ibrick for now 
                         */
@@ -182,13+209,17 @@ static void __init pcibr_setup(void)
                        num_bridges = 3;
                }
        }
+       num = num_bridges - start;
+       spin_unlock(&pcibr_setup_lock);
        /*
          * set bridge registers
          */
-       for (i=0; i<num_bridges; i++) {
+       for (i = start; i < (start + num); i++) {
+
                DBG("pcibr_setup: bus= %d  bus_to_wid[%2d]= %d  bus_to_nid[%2d]= %d\n",
                         i, i, bus_to_wid[i], i, bus_to_nid[i]);
 
+               bus_to_cpu[i] = smp_processor_id();
                /*
                 * point to this bridge
                 */
@@ -207,6+238,19 @@ static void __init pcibr_setup(void)
                bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP;
                bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP;
 
+               /*
+                * Hmm...  IRIX sets additional bits in the address which 
+                * are documented as reserved in the bridge docs.
+                * We waste time programming b_wid_int_upper/b_wid_int_lower,
+                * since bridge_startup will set up the widget->nasid intr
+                * path anyway.
+                */
+               bridge->b_int_mode = 0x0;               /* Don't clear ints */
+               bridge->b_wid_int_upper = 0x000a8000;   /* Ints to widget A */
+               bridge->b_wid_int_lower = 0x01800090;
+               bridge->b_dir_map = 0xa00000;           /* DMA */
+               bridge->b_int_enable = 0;
+
                bridge->b_wid_tflush;     /* wait until Bridge PIO complete */
        }
 }
@@ -216,11+260,11 @@ void __init ip27_setup(void)
        nasid_t nid;
        hubreg_t p, e;
 
+       num_bridges = 0;
        /*
         * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
         */
        DBG("ip27_setup(): Entered.\n");
-       per_cpu_init();
        nid = get_nasid();
        printk("IP27: Running on node %d.\n", nid);
 
@@ -239,9+283,5 @@ void __init ip27_setup(void)
        verify_mode();
        ioc3_sio_init();
        ioc3_eth_init();
-
-       DBG("ip27_setup(): calling pcibr_setup\n");
-       /* set some bridge registers */
-       pcibr_setup();
-       DBG("ip27_setup(): Exit.\n");
+       per_cpu_init();
 }
index 7f19f5e..a6bcdcc 100644 (file)
@@ -1,9+1,7 @@
-/* $Id: ip27-timer.c,v 1.3 2000/02/18 09:54:40 ulfc Exp $
- *
- * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copytight (C) 1999 Silicon Graphics, Inc.
+/*
+ * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #define CYCLES_PER_SEC         (NSEC_PER_SEC/NSEC_PER_CYCLE)
 #define CYCLES_PER_JIFFY       (CYCLES_PER_SEC/HZ)
 
-static unsigned long ct_cur;           /* What counter should be at next timer irq */
+static unsigned long ct_cur[NR_CPUS];  /* What counter should be at next timer irq */
 static long last_rtc_update = 0;       /* Last time the rtc clock got updated */
 
 extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
 
 
 static int set_rtc_mmss(unsigned long nowtime)
@@ -91,26+90,28 @@ static int set_rtc_mmss(unsigned long nowtime)
 void rt_timer_interrupt(struct pt_regs *regs)
 {
        int cpu = smp_processor_id();
-       int cpuA = ((cputoslice(smp_processor_id())) == 0);
-       int user = user_mode(regs);
+       int cpuA = ((cputoslice(cpu)) == 0);
        int irq = 7;                            /* XXX Assign number */
 
        write_lock(&xtime_lock);
 
 again:
        LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);     /* Ack  */
-       ct_cur += CYCLES_PER_JIFFY;
-       LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur);
+       ct_cur[cpu] += CYCLES_PER_JIFFY;
+       LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
 
-       if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur)
+       if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
                goto again;
 
-       kstat.irqs[cpu][irq]++;         /* kstat+do_timer only for bootcpu? */
-       do_timer(regs);
+       kstat.irqs[cpu][irq]++;         /* kstat only for bootcpu? */
+
+       if (cpu == 0)
+               do_timer(regs);
 
 #ifdef CONFIG_SMP
        if (current->pid) {
                unsigned int *inc, *inc2;
+               int user = user_mode(regs);
 
                update_one_process(current, 1, user, !user, cpu);
                if (--current->counter <= 0) {
@@ -159,19+160,51 @@ again:
        write_unlock(&xtime_lock);
 }
 
+unsigned long inline do_gettimeoffset(void)
+{
+       unsigned long ct_cur1;
+       ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY;
+       return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000;
+}
+
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
+       unsigned long usec, sec;
 
        read_lock_irqsave(&xtime_lock, flags);
-       *tv = xtime;
+       usec = do_gettimeoffset();
+       {
+               unsigned long lost = lost_ticks;
+               if (lost)
+                       usec += lost * (1000000 / HZ);
+       }
+       sec = xtime.tv_sec;
+       usec += xtime.tv_usec;
        read_unlock_irqrestore(&xtime_lock, flags);
+
+       while (usec >= 1000000) {
+               usec -= 1000000;
+               sec++;
+       }
+
+       tv->tv_sec = sec;
+       tv->tv_usec = usec;
 }
 
 void do_settimeofday(struct timeval *tv)
 {
        write_lock_irq(&xtime_lock);
+       tv->tv_usec -= do_gettimeoffset();
+       tv->tv_usec -= lost_ticks * (1000000 / HZ);
+
+       while (tv->tv_usec < 0) {
+               tv->tv_usec += 1000000;
+               tv->tv_sec--;
+       }
+
        xtime = *tv;
+       time_adjust = 0;                /* stop active adjtime() */
        time_state = TIME_BAD;
        time_maxerror = MAXPHASE;
        time_esterror = MAXPHASE;
@@ -286,15+319,16 @@ void __init hub_rtc_init(cnodeid_t cnode)
         * node and timeouts will not happen there.
         */
        if (get_compact_nodeid() == cnode) {
+               int cpu = smp_processor_id();
                LOCAL_HUB_S(PI_RT_EN_A, 1);
                LOCAL_HUB_S(PI_RT_EN_B, 1);
                LOCAL_HUB_S(PI_PROF_EN_A, 0);
                LOCAL_HUB_S(PI_PROF_EN_B, 0);
-               ct_cur = CYCLES_PER_JIFFY;
-               LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+               ct_cur[cpu] = CYCLES_PER_JIFFY;
+               LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
                LOCAL_HUB_S(PI_RT_COUNT, 0);
                LOCAL_HUB_S(PI_RT_PEND_A, 0);
-               LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur);
+               LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
                LOCAL_HUB_S(PI_RT_COUNT, 0);
                LOCAL_HUB_S(PI_RT_PEND_B, 0);
        }
index 6a7d7de..3218bfe 100644 (file)
@@ -13,17+13,19 @@ TARGET      := $(TOPDIR)/include/asm-$(ARCH)/offset.h
 .S.o:
        $(CC) $(CFLAGS) -c $< -o $*.o
 
-all: $(TARGET)
-
 $(TARGET): offset.h
        cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET))
 
 offset.h: offset.s
        sed -n '/^@@@/s///p' $^ >$@
 
-offset.s: offset.c
+offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h
 
 clean:
        rm -f offset.[hs] $(TARGET).new
+       
+mrproper:      
+       rm -f offset.[hs] $(TARGET).new
+       rm -f $(TARGET)
 
 include $(TOPDIR)/Rules.make
index cc5dfe7..0813c95 100644 (file)
@@ -134,12+134,8 @@ CONFIG_INET=y
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
 CONFIG_IPV6=m
 # CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
index 5cd76d3..eede468 100644 (file)
@@ -27,6+27,7 @@ define_bool CONFIG_VT_CONSOLE y
 bool 'Symmetric multi-processing support' CONFIG_SMP
 
 # Global things across all Sun machines.
+define_bool CONFIG_HAVE_DEC_LOCK y
 define_bool CONFIG_ISA n
 define_bool CONFIG_PCMCIA n
 define_bool CONFIG_SBUS y
index 6612852..3cf68e2 100644 (file)
@@ -20,6+20,7 @@ CONFIG_KMOD=y
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_SMP is not set
+CONFIG_HAVE_DEC_LOCK=y
 # CONFIG_ISA is not set
 # CONFIG_PCMCIA is not set
 CONFIG_SBUS=y
@@ -155,12+156,8 @@ CONFIG_INET=y
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
-
-#
-# (it is safe to leave these untouched)
-#
-CONFIG_SKB_LARGE=y
 CONFIG_IPV6=m
 # CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
index 4460729..b066b8b 100644 (file)
@@ -325,7+325,7 @@ beyond_if:
                current->thread.flags |= SPARC_FLAG_32BIT;
        }
        start_thread32(regs, ex.a_entry, current->mm->start_stack);
-       if (current->flags & PF_PTRACED)
+       if (current->ptrace & PT_PTRACED)
                send_sig(SIGTRAP, current, 0);
        return 0;
 }
index 2ef0d10..40b12eb 100644 (file)
@@ -386,6+386,46 @@ void smp_cross_call(unsigned long *func, u32 ctx, u64 data1, u64 data2)
        }
 }
 
+struct call_data_struct {
+       void (*func) (void *info);
+       void *info;
+       atomic_t finished;
+       int wait;
+};
+
+extern unsigned long xcall_call_function;
+
+int smp_call_function(void (*func)(void *info), void *info,
+                     int nonatomic, int wait)
+{
+       struct call_data_struct data;
+       int cpus = smp_num_cpus - 1;
+
+       if (!cpus)
+               return 0;
+
+       data.func = func;
+       data.info = info;
+       atomic_set(&data.finished, 0);
+       data.wait = wait;
+
+       smp_cross_call(&xcall_call_function,
+                      0, (u64) &data, 0);
+       if (wait) {
+               while (atomic_read(&data.finished) != cpus)
+                       barrier();
+       }
+
+       return 0;
+}
+
+void smp_call_function_client(struct call_data_struct *call_data)
+{
+       call_data->func(call_data->info);
+       if (call_data->wait)
+               atomic_inc(&call_data->finished);
+}
+
 extern unsigned long xcall_flush_tlb_page;
 extern unsigned long xcall_flush_tlb_mm;
 extern unsigned long xcall_flush_tlb_range;
index 8b917e3..5d2dd29 100644 (file)
@@ -279,7+279,7 @@ char * getname32(const char *filename)
        char *tmp, *result;
 
        result = ERR_PTR(-ENOMEM);
-       tmp = (char *)__get_free_page(GFP_KERNEL);
+       tmp = __getname();
        if (tmp)  {
                int retval = do_getname32(filename, tmp);
 
index 548ef0a..6c2d54e 100644 (file)
@@ -1,5+1,5 @@
 # $Id: Makefile,v 1.22 2000/03/31 04:06:23 davem Exp $
-# Makefile for Sparc library files..
+# Makefile for Sparc64 library files..
 #
 
 CFLAGS := $(CFLAGS)
@@ -7,7+7,8 @@ CFLAGS := $(CFLAGS)
 OBJS  = PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
        memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \
        VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
-       VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o
+       VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
+       dec_and_lock.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
diff --git a/arch/sparc64/lib/dec_and_lock.S b/arch/sparc64/lib/dec_and_lock.S
new file mode 100644 (file)
index 0000000..dca825a
--- /dev/null
@@ -0,0 +1,61 @@
+/* $Id$
+ * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
+ *                 using cas and ldstub instructions.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+       .text
+       .align  64
+
+       /* CAS basically works like this:
+        *
+        * void CAS(MEM, REG1, REG2)
+        * {
+        *   START_ATOMIC();
+        *   if (*(MEM) == REG1) {
+        *     TMP = *(MEM);
+        *     *(MEM) = REG2;
+        *     REG2 = TMP;
+        *   }
+        *   END_ATOMIC();
+        * }
+        *
+        * All non-contention cases are handled in 2 I-cache
+        * lines which is 1 L2 cache line.
+        */
+
+       .globl  atomic_dec_and_lock
+atomic_dec_and_lock:   /* %o0 = counter, %o1 = lock */
+loop1: lduw    [%o0], %g5
+       subcc   %g5, 1, %g7
+       be,pn   %icc, to_zero
+        nop
+nzero: cas     [%o0], %g5, %g7
+       cmp     %g5, %g7
+       bne,pn  %icc, loop1
+        mov    0, %g1
+
+out:   retl
+        mov    %g1, %o0
+to_zero:ldstub [%o1], %g3
+       brnz,pn %g3, spin_on_lock
+        membar #StoreLoad | #StoreStore
+loop2: cas     [%o0], %g5, %g7         /* ASSERT(g7 == 0) */
+       brnz,pt %g7, out
+        mov    1, %g1
+
+       lduw    [%o0], %g5
+       subcc   %g5, 1, %g7
+       be,pn   %icc, loop2
+        nop
+       membar  #StoreStore | #LoadStore
+       stb     %g0, [%o1]
+       b,pt    %xcc, nzero
+        nop
+
+spin_on_lock:
+       ldub    [%o1], %g3
+       brnz,pt %g3, spin_on_lock
+        membar #LoadLoad
+       b,a,pt  %xcc, to_zero
index 90cc898..e954b24 100644 (file)
@@ -432,4+432,24 @@ xcall_flush_cache_all:
         nop
        flush           %g6
        retry
+
+       .globl          xcall_call_function
+xcall_call_function:
+       mov             TLB_TAG_ACCESS, %g5             ! wheee...
+       stxa            %g1, [%g5] ASI_IMMU             ! save call_data here for a bit
+       membar          #Sync
+       rdpr            %pstate, %g2
+       wrpr            %g2, PSTATE_IG | PSTATE_AG, %pstate
+       mov             TLB_TAG_ACCESS, %g2
+       ldxa            [%g2] ASI_IMMU, %g5
+       rdpr            %pil, %g2
+       wrpr            %g0, 15, %pil
+       sethi           %hi(109f), %g7
+       b,pt            %xcc, etrap_irq
+109:    or             %g7, %lo(109b), %g7
+       call            smp_call_function_client
+        mov            %l5, %o0
+       b,pt            %xcc, rtrap
+        clr            %l6
+
 #endif /* CONFIG_SMP */
index 5be9c5d..8200c83 100644 (file)
@@ -9,6+9,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/file.h>
index 943c7f8..a91c335 100644 (file)
@@ -86,7+86,7 @@ else
   endif
 endif 
 
-ifdef CONFIG_SGI_IP22
+ifdef CONFIG_SGI
 SUB_DIRS += sgi
 MOD_SUB_DIRS += sgi
 endif
index 2f01d3f..20e1c78 100644 (file)
 #include <linux/lvm.h>
 
 
-static char *lvm_snap_version = "LVM 0.8final (15/02/2000)\n";
+static char *lvm_snap_version __attribute__ ((unused)) = "LVM 0.8final (15/02/2000)\n";
 
 extern const char *const lvm_name;
 extern int lvm_blocksizes[];
index bff2d08..274f3a7 100644 (file)
@@ -75,6+75,7 @@ extern void pcwatchdog_init(void);
 extern int rtc_sun_init(void);         /* Combines MK48T02 and MK48T08 */
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
+extern int ds1286_init(void);
 extern int dsp56k_init(void);
 extern int radio_init(void);
 extern int pc110pad_init(void);
index 42063ce..a32cd18 100644 (file)
  * the kernel and is not a module. Since the functions are used by some Atari
  * drivers, this is the case on the Atari.
  *
+ *
+ *     1.1     Cesar Barros: SMP locking fixes
+ *             added changelog
  */
 
-#define NVRAM_VERSION          "1.0"
+#define NVRAM_VERSION          "1.1"
 
 #include <linux/module.h>
 #include <linux/config.h>
 #endif
 
 /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with
- * interrupts disabled. Due to the index-port/data-port design of the RTC, we
+ * rtc_lock held. Due to the index-port/data-port design of the RTC, we
  * don't want two different things trying to get to it at once. (e.g. the
  * periodic 11 min sync from time.c vs. this driver.)
  */
 #include <linux/nvram.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/spinlock.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+extern spinlock_t rtc_lock;
 
 static int nvram_open_cnt = 0; /* #times opened */
 static int nvram_open_mode;            /* special open modes */
@@ -163,21+168,20 @@ unsigned char nvram_read_byte( int i )
        unsigned long flags;
        unsigned char c;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave (&rtc_lock, flags);
        c = nvram_read_int( i );
-       restore_flags(flags);
+       spin_unlock_irqrestore (&rtc_lock, flags);
        return( c );
 }
 
+/* This races nicely with trying to read with checksum checking (nvram_read) */
 void nvram_write_byte( unsigned char c, int i )
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave (&rtc_lock, flags);
        nvram_write_int( c, i );
-       restore_flags(flags);
+       spin_unlock_irqrestore (&rtc_lock, flags);
 }
 
 int nvram_check_checksum( void )
@@ -185,10+189,9 @@ int nvram_check_checksum( void )
        unsigned long flags;
        int rv;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave (&rtc_lock, flags);
        rv = nvram_check_checksum_int();
-       restore_flags(flags);
+       spin_unlock_irqrestore (&rtc_lock, flags);
        return( rv );
 }
 
@@ -196,10+199,9 @@ void nvram_set_checksum( void )
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave (&rtc_lock, flags);
        nvram_set_checksum_int();
-       restore_flags(flags);
+       spin_unlock_irqrestore (&rtc_lock, flags);
 }
 
 #endif /* MACH == ATARI */
@@ -228,63+230,67 @@ static long long nvram_llseek(struct file *file,loff_t offset, int origin )
 static ssize_t nvram_read(struct file * file,
        char * buf, size_t count, loff_t *ppos )
 {
-       unsigned long flags;
+       char contents [NVRAM_BYTES];
        unsigned i = *ppos;
-       char *tmp = buf;
-       
-       if (i != *ppos)
-               return -EINVAL;
+       char *tmp;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irq (&rtc_lock);
        
-       if (!nvram_check_checksum_int()) {
-               restore_flags(flags);
-               return( -EIO );
-       }
+       if (!nvram_check_checksum_int())
+               goto checksum_err;
+
+       for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+               *tmp = nvram_read_int(i);
+
+       spin_unlock_irq (&rtc_lock);
+
+       copy_to_user_ret (buf, contents, tmp - contents, -EFAULT);
 
-       for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp )
-               put_user( nvram_read_int(i), tmp );
        *ppos = i;
 
-       restore_flags(flags);
-       return( tmp - buf );
+       return (tmp - contents);
+
+checksum_err:
+       spin_unlock_irq (&rtc_lock);
+       return -EIO;
 }
 
 static ssize_t nvram_write(struct file * file,
                const char * buf, size_t count, loff_t *ppos )
 {
-       unsigned long flags;
+       char contents [NVRAM_BYTES];
        unsigned i = *ppos;
-       const char *tmp = buf;
-       char c;
-       
-       if (i != *ppos)
-               return -EINVAL;
+       char * tmp;
 
-       save_flags(flags);
-       cli();
-       
-       if (!nvram_check_checksum_int()) {
-               restore_flags(flags);
-               return( -EIO );
-       }
+       /* could comebody please help me indent this better? */
+       copy_from_user_ret (contents, buf, (NVRAM_BYTES - i) < count ?
+                                               (NVRAM_BYTES - i) : count,
+                               -EFAULT);
+
+       spin_lock_irq (&rtc_lock);
+
+       if (!nvram_check_checksum_int())
+               goto checksum_err;
+
+       for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
+               nvram_write_int (*tmp, i);
 
-       for( ; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp ) {
-               get_user( c, tmp );
-               nvram_write_int( c, i );
-       }
        nvram_set_checksum_int();
+
+       spin_unlock_irq (&rtc_lock);
+
        *ppos = i;
 
-       restore_flags(flags);
-       return( tmp - buf );
+       return (tmp - contents);
+
+checksum_err:
+       spin_unlock_irq (&rtc_lock);
+       return -EIO;
 }
 
 static int nvram_ioctl( struct inode *inode, struct file *file,
                                                unsigned int cmd, unsigned long arg )
 {
-       unsigned long flags;
        int i;
        
        switch( cmd ) {
@@ -293,14+299,13 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
                if (!capable(CAP_SYS_ADMIN))
                        return( -EACCES );
 
-               save_flags(flags);
-               cli();
+               spin_lock_irq (&rtc_lock);
 
                for( i = 0; i < NVRAM_BYTES; ++i )
                        nvram_write_int( 0, i );
                nvram_set_checksum_int();
                
-               restore_flags(flags);
+               spin_unlock_irq (&rtc_lock);
                return( 0 );
          
          case NVRAM_SETCKS:            /* just set checksum, contents unchanged
@@ -309,10+314,9 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
                if (!capable(CAP_SYS_ADMIN))
                        return( -EACCES );
 
-               save_flags(flags);
-               cli();
+               spin_lock_irq (&rtc_lock);
                nvram_set_checksum_int();
-               restore_flags(flags);
+               spin_unlock_irq (&rtc_lock);
                return( 0 );
 
          default:
@@ -355,16+359,14 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset,
 static int nvram_read_proc( char *buffer, char **start, off_t offset,
                                                        int size, int *eof, void *data )
 {
-       unsigned long flags;
        unsigned char contents[NVRAM_BYTES];
     int i, len = 0;
     off_t begin = 0;
-       
-       save_flags(flags);
-       cli();
+
+       spin_lock_irq (&rtc_lock);
        for( i = 0; i < NVRAM_BYTES; ++i )
                contents[i] = nvram_read_int( i );
-       restore_flags(flags);
+       spin_unlock_irq (&rtc_lock);
        
        *eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size );
 
@@ -475,15+477,13 @@ static char *gfx_types[] = {
 static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len,
                                                  off_t *begin, off_t offset, int size )
 {
-       unsigned long flags;
        int checksum;
        int type;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irq (&rtc_lock);
        checksum = nvram_check_checksum_int();
-       restore_flags(flags);
-       
+       spin_unlock_irq (&rtc_lock);
+
        PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " );
 
        PRINT_PROC( "# floppies     : %d\n",
index 73171b4..105137a 100644 (file)
@@ -258,6+258,8 @@ static struct rs_multiport_struct rs_multiport[NR_IRQS];
 static int IRQ_timeout[NR_IRQS];
 #ifdef CONFIG_SERIAL_CONSOLE
 static struct console sercons;
+#endif
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) && !defined(MODULE)
 static unsigned long break_pressed; /* break, really ... */
 #endif
 
@@ -2048,7+2050,7 @@ static int set_serial_info(struct async_struct * info,
 
        new_port = new_serial.port;
        if (HIGH_BITS_OFFSET)
-               new_port += new_serial.port_high << HIGH_BITS_OFFSET;
+               new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;
 
        change_irq = new_serial.irq != state->irq;
        change_port = (new_port != ((int) state->port)) ||
@@ -4450,9+4452,10 @@ static struct pci_board pci_boards[] __initdata = {
        {       PCI_VENDOR_ID_ROCKWELL, 0x1004,
                0x1048, 0x1500, 
                SPCI_FL_BASE1, 1, 115200 },
-#if 0                  /* No definition for PCI_DEVICE_ID_NEC_NILE4 */
+#ifdef CONFIG_DDB5074
        /*
         * NEC Vrc-5074 (Nile 4) builtin UART.
+        * Conditionally compiled in since this is a motherboard device.
         */
        {       PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_NILE4,
                PCI_ANY_ID, PCI_ANY_ID,
@@ -5172,7+5175,7 @@ int register_serial(struct serial_struct *req)
 
        port = req->port;
        if (HIGH_BITS_OFFSET)
-               port += req->port_high << HIGH_BITS_OFFSET;
+               port += (unsigned long) req->port_high << HIGH_BITS_OFFSET;
 
        save_flags(flags); cli();
        for (i = 0; i < NR_PORTS; i++) {
index 5e722a9..60a5c41 100644 (file)
@@ -152,6+152,7 @@ extern void rs285_console_init(void);
 extern void rs285_init(void);
 extern void sa1100_rs_console_init(void);
 extern void sa1100_rs_init(void);
+extern void sgi_serial_console_init(void);
 
 #ifndef MIN
 #define MIN(a,b)       ((a) < (b) ? (a) : (b))
@@ -2168,9+2169,12 @@ void __init console_init(void)
 #ifdef CONFIG_SERIAL_CONSOLE
 #if (defined(CONFIG_8xx) || defined(CONFIG_8260))
        console_8xx_init();
-#elif defined(CONFIG_SERIAL)   
+#elif defined(CONFIG_SERIAL)
        serial_console_init();
 #endif /* CONFIG_8xx */
+#ifdef CONFIG_SGI_SERIAL
+       sgi_serial_console_init();
+#endif
 #if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
        vme_scc_console_init();
 #endif
index f0b95fd..0bcb9ed 100644 (file)
@@ -1115,26+1115,26 @@ static int __init i2c_init(void)
        extern int i2c_dev_init(void);
 #endif
 #ifdef CONFIG_I2C_ALGOBIT
-       extern int algo_bit_init(void);
+       extern int i2c_algo_bit_init(void);
 #endif
 #ifdef CONFIG_I2C_BITLP
-       extern int bitlp_init(void);
+       extern int i2c_bitlp_init(void);
 #endif
 #ifdef CONFIG_I2C_BITELV
-       extern int bitelv_init(void);
+       extern int i2c_bitelv_init(void);
 #endif
 #ifdef CONFIG_I2C_BITVELLE
-       extern int bitvelle_init(void);
+       extern int i2c_bitvelle_init(void);
 #endif
 #ifdef CONFIG_I2C_BITVIA
-       extern int bitvia_init(void);
+       extern int i2c_bitvia_init(void);
 #endif
 
 #ifdef CONFIG_I2C_ALGOPCF
-       extern int algo_pcf_init(void); 
+       extern int i2c_algo_pcf_init(void);     
 #endif
 #ifdef CONFIG_I2C_PCFISA
-       extern int pcfisa_init(void);
+       extern int i2c_pcfisa_init(void);
 #endif
 
 /* This is needed for automatic patch generation: sensors code starts here */
index 43838c6..88b3f8e 100644 (file)
@@ -2858,13+2858,16 @@ int __init ide_setup (char *s)
        const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
        const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
+       
+       if (strncmp(s,"hd",2) == 0 && s[2] == '=')      /* hd= is for hd.c   */
+               return 0;                               /* driver and not us */
+
        if (strncmp(s,"ide",3) &&
            strncmp(s,"idebus",6) &&
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
            strncmp(s,"splitfifo",9) &&
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
-           strncmp(s,"hdxlun",6) &&
-           (strncmp(s,"hd",2) && s[2] != '='))
+           strncmp(s,"hd",2))          /* hdx= & hdxlun= */
                return 0;
 
        printk("ide_setup: %s", s);
index 253338e..25257b0 100644 (file)
@@ -79,7+79,6 @@ extern int ni5010_probe(struct net_device *);
 extern int ni52_probe(struct net_device *);
 extern int ni65_probe(struct net_device *);
 extern int sonic_probe(struct net_device *);
-extern int ioc3_probe(struct net_device *);
 extern int SK_init(struct net_device *);
 extern int seeq8005_probe(struct net_device *);
 extern int smc_init( struct net_device * );
@@ -95,7+94,6 @@ extern int cs89x0_probe(struct net_device *dev);
 extern int ethertap_probe(struct net_device *dev);
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
-extern int dec_lance_probe(struct net_device *);
 extern int mvme147lance_probe(struct net_device *dev);
 extern int tc515_probe(struct net_device *dev);
 extern int lance_probe(struct net_device *dev);
@@ -373,12+371,6 @@ struct devprobe mips_probes[] __initdata = {
 #ifdef CONFIG_MIPS_JAZZ_SONIC
        {sonic_probe, 0},
 #endif
-#ifdef CONFIG_SGI_IOC3_ETH
-       {ioc3_probe, 0},
-#endif
-#ifdef CONFIG_DECLANCE         /* DECstation on-board controller */
-       {dec_lance_probe, 0},   /* and maybe TURBOchannel option boards */
-#endif
 #ifdef CONFIG_BAGETLANCE        /* Lance-based Baget ethernet boards */
         {bagetlance_probe, 0},
 #endif
index c294323..7ed3785 100644 (file)
@@ -1,8+1,10 @@
 /*
- * $Id: dmascc.c,v 1.3 1998/09/07 04:41:56 kudielka Exp $
+ * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $
  *
  * Driver for high-speed SCC boards (those with DMA support)
- * Copyright (C) 1997 Klaus Kudielka
+ * Copyright (C) 1997-2000 Klaus Kudielka
+ *
+ * S5SCC/DMA support by Janko Koleznik S52HI
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
  */
 
 
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/dmascc.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/in.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/netdevice.h>
+#include <linux/rtnetlink.h>
 #include <linux/sockios.h>
 #include <linux/tqueue.h>
 #include <linux/version.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <net/ax25.h>
 #include "z8530.h"
 
 
-/* Linux 2.0 compatibility */
-
-#if LINUX_VERSION_CODE < 0x20100
-
-
-#define __init
-#define __initdata
-#define __initfunc(x) x
-
-#define MODULE_AUTHOR(x)
-#define MODULE_DESCRIPTION(x)
-#define MODULE_PARM(x,y)
-
-#define copy_to_user(x,y,z) memcpy_tofs(x,y,z)
-#define copy_from_user(x,y,z) memcpy_fromfs(x,y,z)
-#define test_and_set_bit(x,y) set_bit(x,y)
-#define register_netdevice(x) register_netdev(x)
-#define unregister_netdevice(x) unregister_netdev(x)
-#define dev_kfree_skb(x) dev_kfree_skb(x,FREE_WRITE)
-#define SET_DEV_INIT(x) (x=dmascc_dev_init)
-
-#define SHDLCE  0x01 /* WR15 */
-
-#define AUTOEOM 0x02 /* WR7' */
-#define RXFIFOH 0x08
-#define TXFIFOE 0x20
-
-static int dmascc_dev_init(struct net_device *dev)
-{
-  return 0;
-}
-
-static void dev_init_buffers(struct net_device *dev)
-{
-  int i;
-
-  for (i = 0; i < DEV_NUMBUFFS; i++)
-    skb_queue_head_init(&dev->buffs[i]);
-}
-
-
-#else
-
-
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-#define SET_DEV_INIT(x)
-
+/* Linux 2.2 and 2.3 compatibility */
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14)
+#define net_device device
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43)
+#define netif_start_queue(dev) { dev->tbusy = 0; }
+#define netif_stop_queue(dev) { dev->tbusy = 1; }
+#define netif_wake_queue(dev) { dev->tbusy = 0; mark_bh(NET_BH); }
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47)
+#define netif_running(dev) (dev->flags & IFF_UP)
 #endif
 
 
 /* Number of buffers per channel */
 
-#define NUM_TX_BUF      2          /* NUM_TX_BUF >= 1 (2 recommended) */
-#define NUM_RX_BUF      2          /* NUM_RX_BUF >= 1 (2 recommended) */
-#define BUF_SIZE        2016
+#define NUM_TX_BUF      2          /* NUM_TX_BUF >= 1 (min. 2 recommended) */
+#define NUM_RX_BUF      6          /* NUM_RX_BUF >= 1 (min. 2 recommended) */
+#define BUF_SIZE        1576       /* BUF_SIZE >= mtu + hard_header_len */
 
 
 /* Cards supported */
@@ -112,13+79,18 @@ static void dev_init_buffers(struct net_device *dev)
                            0, 8, 3686400, 7372800 }
 #define HW_TWIN         { "Gracilis PackeTwin", 0x200, 0x10, 0x10, 32, \
                            0, 4, 6144000, 6144000 }
+#define HW_S5           { "S5SCC/DMA", 0x200, 0x10, 0x10, 32, \
+                          0, 8, 4915200, 9830400 }
+
+#define HARDWARE        { HW_PI, HW_PI2, HW_TWIN, HW_S5 }
 
-#define HARDWARE        { HW_PI, HW_PI2, HW_TWIN }
+#define TMR_0_HZ        25600      /* Frequency of timer 0 */
 
 #define TYPE_PI         0
 #define TYPE_PI2        1
 #define TYPE_TWIN       2
-#define NUM_TYPES       3
+#define TYPE_S5         3
+#define NUM_TYPES       4
 
 #define MAX_NUM_DEVS    32
 
@@ -188,16+160,44 @@ static void dev_init_buffers(struct net_device *dev)
 
 /* Status values */
 
-/* tx_state */
-#define TX_IDLE    0
-#define TX_OFF     1
-#define TX_TXDELAY 2
-#define TX_ACTIVE  3
-#define TX_SQDELAY 4
+#define IDLE      0
+#define TX_HEAD   1
+#define TX_DATA   2
+#define TX_PAUSE  3
+#define TX_TAIL   4
+#define RTS_OFF   5
+#define WAIT      6
+#define DCD_ON    7
+#define RX_ON     8
+#define DCD_OFF   9
+
+
+/* Ioctls */
+
+#define SIOCGSCCPARAM SIOCDEVPRIVATE
+#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
 
 
 /* Data types */
 
+struct scc_param {
+  int pclk_hz;    /* frequency of BRG input (don't change) */
+  int brg_tc;     /* BRG terminal count; BRG disabled if < 0 */
+  int nrzi;       /* 0 (nrz), 1 (nrzi) */
+  int clocks;     /* see dmascc_cfg documentation */
+  int txdelay;    /* [1/TMR_0_HZ] */
+  int txtimeout;  /* [1/HZ] */
+  int txtail;     /* [1/TMR_0_HZ] */
+  int waittime;   /* [1/TMR_0_HZ] */
+  int slottime;   /* [1/TMR_0_HZ] */
+  int persist;    /* 1 ... 256 */
+  int dma;        /* -1 (disable), 0, 1, 3 */
+  int txpause;    /* [1/TMR_0_HZ] */
+  int rtsoff;     /* [1/TMR_0_HZ] */
+  int dcdon;      /* [1/TMR_0_HZ] */
+  int dcdoff;     /* [1/TMR_0_HZ] */
+};
+
 struct scc_hardware {
   char *name;
   int io_region;
@@ -211,10+211,17 @@ struct scc_hardware {
 };
 
 struct scc_priv {
-  struct enet_statistics stats;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+  char name[IFNAMSIZ];
+#endif
+  int type;
+  int chip;
+  struct net_device *dev;
   struct scc_info *info;
+  struct net_device_stats stats;
   int channel;
-  int cmd, data, tmr;
+  int card_base, scc_cmd, scc_data;
+  int tmr_cnt, tmr_ctrl, tmr_mode;
   struct scc_param param;
   char rx_buf[NUM_RX_BUF][BUF_SIZE];
   int rx_len[NUM_RX_BUF];
@@ -226,17+233,13 @@ struct scc_priv {
   int tx_len[NUM_TX_BUF];
   int tx_ptr;
   int tx_head, tx_tail, tx_count;
-  int tx_sem, tx_state;
+  int state;
   unsigned long tx_start;
-  int status;
+  int rr0;
 };
 
 struct scc_info {
-  int type;
-  int chip;
-  int open;
-  int scc_base;
-  int tmr_base;
+  int irq_used;
   int twin_serial_cfg;
   struct net_device dev[2];
   struct scc_priv priv[2];
@@ -247,25+250,33 @@ struct scc_info {
 /* Function declarations */
 
 int dmascc_init(void) __init;
-static int setup_adapter(int io, int h, int n) __init;
+static int setup_adapter(int card_base, int type, int n) __init;
+
+static void write_scc(struct scc_priv *priv, int reg, int val);
+static void write_scc_data(struct scc_priv *priv, int val, int fast);
+static int read_scc(struct scc_priv *priv, int reg);
+static int read_scc_data(struct scc_priv *priv);
 
-static inline void write_scc(int ctl, int reg, int val);
-static inline int read_scc(int ctl, int reg);
 static int scc_open(struct net_device *dev);
 static int scc_close(struct net_device *dev);
 static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
 static int scc_send_packet(struct sk_buff *skb, struct net_device *dev);
-static struct enet_statistics *scc_get_stats(struct net_device *dev);
+static struct net_device_stats *scc_get_stats(struct net_device *dev);
 static int scc_set_mac_address(struct net_device *dev, void *sa);
+
 static void scc_isr(int irq, void *dev_id, struct pt_regs * regs);
 static inline void z8530_isr(struct scc_info *info);
-static void rx_isr(struct net_device *dev);
-static void special_condition(struct net_device *dev, int rc);
+static void rx_isr(struct scc_priv *priv);
+static void special_condition(struct scc_priv *priv, int rc);
 static void rx_bh(void *arg);
-static void tx_isr(struct net_device *dev);
-static void es_isr(struct net_device *dev);
-static void tm_isr(struct net_device *dev);
-static inline void delay(struct net_device *dev, int t);
+static void tx_isr(struct scc_priv *priv);
+static void es_isr(struct scc_priv *priv);
+static void tm_isr(struct scc_priv *priv);
+
+static inline void tx_on(struct scc_priv *priv);
+static inline void rx_on(struct scc_priv *priv);
+static inline void rx_off(struct scc_priv *priv);
+static void start_timer(struct scc_priv *priv, int t, int r15);
 static inline unsigned char random(void);
 
 
@@ -287,7+298,6 @@ static struct scc_info *first = NULL;
 static unsigned long rand;
 
 
-
 /* Module functions */
 
 #ifdef MODULE
@@ -298,14+308,12 @@ MODULE_DESCRIPTION("Driver for high-speed SCC boards");
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
 
 
-int init_module(void)
-{
+int init_module(void) {
   return dmascc_init();
 }
 
 
-void cleanup_module(void)
-{
+void cleanup_module(void) {
   int i;
   struct scc_info *info;
 
@@ -315,15+323,17 @@ void cleanup_module(void)
     /* Unregister devices */
     for (i = 0; i < 2; i++) {
       if (info->dev[i].name)
+       rtnl_lock();
        unregister_netdevice(&info->dev[i]);
+       rtnl_unlock();
     }
 
     /* Reset board */
-    if (info->type == TYPE_TWIN)
-      outb_p(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
-    write_scc(info->priv[0].cmd, R9, FHWRES);
+    if (info->priv[0].type == TYPE_TWIN)
+      outb(0, info->dev[0].base_addr + TWIN_SERIAL_CFG);
+    write_scc(&info->priv[0], R9, FHWRES);
     release_region(info->dev[0].base_addr,
-                  hw[info->type].io_size);
+                  hw[info->priv[0].type].io_size);
 
     /* Free memory */
     first = info->next;
@@ -335,8+345,7 @@ void cleanup_module(void)
 #else
 
 
-void __init dmascc_setup(char *str, int *ints)
-{
+void __init dmascc_setup(char *str, int *ints) {
    int i;
 
    for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
@@ -349,8+358,7 @@ void __init dmascc_setup(char *str, int *ints)
 
 /* Initialization functions */
 
-int __init dmascc_init(void)
-{
+int __init dmascc_init(void) {
   int h, i, j, n;
   int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
     t1[MAX_NUM_DEVS];
@@ -402,18+410,18 @@ int __init dmascc_init(void)
     for (i = 0; i < hw[h].num_devs; i++)
       if (base[i]) {
        /* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
-       outb_p(0x36, tcmd[i]);
-       outb_p((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
-       outb_p((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
+       outb(0x36, tcmd[i]);
+       outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
+       outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
        /* Timer 1: LSB+MSB, Mode 0, HZ/10 */
-       outb_p(0x70, tcmd[i]);
-       outb_p((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
-       outb_p((TMR_0_HZ/HZ*10) >> 8, t1[i]);
+       outb(0x70, tcmd[i]);
+       outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
+       outb((TMR_0_HZ/HZ*10) >> 8, t1[i]);
        start[i] = jiffies;
        delay[i] = 0;
        counting[i] = 1;
        /* Timer 2: LSB+MSB, Mode 0 */
-       outb_p(0xb0, tcmd[i]);
+       outb(0xb0, tcmd[i]);
       }
     time = jiffies;
     /* Wait until counter registers are loaded */
@@ -424,8+432,8 @@ int __init dmascc_init(void)
       for (i = 0; i < hw[h].num_devs; i++)
        if (base[i] && counting[i]) {
          /* Read back Timer 1: latch; read LSB; read MSB */
-         outb_p(0x40, tcmd[i]);
-         t_val = inb_p(t1[i]) + (inb_p(t1[i]) << 8);
+         outb(0x40, tcmd[i]);
+         t_val = inb(t1[i]) + (inb(t1[i]) << 8);
          /* Also check whether counter did wrap */
          if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0;
          delay[i] = jiffies - start[i];
@@ -452,31+460,46 @@ int __init dmascc_init(void)
   return -EIO;
 }
 
-int __init setup_adapter(int io, int h, int n)
-{
+
+int __init setup_adapter(int card_base, int type, int n) {
   int i, irq, chip;
   struct scc_info *info;
   struct net_device *dev;
   struct scc_priv *priv;
   unsigned long time;
   unsigned int irqs;
-  int tmr = io + hw[h].tmr_offset;
-  int scc = io + hw[h].scc_offset;
-  int cmd = scc + SCCA_CMD;
+  int tmr_base = card_base + hw[type].tmr_offset;
+  int scc_base = card_base + hw[type].scc_offset;
   char *chipnames[] = CHIPNAMES;
 
-  /* Reset 8530 */
-  write_scc(cmd, R9, FHWRES | MIE | NV);
+  /* Allocate memory */
+  info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
+  if (!info) {
+    printk("dmascc: could not allocate memory for %s at %#3x\n",
+          hw[type].name, card_base);
+    return -1;
+  }
+
+  /* Initialize what is necessary for write_scc and write_scc_data */
+  memset(info, 0, sizeof(struct scc_info));
+  priv = &info->priv[0];
+  priv->type = type;
+  priv->card_base = card_base;
+  priv->scc_cmd = scc_base + SCCA_CMD;
+  priv->scc_data = scc_base + SCCA_DATA;
+
+  /* Reset SCC */
+  write_scc(priv, R9, FHWRES | MIE | NV);
 
   /* Determine type of chip by enabling SDLC/HDLC enhancements */
-  write_scc(cmd, R15, SHDLCE);
-  if (!read_scc(cmd, R15)) {
+  write_scc(priv, R15, SHDLCE);
+  if (!read_scc(priv, R15)) {
     /* WR7' not present. This is an ordinary Z8530 SCC. */
     chip = Z8530;
   } else {
     /* Put one character in TX FIFO */
-    write_scc(cmd, R8, 0);
-    if (read_scc(cmd, R0) & Tx_BUF_EMP) {
+    write_scc_data(priv, 0, 0);
+    if (read_scc(priv, R0) & Tx_BUF_EMP) {
       /* TX FIFO not full. This is a Z85230 ESCC with a 4-byte FIFO. */
       chip = Z85230;
     } else {
@@ -484,93+507,76 @@ int __init setup_adapter(int io, int h, int n)
       chip = Z85C30;
     }
   }
-  write_scc(cmd, R15, 0);
+  write_scc(priv, R15, 0);
 
   /* Start IRQ auto-detection */
   sti();
   irqs = probe_irq_on();
 
   /* Enable interrupts */
-  switch (h) {
-  case TYPE_PI:
-  case TYPE_PI2:
-    outb_p(0, io + PI_DREQ_MASK);
-    write_scc(cmd, R15, CTSIE);
-    write_scc(cmd, R0, RES_EXT_INT);
-    write_scc(cmd, R1, EXT_INT_ENAB);
-    break;
-  case TYPE_TWIN:
-    outb_p(0, io + TWIN_DMA_CFG);
-    inb_p(io + TWIN_CLR_TMR1);
-    inb_p(io + TWIN_CLR_TMR2);
-    outb_p(TWIN_EI, io + TWIN_SERIAL_CFG);
-    break;
+  if (type == TYPE_TWIN) {
+    outb(0, card_base + TWIN_DMA_CFG);
+    inb(card_base + TWIN_CLR_TMR1);
+    inb(card_base + TWIN_CLR_TMR2);
+    outb((info->twin_serial_cfg = TWIN_EI), card_base + TWIN_SERIAL_CFG);
+  } else {
+    write_scc(priv, R15, CTSIE);
+    write_scc(priv, R0, RES_EXT_INT);
+    write_scc(priv, R1, EXT_INT_ENAB);
   }
 
   /* Start timer */
-  outb_p(1, tmr + TMR_CNT1);
-  outb_p(0, tmr + TMR_CNT1);
+  outb(1, tmr_base + TMR_CNT1);
+  outb(0, tmr_base + TMR_CNT1);
+
   /* Wait and detect IRQ */
   time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
   irq = probe_irq_off(irqs);
 
   /* Clear pending interrupt, disable interrupts */
-  switch (h) {
-  case TYPE_PI:
-  case TYPE_PI2:
-    write_scc(cmd, R1, 0);
-    write_scc(cmd, R15, 0);
-    write_scc(cmd, R0, RES_EXT_INT);
-    break;
-  case TYPE_TWIN:
-    inb_p(io + TWIN_CLR_TMR1);
-    outb_p(0, io + TWIN_SERIAL_CFG);
-    break;
+  if (type == TYPE_TWIN) {
+    inb(card_base + TWIN_CLR_TMR1);
+  } else {
+    write_scc(priv, R1, 0);
+    write_scc(priv, R15, 0);
+    write_scc(priv, R0, RES_EXT_INT);
   }
 
   if (irq <= 0) {
     printk("dmascc: could not find irq of %s at %#3x (irq=%d)\n",
-          hw[h].name, io, irq);
-    return -1;
-  }
-
-  /* Allocate memory */
-  info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
-  if (!info) {
-    printk("dmascc: could not allocate memory for %s at %#3x\n",
-          hw[h].name, io);
+          hw[type].name, card_base, irq);
+    kfree_s(info, sizeof(struct scc_info));
     return -1;
   }
 
   /* Set up data structures */
-  memset(info, 0, sizeof(struct scc_info));
-  info->type = h;
-  info->chip = chip;
-  info->scc_base = io + hw[h].scc_offset;
-  info->tmr_base = io + hw[h].tmr_offset;
-  info->twin_serial_cfg = 0;
   for (i = 0; i < 2; i++) {
     dev = &info->dev[i];
     priv = &info->priv[i];
+    priv->type = type;
+    priv->chip = chip;
+    priv->dev = dev;
     priv->info = info;
     priv->channel = i;
-    priv->cmd = info->scc_base + (i ? SCCB_CMD : SCCA_CMD);
-    priv->data = info->scc_base + (i ? SCCB_DATA : SCCA_DATA);
-    priv->tmr = info->tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
-    priv->param.pclk_hz = hw[h].pclk_hz;
+    priv->card_base = card_base;
+    priv->scc_cmd = scc_base + (i ? SCCB_CMD : SCCA_CMD);
+    priv->scc_data = scc_base + (i ? SCCB_DATA : SCCA_DATA);
+    priv->tmr_cnt = tmr_base + (i ? TMR_CNT2 : TMR_CNT1);
+    priv->tmr_ctrl = tmr_base + TMR_CTRL;
+    priv->tmr_mode = i ? 0xb0 : 0x70;
+    priv->param.pclk_hz = hw[type].pclk_hz;
     priv->param.brg_tc = -1;
     priv->param.clocks = TCTRxCP | RCRTxCP;
-    priv->param.txdelay = TMR_0_HZ * 10 / 1000;
-    priv->param.txtime = HZ * 3;
-    priv->param.sqdelay = TMR_0_HZ * 1 / 1000;
-    priv->param.slottime = TMR_0_HZ * 10 / 1000;
-    priv->param.waittime = TMR_0_HZ * 100 / 1000;
-    priv->param.persist = 32;
+    priv->param.persist = 256;
+    priv->param.dma = -1;
     priv->rx_task.routine = rx_bh;
-    priv->rx_task.data = dev;
+    priv->rx_task.data = priv;
     dev->priv = priv;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+    if (sizeof(dev->name) == sizeof(char *)) dev->name = priv->name;
+#endif
     sprintf(dev->name, "dmascc%i", 2*n+i);
-    dev->base_addr = io;
+    dev->base_addr = card_base;
     dev->irq = irq;
     dev->open = scc_open;
     dev->stop = scc_close;
@@ -580,7+586,6 @@ int __init setup_adapter(int io, int h, int n)
     dev->hard_header = ax25_encapsulate;
     dev->rebuild_header = ax25_rebuild_header;
     dev->set_mac_address = scc_set_mac_address;
-    SET_DEV_INIT(dev->init);
     dev->type = ARPHRD_AX25;
     dev->hard_header_len = 73;
     dev->mtu = 1500;
@@ -589,203+594,298 @@ int __init setup_adapter(int io, int h, int n)
     memcpy(dev->broadcast, ax25_broadcast, 7);
     memcpy(dev->dev_addr, ax25_test, 7);
     dev_init_buffers(dev);
+    rtnl_lock();
     if (register_netdevice(dev)) {
       printk("dmascc: could not register %s\n", dev->name);
     }
+    rtnl_unlock();
   }
 
-  request_region(io, hw[h].io_size, "dmascc");
+  request_region(card_base, hw[type].io_size, "dmascc");
 
   info->next = first;
   first = info;
-  printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[h].name,
-        chipnames[chip], io, irq);
+  printk("dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
+        chipnames[chip], card_base, irq);
   return 0;
 }
 
 
 /* Driver functions */
 
-static inline void write_scc(int ctl, int reg, int val)
-{
-  outb_p(reg, ctl);
-  outb_p(val, ctl);
+static void write_scc(struct scc_priv *priv, int reg, int val) {
+  unsigned long flags;
+  switch (priv->type) {
+  case TYPE_S5:
+    if (reg) outb(reg, priv->scc_cmd);
+    outb(val, priv->scc_cmd);
+    return;
+  case TYPE_TWIN:
+    if (reg) outb_p(reg, priv->scc_cmd);
+    outb_p(val, priv->scc_cmd);
+    return;
+  default:
+    save_flags(flags);
+    cli();
+    outb_p(0, priv->card_base + PI_DREQ_MASK);
+    if (reg) outb_p(reg, priv->scc_cmd);
+    outb_p(val, priv->scc_cmd);
+    outb(1, priv->card_base + PI_DREQ_MASK);
+    restore_flags(flags);
+    return;
+  }
 }
 
 
-static inline int read_scc(int ctl, int reg)
-{
-  outb_p(reg, ctl);
-  return inb_p(ctl);
+static void write_scc_data(struct scc_priv *priv, int val, int fast) {
+  unsigned long flags;
+  switch (priv->type) {
+  case TYPE_S5:
+    outb(val, priv->scc_data);
+    return;
+  case TYPE_TWIN:
+    outb_p(val, priv->scc_data);
+    return;
+  default:
+    if (fast) outb_p(val, priv->scc_data);
+    else {
+      save_flags(flags);
+      cli();
+      outb_p(0, priv->card_base + PI_DREQ_MASK);
+      outb_p(val, priv->scc_data);
+      outb(1, priv->card_base + PI_DREQ_MASK);
+      restore_flags(flags);
+    }
+    return;
+  }
 }
 
 
-static int scc_open(struct net_device *dev)
-{
+static int read_scc(struct scc_priv *priv, int reg) {
+  int rc;
+  unsigned long flags;
+  switch (priv->type) {
+  case TYPE_S5:
+    if (reg) outb(reg, priv->scc_cmd);
+    return inb(priv->scc_cmd);
+  case TYPE_TWIN:
+    if (reg) outb_p(reg, priv->scc_cmd);
+    return inb_p(priv->scc_cmd);
+  default:
+    save_flags(flags);
+    cli();
+    outb_p(0, priv->card_base + PI_DREQ_MASK);
+    if (reg) outb_p(reg, priv->scc_cmd);
+    rc = inb_p(priv->scc_cmd);
+    outb(1, priv->card_base + PI_DREQ_MASK);
+    restore_flags(flags);
+    return rc;
+  }
+}
+
+
+static int read_scc_data(struct scc_priv *priv) {
+  int rc;
+  unsigned long flags;
+  switch (priv->type) {
+  case TYPE_S5:
+    return inb(priv->scc_data);
+  case TYPE_TWIN:
+    return inb_p(priv->scc_data);
+  default:
+    save_flags(flags);
+    cli();
+    outb_p(0, priv->card_base + PI_DREQ_MASK);
+    rc = inb_p(priv->scc_data);
+    outb(1, priv->card_base + PI_DREQ_MASK);
+    restore_flags(flags);
+    return rc;
+  }
+}
+
+
+static int scc_open(struct net_device *dev) {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
-  int io = dev->base_addr;
-  int cmd = priv->cmd;
+  int card_base = priv->card_base;
+
+  MOD_INC_USE_COUNT;
 
   /* Request IRQ if not already used by other channel */
-  if (!info->open) {
-    if (request_irq(dev->irq, scc_isr, SA_INTERRUPT, "dmascc", info))
+  if (!info->irq_used) {
+    if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
+      MOD_DEC_USE_COUNT;
       return -EAGAIN;
+    }
   }
+  info->irq_used++;
 
   /* Request DMA if required */
-  if (dev->dma && request_dma(dev->dma, "dmascc")) {
-    if (!info->open) free_irq(dev->irq, info);
-    return -EAGAIN;
+  if (priv->param.dma >= 0) {
+    if (request_dma(priv->param.dma, "dmascc")) {
+      if (--info->irq_used == 0) free_irq(dev->irq, info);
+      MOD_DEC_USE_COUNT;
+      return -EAGAIN;
+    } else {
+      unsigned long flags = claim_dma_lock();
+      clear_dma_ff(priv->param.dma);
+      release_dma_lock(flags);
+    }
   }
 
   /* Initialize local variables */
   priv->rx_ptr = 0;
   priv->rx_over = 0;
   priv->rx_head = priv->rx_tail = priv->rx_count = 0;
-  priv->tx_state = TX_IDLE;
+  priv->state = IDLE;
   priv->tx_head = priv->tx_tail = priv->tx_count = 0;
   priv->tx_ptr = 0;
-  priv->tx_sem = 0;
 
   /* Reset channel */
-  write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+  write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
   /* X1 clock, SDLC mode */
-  write_scc(cmd, R4, SDLC | X1CLK);
+  write_scc(priv, R4, SDLC | X1CLK);
   /* DMA */
-  write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
   /* 8 bit RX char, RX disable */
-  write_scc(cmd, R3, Rx8);
+  write_scc(priv, R3, Rx8);
   /* 8 bit TX char, TX disable */
-  write_scc(cmd, R5, Tx8);
+  write_scc(priv, R5, Tx8);
   /* SDLC address field */
-  write_scc(cmd, R6, 0);
+  write_scc(priv, R6, 0);
   /* SDLC flag */
-  write_scc(cmd, R7, FLAG);
-  switch (info->chip) {
+  write_scc(priv, R7, FLAG);
+  switch (priv->chip) {
   case Z85C30:
     /* Select WR7' */
-    write_scc(cmd, R15, SHDLCE);
+    write_scc(priv, R15, SHDLCE);
     /* Auto EOM reset */
-    write_scc(cmd, R7, AUTOEOM);
-    write_scc(cmd, R15, 0);
+    write_scc(priv, R7, AUTOEOM);
+    write_scc(priv, R15, 0);
     break;
   case Z85230:
     /* Select WR7' */
-    write_scc(cmd, R15, SHDLCE);
-    /* RX FIFO half full (interrupt only), Auto EOM reset,
-       TX FIFO empty (DMA only) */
-    write_scc(cmd, R7, AUTOEOM | (dev->dma ? TXFIFOE : RXFIFOH));
-    write_scc(cmd, R15, 0);
+    write_scc(priv, R15, SHDLCE);
+    /* The following bits are set (see 2.5.2.1):
+       - Automatic EOM reset
+       - Interrupt request if RX FIFO is half full
+         This bit should be ignored in DMA mode (according to the
+         documentation), but actually isn't. The receiver doesn't work if
+         it is set. Thus, we have to clear it in DMA mode.
+       - Interrupt/DMA request if TX FIFO is completely empty
+         a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
+            compatibility).
+         b) If cleared, DMA requests may follow each other very quickly,
+            filling up the TX FIFO.
+            Advantage: TX works even in case of high bus latency.
+            Disadvantage: Edge-triggered DMA request circuitry may miss
+                          a request. No more data is delivered, resulting
+                          in a TX FIFO underrun.
+         Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
+         The PackeTwin doesn't. I don't know about the PI, but let's
+        assume it behaves like the PI2.
+    */
+    if (priv->param.dma >= 0) {
+      if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE);
+      else write_scc(priv, R7, AUTOEOM);
+    } else {
+      write_scc(priv, R7, AUTOEOM | RXFIFOH);
+    }
+    write_scc(priv, R15, 0);
     break;
   }
   /* Preset CRC, NRZ(I) encoding */
-  write_scc(cmd, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+  write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
 
   /* Configure baud rate generator */
   if (priv->param.brg_tc >= 0) {
     /* Program BR generator */
-    write_scc(cmd, R12, priv->param.brg_tc & 0xFF);
-    write_scc(cmd, R13, (priv->param.brg_tc>>8) & 0xFF);
+    write_scc(priv, R12, priv->param.brg_tc & 0xFF);
+    write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF);
     /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
        PackeTwin, not connected on the PI2); set DPLL source to BRG */
-    write_scc(cmd, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+    write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
     /* Enable DPLL */
-    write_scc(cmd, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
+    write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
   } else {
     /* Disable BR generator */
-    write_scc(cmd, R14, DTRREQ | BRSRC);
+    write_scc(priv, R14, DTRREQ | BRSRC);
   }
 
   /* Configure clocks */
-  if (info->type == TYPE_TWIN) {
+  if (priv->type == TYPE_TWIN) {
     /* Disable external TX clock receiver */
-    outb_p((info->twin_serial_cfg &=
+    outb((info->twin_serial_cfg &=
            ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), 
-          io + TWIN_SERIAL_CFG);
+          card_base + TWIN_SERIAL_CFG);
   }
-  write_scc(cmd, R11, priv->param.clocks);
-  if ((info->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+  write_scc(priv, R11, priv->param.clocks);
+  if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
     /* Enable external TX clock receiver */
-    outb_p((info->twin_serial_cfg |=
+    outb((info->twin_serial_cfg |=
            (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
-          io + TWIN_SERIAL_CFG);
+          card_base + TWIN_SERIAL_CFG);
   }
 
   /* Configure PackeTwin */
-  if (info->type == TYPE_TWIN) {
+  if (priv->type == TYPE_TWIN) {
     /* Assert DTR, enable interrupts */
-    outb_p((info->twin_serial_cfg |= TWIN_EI |
+    outb((info->twin_serial_cfg |= TWIN_EI |
            (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
-          io + TWIN_SERIAL_CFG);
+          card_base + TWIN_SERIAL_CFG);
   }
 
   /* Read current status */
-  priv->status = read_scc(cmd, R0);
-  /* Enable SYNC, DCD, and CTS interrupts */
-  write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
-
-  /* Configure PI2 DMA */
-  if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
+  priv->rr0 = read_scc(priv, R0);
+  /* Enable DCD interrupt */
+  write_scc(priv, R15, DCDIE);
 
   netif_start_queue(dev);
-  info->open++;
-  MOD_INC_USE_COUNT;
 
   return 0;
 }
 
 
-static int scc_close(struct net_device *dev)
-{
+static int scc_close(struct net_device *dev) {
   struct scc_priv *priv = dev->priv;
   struct scc_info *info = priv->info;
-  int io = dev->base_addr;
-  int cmd = priv->cmd;
+  int card_base = priv->card_base;
 
   netif_stop_queue(dev);
-  info->open--;
 
-  if (info->type == TYPE_TWIN)
+  if (priv->type == TYPE_TWIN) {
     /* Drop DTR */
-    outb_p((info->twin_serial_cfg &=
+    outb((info->twin_serial_cfg &=
            (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
-          io + TWIN_SERIAL_CFG);
-
-  /* Reset channel, free DMA */
-  write_scc(cmd, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
-  if (dev->dma) {
-    if (info->type == TYPE_TWIN) outb_p(0, io + TWIN_DMA_CFG);
-    free_dma(dev->dma);
+          card_base + TWIN_SERIAL_CFG);
   }
 
-  if (!info->open) {
-    if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
-    free_irq(dev->irq, info);
+  /* Reset channel, free DMA and IRQ */
+  write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+  if (priv->param.dma >= 0) {
+    if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG);
+    free_dma(priv->param.dma);
   }
+  if (--info->irq_used == 0) free_irq(dev->irq, info);
+
   MOD_DEC_USE_COUNT;
   return 0;
 }
 
 
-static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-  int rc;
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
   struct scc_priv *priv = dev->priv;
   
   switch (cmd) {
   case SIOCGSCCPARAM:
-    if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
-       return -EFAULT;
+    if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
+      return -EFAULT;
     return 0;
   case SIOCSSCCPARAM:
-    if (!capable(CAP_NET_ADMIN)) 
-       return -EPERM;
-    if (netif_running(dev))
-       return -EAGAIN;
-    if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
-       return -EFAULT;
-    dev->dma = priv->param.dma;
+    if (!capable(CAP_NET_ADMIN)) return -EPERM;
+    if (netif_running(dev)) return -EAGAIN;
+    if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
+      return -EFAULT;
     return 0;
   default:
     return -EINVAL;
@@ -793,165+893,150 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 }
 
 
-static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) {
   struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int cmd = priv->cmd;
   unsigned long flags;
   int i;
 
-  /* Block a timer-based transmit from overlapping */
+  /* Temporarily stop the scheduler feeding us packets */
   netif_stop_queue(dev);
-  
+
   /* Transfer data to DMA buffer */
   i = priv->tx_head;
   memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
   priv->tx_len[i] = skb->len-1;
 
+  /* Clear interrupts while we touch our circular buffers */
   save_flags(flags);
   cli();
 
-  /* Set the busy flag if we just filled up the last buffer */
+  /* Move the ring buffer's head */
   priv->tx_head = (i + 1) % NUM_TX_BUF;
   priv->tx_count++;
-  if (priv->tx_count != NUM_TX_BUF)
-       netif_wake_queue(dev);
+
+  /* If we just filled up the last buffer, leave queue stopped.
+     The higher layers must wait until we have a DMA buffer
+     to accept the data. */
+  if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev);
 
   /* Set new TX state */
-  if (priv->tx_state == TX_IDLE) {
+  if (priv->state == IDLE) {
     /* Assert RTS, start timer */
-    priv->tx_state = TX_TXDELAY;
-    if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
-    write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
-    if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
+    priv->state = TX_HEAD;
     priv->tx_start = jiffies;
-    delay(dev, priv->param.txdelay);
+    write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+    write_scc(priv, R15, 0);
+    start_timer(priv, priv->param.txdelay, 0);
   }
 
+  /* Turn interrupts back on and free buffer */
   restore_flags(flags);
-
   dev_kfree_skb(skb);
 
-  priv->tx_sem = 0;
   return 0;
 }
 
 
-static struct enet_statistics *scc_get_stats(struct net_device *dev)
-{
+static struct net_device_stats *scc_get_stats(struct net_device *dev) {
   struct scc_priv *priv = dev->priv;
 
   return &priv->stats;
 }
 
 
-static int scc_set_mac_address(struct net_device *dev, void *sa)
-{
+static int scc_set_mac_address(struct net_device *dev, void *sa) {
   memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
   return 0;
 }
 
 
-static void scc_isr(int irq, void *dev_id, struct pt_regs * regs)
-{
+static void scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
   struct scc_info *info = dev_id;
-  int is, io = info->dev[0].base_addr;
 
-  /* We're a fast IRQ handler and are called with interrupts disabled */
+  /* At this point interrupts are enabled, and the interrupt under service
+     is already acknowledged, but masked off.
 
-  /* IRQ sharing doesn't make sense due to ISA's edge-triggered
-     interrupts, hence it is safe to return if we have found and
-     processed a single device. */
-
-  /* Interrupt processing: We loop until we know that the IRQ line is
+     Interrupt processing: We loop until we know that the IRQ line is
      low. If another positive edge occurs afterwards during the ISR,
      another interrupt will be triggered by the interrupt controller
-     as soon as the IRQ level is enabled again (see asm/irq.h). */
-
-  switch (info->type) {
-  case TYPE_PI:
-  case TYPE_PI2:
-    outb_p(0, io + PI_DREQ_MASK);
-    z8530_isr(info);
-    outb_p(1, io + PI_DREQ_MASK);
-    return;
-  case TYPE_TWIN:
-    while ((is = ~inb_p(io + TWIN_INT_REG)) &
+     as soon as the IRQ level is enabled again (see asm/irq.h).
+
+     Bottom-half handlers will be processed after scc_isr(). This is
+     important, since we only have small ringbuffers and want new data
+     to be fetched/delivered immediately. */
+
+  if (info->priv[0].type == TYPE_TWIN) {
+    int is, card_base = info->priv[0].card_base;
+    while ((is = ~inb(card_base + TWIN_INT_REG)) &
           TWIN_INT_MSK) {
       if (is & TWIN_SCC_MSK) {
        z8530_isr(info);
       } else if (is & TWIN_TMR1_MSK) {
-       inb_p(io + TWIN_CLR_TMR1);
-       tm_isr(&info->dev[0]);
+       inb(card_base + TWIN_CLR_TMR1);
+       tm_isr(&info->priv[0]);
       } else {
-       inb_p(io + TWIN_CLR_TMR2);
-       tm_isr(&info->dev[1]);
+       inb(card_base + TWIN_CLR_TMR2);
+       tm_isr(&info->priv[1]);
       }
     }
-    /* No interrupts pending from the PackeTwin */
-    return;
-  }
+  } else z8530_isr(info);
 }
 
 
-static inline void z8530_isr(struct scc_info *info)
-{
-  int is, a_cmd;
-  
-  a_cmd = info->scc_base + SCCA_CMD;
+static inline void z8530_isr(struct scc_info *info) {
+  int is, i = 100;
 
-  while ((is = read_scc(a_cmd, R3))) {
+  while ((is = read_scc(&info->priv[0], R3)) && i--) {
     if (is & CHARxIP) {
-      rx_isr(&info->dev[0]);
+      rx_isr(&info->priv[0]);
     } else if (is & CHATxIP) {
-      tx_isr(&info->dev[0]);
+      tx_isr(&info->priv[0]);
     } else if (is & CHAEXT) {
-      es_isr(&info->dev[0]);
+      es_isr(&info->priv[0]);
     } else if (is & CHBRxIP) {
-      rx_isr(&info->dev[1]);
+      rx_isr(&info->priv[1]);
     } else if (is & CHBTxIP) {
-      tx_isr(&info->dev[1]);
+      tx_isr(&info->priv[1]);
     } else {
-      es_isr(&info->dev[1]);
+      es_isr(&info->priv[1]);
     }
+    write_scc(&info->priv[0], R0, RES_H_IUS);
+    i++;
+  }
+  if (i < 0) {
+    printk("dmascc: stuck in ISR with RR3=0x%02x.\n", is);
   }
   /* Ok, no interrupts pending from this 8530. The INT line should
      be inactive now. */
 }
 
 
-static void rx_isr(struct net_device *dev)
-{
-  struct scc_priv *priv = dev->priv;
-  int cmd = priv->cmd;
-
-  if (dev->dma) {
+static void rx_isr(struct scc_priv *priv) {
+  if (priv->param.dma >= 0) {
     /* Check special condition and perform error reset. See 2.4.7.5. */
-    special_condition(dev, read_scc(cmd, R1));
-    write_scc(cmd, R0, ERR_RES);
+    special_condition(priv, read_scc(priv, R1));
+    write_scc(priv, R0, ERR_RES);
   } else {
     /* Check special condition for each character. Error reset not necessary.
        Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
     int rc;
-    while (read_scc(cmd, R0) & Rx_CH_AV) {
-      rc = read_scc(cmd, R1);
+    while (read_scc(priv, R0) & Rx_CH_AV) {
+      rc = read_scc(priv, R1);
       if (priv->rx_ptr < BUF_SIZE)
-       priv->rx_buf[priv->rx_head][priv->rx_ptr++] = read_scc(cmd, R8);
+       priv->rx_buf[priv->rx_head][priv->rx_ptr++] =
+         read_scc_data(priv);
       else {
        priv->rx_over = 2;
-       read_scc(cmd, R8);
+       read_scc_data(priv);
       }
-      special_condition(dev, rc);
+      special_condition(priv, rc);
     }
   }
 }
 
 
-static void special_condition(struct net_device *dev, int rc)
-{
-  struct scc_priv *priv = dev->priv;
-  int cb, cmd = priv->cmd;
+static void special_condition(struct scc_priv *priv, int rc) {
+  int cb;
   unsigned long flags;
 
   /* See Figure 2-15. Only overrun and EOF need to be checked. */
@@ -959,18+1044,15 @@ static void special_condition(struct net_device *dev, int rc)
   if (rc & Rx_OVR) {
     /* Receiver overrun */
     priv->rx_over = 1;
-    if (!dev->dma) write_scc(cmd, R0, ERR_RES);
+    if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES);
   } else if (rc & END_FR) {
     /* End of frame. Get byte count */
-    if (dev->dma) {
-        flags=claim_dma_lock();
-       disable_dma(dev->dma);
-       clear_dma_ff(dev->dma);
-       cb = BUF_SIZE - get_dma_residue(dev->dma) - 2;
-       release_dma_lock(flags);
-       
+    if (priv->param.dma >= 0) {
+      flags = claim_dma_lock();
+      cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2;
+      release_dma_lock(flags);
     } else {
-       cb = priv->rx_ptr - 2;
+      cb = priv->rx_ptr - 2;
     }
     if (priv->rx_over) {
       /* We had an overrun */
@@ -980,36+1062,32 @@ static void special_condition(struct net_device *dev, int rc)
       priv->rx_over = 0;
     } else if (rc & CRC_ERR) {
       /* Count invalid CRC only if packet length >= minimum */
-      if (cb >= 8) {
+      if (cb >= 15) {
        priv->stats.rx_errors++;
        priv->stats.rx_crc_errors++;
       }
     } else {
-      if (cb >= 8) {
-       /* Put good frame in FIFO */
-       priv->rx_len[priv->rx_head] = cb;
-       priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
-       priv->rx_count++;
-       if (priv->rx_count == NUM_RX_BUF) {
-         /* Disable receiver if FIFO full */
-         write_scc(cmd, R3, Rx8);
+      if (cb >= 15) {
+       if (priv->rx_count < NUM_RX_BUF - 1) {
+         /* Put good frame in FIFO */
+         priv->rx_len[priv->rx_head] = cb;
+         priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
+         priv->rx_count++;
+         /* Mark bottom half handler */
+         queue_task(&priv->rx_task, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+       } else {
          priv->stats.rx_errors++;
          priv->stats.rx_over_errors++;
        }
-       /* Mark bottom half handler */
-       queue_task(&priv->rx_task, &tq_immediate);
-       mark_bh(IMMEDIATE_BH);
       }
     }
     /* Get ready for new frame */
-    if (dev->dma) {
-      
-      flags=claim_dma_lock();
-      set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
-      set_dma_count(dev->dma, BUF_SIZE);
-      enable_dma(dev->dma);
+    if (priv->param.dma >= 0) {
+      flags = claim_dma_lock();
+      set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+      set_dma_count(priv->param.dma, BUF_SIZE);
       release_dma_lock(flags);
-      
     } else {
       priv->rx_ptr = 0;
     }
@@ -1017,12+1095,8 @@ static void special_condition(struct net_device *dev, int rc)
 }
 
 
-static void rx_bh(void *arg)
-{
-  struct net_device *dev = arg;
-  struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int cmd = priv->cmd;
+static void rx_bh(void *arg) {
+  struct scc_priv *priv = arg;
   int i = priv->rx_tail;
   int cb;
   unsigned long flags;
@@ -1045,20+1119,15 @@ static void rx_bh(void *arg)
       data = skb_put(skb, cb+1);
       data[0] = 0;
       memcpy(&data[1], priv->rx_buf[i], cb);
-      skb->dev = dev;
+      skb->dev = priv->dev;
       skb->protocol = ntohs(ETH_P_AX25);
       skb->mac.raw = skb->data;
       netif_rx(skb);
       priv->stats.rx_packets++;
+      priv->stats.rx_bytes += cb;
     }
     save_flags(flags);
     cli();
-    /* Enable receiver if RX buffers have been unavailable */
-    if ((priv->rx_count == NUM_RX_BUF) && (priv->status & DCD)) {
-      if (info->type <= TYPE_PI2) outb_p(0, dev->base_addr + PI_DREQ_MASK);
-      write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
-      if (info->type <= TYPE_PI2) outb_p(1, dev->base_addr + PI_DREQ_MASK);
-    }
     /* Move tail */
     priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
     priv->rx_count--;
@@ -1068,265+1137,277 @@ static void rx_bh(void *arg)
 }
 
 
-static void tx_isr(struct net_device *dev)
-{
-  struct scc_priv *priv = dev->priv;
-  int cmd = priv->cmd;
+static void tx_isr(struct scc_priv *priv) {
   int i = priv->tx_tail, p = priv->tx_ptr;
 
   /* Suspend TX interrupts if we don't want to send anything.
      See Figure 2-22. */
   if (p ==  priv->tx_len[i]) {
-    write_scc(cmd, R0, RES_Tx_P);
+    write_scc(priv, R0, RES_Tx_P);
     return;
   }
 
   /* Write characters */
-  while ((read_scc(cmd, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
-    write_scc(cmd, R8, priv->tx_buf[i][p++]);
+  while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+    write_scc_data(priv, priv->tx_buf[i][p++], 0);
   }
-  priv->tx_ptr = p;
 
+  /* Reset EOM latch of Z8530 */
+  if (!priv->tx_ptr && p && priv->chip == Z8530)
+    write_scc(priv, R0, RES_EOM_L);
+
+  priv->tx_ptr = p;
 }
 
 
-static void es_isr(struct net_device *dev)
-{
-  struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int i, cmd = priv->cmd;
-  int st, dst, res;
+static void es_isr(struct scc_priv *priv) {
+  int i, rr0, drr0, res;
   unsigned long flags;
 
-  /* Read status and reset interrupt bit */
-  st = read_scc(cmd, R0);
-  write_scc(cmd, R0, RES_EXT_INT);
-  dst = priv->status ^ st;
-  priv->status = st;
-
-  /* Since the EOM latch is reset automatically, we assume that
-     it has been zero if and only if we are in the TX_ACTIVE state.
-     Otherwise we follow 2.4.9.6. */
+  /* Read status, reset interrupt bit (open latches) */
+  rr0 = read_scc(priv, R0);
+  write_scc(priv, R0, RES_EXT_INT);
+  drr0 = priv->rr0 ^ rr0;
+  priv->rr0 = rr0;
 
-  /* Transmit underrun */
-  if ((priv->tx_state == TX_ACTIVE) && (st & TxEOM)) {
+  /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
+     it might have already been cleared again by AUTOEOM. */
+  if (priv->state == TX_DATA) {
     /* Get remaining bytes */
     i = priv->tx_tail;
-    if (dev->dma) {
-      flags=claim_dma_lock();
-      disable_dma(dev->dma);
-      clear_dma_ff(dev->dma);
-      res = get_dma_residue(dev->dma);
+    if (priv->param.dma >= 0) {
+      disable_dma(priv->param.dma);
+      flags = claim_dma_lock();
+      res = get_dma_residue(priv->param.dma);
       release_dma_lock(flags);
     } else {
       res = priv->tx_len[i] - priv->tx_ptr;
-      if (res) write_scc(cmd, R0, RES_Tx_P);
       priv->tx_ptr = 0;
     }
-    /* Remove frame from FIFO */
-    priv->tx_tail = (i + 1) % NUM_TX_BUF;
-    priv->tx_count--;
-    /* Check if another frame is available and we are allowed to transmit */
-    if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
-      if (dev->dma) {
-        flags=claim_dma_lock();
-       set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
-       set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
-       enable_dma(dev->dma);
-       release_dma_lock(flags);
-      } else {
-       /* If we have an ESCC, we are allowed to write data bytes
-          immediately. Otherwise we have to wait for the next
-          TX interrupt. See Figure 2-22. */
-       if (info->chip == Z85230) {
-         tx_isr(dev);
-       }
-      }
-    } else {
-      /* No frame available. Disable interrupts. */
-      priv->tx_state = TX_SQDELAY;
-      delay(dev, priv->param.sqdelay);
-      write_scc(cmd, R15, DCDIE | CTSIE | SYNCIE);
-      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-    }
-    /* Update packet statistics */
+    /* Disable DREQ / TX interrupt */
+    if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+      outb(0, priv->card_base + TWIN_DMA_CFG);
+    else
+      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
     if (res) {
+      /* Update packet statistics */
       priv->stats.tx_errors++;
       priv->stats.tx_fifo_errors++;
+      /* Other underrun interrupts may already be waiting */
+      write_scc(priv, R0, RES_EXT_INT);
+      write_scc(priv, R0, RES_EXT_INT);
     } else {
+      /* Update packet statistics */
       priv->stats.tx_packets++;
+      priv->stats.tx_bytes += priv->tx_len[i];
+      /* Remove frame from FIFO */
+      priv->tx_tail = (i + 1) % NUM_TX_BUF;
+      priv->tx_count--;
+      /* Inform upper layers */
+      netif_wake_queue(priv->dev);
+    }
+    /* Switch state */
+    write_scc(priv, R15, 0);
+    if (priv->tx_count &&
+       (jiffies - priv->tx_start) < priv->param.txtimeout) {
+      priv->state = TX_PAUSE;
+      start_timer(priv, priv->param.txpause, 0);
+    } else {
+      priv->state = TX_TAIL;
+      start_timer(priv, priv->param.txtail, 0);
     }
-    /* Inform upper layers */
-    netif_wake_queue(dev);
   }
 
   /* DCD transition */
-  if ((priv->tx_state < TX_TXDELAY) && (dst & DCD)) {
-    /* Transmitter state change */
-    priv->tx_state = TX_OFF;
-    /* Enable or disable receiver */
-    if (st & DCD) {
-      if (dev->dma) {
-       /* Program DMA controller */
-       flags=claim_dma_lock();
-       disable_dma(dev->dma);
-       clear_dma_ff(dev->dma);
-       set_dma_mode(dev->dma, DMA_MODE_READ);
-       set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
-       set_dma_count(dev->dma, BUF_SIZE);
-       enable_dma(dev->dma);
-       release_dma_lock(flags);
-       /* Configure PackeTwin DMA */
-       if (info->type == TYPE_TWIN) {
-         outb_p((dev->dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
-                dev->base_addr + TWIN_DMA_CFG);
-       }
-       /* Sp. cond. intr. only, ext int enable */
-       write_scc(cmd, R1, EXT_INT_ENAB | INT_ERR_Rx |
-                 WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
-      } else {
-       /* Intr. on all Rx characters and Sp. cond., ext int enable */
-       write_scc(cmd, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
-                 WT_FN_RDYFN);
-      }
-      if (priv->rx_count < NUM_RX_BUF) {
-       /* Enable receiver */
-       write_scc(cmd, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+  if (drr0 & DCD) {
+    if (rr0 & DCD) {
+      switch (priv->state) {
+      case IDLE:
+      case WAIT:
+       priv->state = DCD_ON;
+       write_scc(priv, R15, 0);
+       start_timer(priv, priv->param.dcdon, 0);
       }
     } else {
-      /* Disable DMA */
-      if (dev->dma)
-      {
-       flags=claim_dma_lock();
-       disable_dma(dev->dma);
-       release_dma_lock(flags);
-      }
-      /* Disable receiver */
-      write_scc(cmd, R3, Rx8);
-      /* DMA disable, RX int disable, Ext int enable */
-      write_scc(cmd, R1, EXT_INT_ENAB | WT_RDY_RT | WT_FN_RDYFN);
-      /* Transmitter state change */
-      if (random() > priv->param.persist)
-       delay(dev, priv->param.slottime);
-      else {
-       if (priv->tx_count) {
-         priv->tx_state = TX_TXDELAY;
-         write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
-         priv->tx_start = jiffies;
-         delay(dev, priv->param.txdelay);
-       } else {
-         priv->tx_state = TX_IDLE;
-       }
+      switch (priv->state) {
+      case RX_ON:
+       rx_off(priv);
+       priv->state = DCD_OFF;
+       write_scc(priv, R15, 0);
+       start_timer(priv, priv->param.dcdoff, 0);
       }
     }
   }
 
   /* CTS transition */
-  if ((info->type <= TYPE_PI2) && (dst & CTS) && (~st & CTS)) {
-    /* Timer has expired */
-    tm_isr(dev);
-  }
+  if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
+    tm_isr(priv);
 
-  /* /SYNC/HUNT transition */
-  if ((dst & SYNC_HUNT) && (~st & SYNC_HUNT)) {
-    /* Reset current frame and clear RX FIFO */
-    while (read_scc(cmd, R0) & Rx_CH_AV) read_scc(cmd, R8);
-    priv->rx_over = 0;
-    if (dev->dma) {
-      flags=claim_dma_lock();
-      disable_dma(dev->dma);
-      clear_dma_ff(dev->dma);
-      set_dma_addr(dev->dma, (int) priv->rx_buf[priv->rx_head]);
-      set_dma_count(dev->dma, BUF_SIZE);
-      enable_dma(dev->dma);
-      release_dma_lock(flags);
+}
+
+
+static void tm_isr(struct scc_priv *priv) {
+  switch (priv->state) {
+  case TX_HEAD:
+  case TX_PAUSE:
+    tx_on(priv);
+    priv->state = TX_DATA;
+    break;
+  case TX_TAIL:
+    write_scc(priv, R5, TxCRC_ENAB | Tx8);
+    priv->state = RTS_OFF;
+    if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0);
+    start_timer(priv, priv->param.rtsoff, 0);
+    break;
+  case RTS_OFF:
+    write_scc(priv, R15, DCDIE);
+    priv->rr0 = read_scc(priv, R0);
+    if (priv->rr0 & DCD) {
+      priv->stats.collisions++;
+      rx_on(priv);
+      priv->state = RX_ON;
     } else {
-      priv->rx_ptr = 0;
+      priv->state = WAIT;
+      start_timer(priv, priv->param.waittime, DCDIE);
+    }
+    break;
+  case WAIT:
+    if (priv->tx_count) {
+      priv->state = TX_HEAD;
+      priv->tx_start = jiffies;
+      write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+      write_scc(priv, R15, 0);
+      start_timer(priv, priv->param.txdelay, 0);
+    } else {
+      priv->state = IDLE;
+      if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE);
     }
+    break;
+  case DCD_ON:
+  case DCD_OFF:
+    write_scc(priv, R15, DCDIE);
+    priv->rr0 = read_scc(priv, R0);
+    if (priv->rr0 & DCD) {
+      rx_on(priv);
+      priv->state = RX_ON;
+    } else {
+      priv->state = WAIT;
+      start_timer(priv,
+                 random()/priv->param.persist*priv->param.slottime,
+                 DCDIE);
+    }
+    break;
   }
 }
 
 
-static void tm_isr(struct net_device *dev)
-{
-  struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int cmd = priv->cmd;
+static inline void tx_on(struct scc_priv *priv) {
+  int i, n;
   unsigned long flags;
 
-  switch (priv->tx_state) {
-  case TX_OFF:
-    if (~priv->status & DCD) {
-      if (random() > priv->param.persist) delay(dev, priv->param.slottime);
-      else {
-       if (priv->tx_count) {
-         priv->tx_state = TX_TXDELAY;
-         write_scc(cmd, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
-         priv->tx_start = jiffies;
-         delay(dev, priv->param.txdelay);
-       } else {
-         priv->tx_state = TX_IDLE;
-       }
-      }
-    }
-    break;
-  case TX_TXDELAY:
-    priv->tx_state = TX_ACTIVE;
-    if (dev->dma) {
-      /* Program DMA controller */
-      
-      flags=claim_dma_lock();
-      disable_dma(dev->dma);
-      clear_dma_ff(dev->dma);
-      set_dma_mode(dev->dma, DMA_MODE_WRITE);
-      set_dma_addr(dev->dma, (int) priv->tx_buf[priv->tx_tail]);
-      set_dma_count(dev->dma, priv->tx_len[priv->tx_tail]);
-      enable_dma(dev->dma);
-      release_dma_lock(flags);
-      
-      /* Configure PackeTwin DMA */
-      if (info->type == TYPE_TWIN) {
-       outb_p((dev->dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
-              dev->base_addr + TWIN_DMA_CFG);
-      }
-      /* Enable interrupts and DMA. On the PackeTwin, the DTR//REQ pin
-        is used for TX DMA requests, but we enable the WAIT/DMA request
-        pin, anyway */
-      write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
-      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
-    } else {
-      write_scc(cmd, R15, TxUIE | DCDIE | CTSIE | SYNCIE);
-      write_scc(cmd, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
-      tx_isr(dev);
+  if (priv->param.dma >= 0) {
+    n = (priv->chip == Z85230) ? 3 : 1;
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
+    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
+    release_dma_lock(flags);
+    /* Enable TX underrun interrupt */
+    write_scc(priv, R15, TxUIE);
+    /* Configure DREQ */
+    if (priv->type == TYPE_TWIN)
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+          priv->card_base + TWIN_DMA_CFG);
+    else
+      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
+    /* Write first byte(s) */
+    save_flags(flags);
+    cli();
+    for (i = 0; i < n; i++)
+      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
+    enable_dma(priv->param.dma);
+    restore_flags(flags);
+  } else {
+    write_scc(priv, R15, TxUIE);
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+    tx_isr(priv);
+  }
+  /* Reset EOM latch if we do not have the AUTOEOM feature */
+  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
+}
+
+
+static inline void rx_on(struct scc_priv *priv) {
+  unsigned long flags;
+
+  /* Clear RX FIFO */
+  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
+  priv->rx_over = 0;
+  if (priv->param.dma >= 0) {
+    /* Program DMA controller */
+    flags = claim_dma_lock();
+    set_dma_mode(priv->param.dma, DMA_MODE_READ);
+    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
+    set_dma_count(priv->param.dma, BUF_SIZE);
+    release_dma_lock(flags);
+    enable_dma(priv->param.dma);
+    /* Configure PackeTwin DMA */
+    if (priv->type == TYPE_TWIN) {
+      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+          priv->card_base + TWIN_DMA_CFG);
     }
-    if (info->chip == Z8530) write_scc(cmd, R0, RES_EOM_L);
-    break;
-  case TX_SQDELAY:
-    /* Disable transmitter */
-    write_scc(cmd, R5, TxCRC_ENAB | Tx8);
-    /* Transmitter state change: Switch to TX_OFF and wait at least
-       1 slottime. */
-    priv->tx_state = TX_OFF;    
-    if (~priv->status & DCD) delay(dev, priv->param.waittime);
+    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+             WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+  } else {
+    /* Reset current frame */
+    priv->rx_ptr = 0;
+    /* Intr. on all Rx characters and Sp. cond., ext int enable */
+    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+             WT_FN_RDYFN);
   }
+  write_scc(priv, R0, ERR_RES);
+  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
 }
 
 
-static inline void delay(struct net_device *dev, int t)
-{
-  struct scc_priv *priv = dev->priv;
-  int tmr = priv->tmr;
+static inline void rx_off(struct scc_priv *priv) {
+  /* Disable receiver */
+  write_scc(priv, R3, Rx8);
+  /* Disable DREQ / RX interrupt */
+  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+    outb(0, priv->card_base + TWIN_DMA_CFG);
+  else
+    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+  /* Disable DMA */
+  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15) {
+  unsigned long flags;
 
-  outb_p(t & 0xFF, tmr);
-  outb_p((t >> 8) & 0xFF, tmr);
+  outb(priv->tmr_mode, priv->tmr_ctrl);
+  if (t == 0) {
+    tm_isr(priv);
+  } else if (t > 0) {
+    save_flags(flags);
+    cli();
+    outb(t & 0xFF, priv->tmr_cnt);
+    outb((t >> 8) & 0xFF, priv->tmr_cnt);
+    if (priv->type != TYPE_TWIN) {
+      write_scc(priv, R15, r15 | CTSIE);
+      priv->rr0 |= CTS;
+    }
+    restore_flags(flags);
+  }
 }
 
 
-static inline unsigned char random(void)
-{
+static inline unsigned char random(void) {
   /* See "Numerical Recipes in C", second edition, p. 284 */
   rand = rand * 1664525L + 1013904223L;
   return (unsigned char) (rand >> 24);
 }
 
-
index 15a304c..1cea70f 100644 (file)
@@ -326,6+326,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
                                skb->protocol = eth_type_trans(skb, dev);
                                netif_rx(skb);
                                sp->stats.rx_packets++;
+                               sp->stats.rx_bytes += len;
                        } else {
                                printk ("%s: Memory squeeze, deferring packet.\n",
                                        dev->name);
@@ -500,6+501,7 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Setup... */
        skblen = skb->len;
        len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
+       sp->stats.tx_bytes += len;
        entry = sp->tx_new;
        td = &sp->srings.tx_desc[entry];
 
@@ -690,7+692,7 @@ static inline void str2eaddr(unsigned char *ea, unsigned char *str)
 
 int sgiseeq_probe(struct net_device *dev)
 {
-       static int initialized;
+       static int initialized = 0;
        char *ep;
 
        if (initialized)        /* Already initialized? */
index a899d7f..51827fa 100644 (file)
 
 #ifndef MULTIPLE_PAD_SIZES
 
+#ifdef CONFIG_CPU_HAS_WB
+#include <asm/wbflush.h>
+#define esp_write(__reg, __val) do{(__reg) = (__val); wbflush();} while(0)
+#else
 #define esp_write(__reg, __val) ((__reg) = (__val))
+#endif
 #define esp_read(__reg) (__reg)
 
 struct ESP_regs {
index 47fc003..25c3cad 100644 (file)
 #include <asm/dec/ioasic_ints.h>
 #include <asm/dec/machtype.h>
 
+/*
+ * Once upon a time the pmaz code used to be working but
+ * it hasn't been maintained for quite some time.
+ * It isn't working anymore but I'll leave here as a
+ * starting point. #define this an be prepared for tons
+ * of warnings and errors :)
+ */
+#undef PMAZ_A
+
 static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
 static void dma_drain(struct NCR_ESP *esp);
-static void pmaz_dma_drain(struct NCR_ESP *esp);
-static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp);
 static void dma_dump_state(struct NCR_ESP *esp);
 static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
 static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
 static void dma_ints_off(struct NCR_ESP *esp);
 static void dma_ints_on(struct NCR_ESP *esp);
-static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void pmaz_dma_ints_off(struct NCR_ESP *esp);
-static void pmaz_dma_ints_on(struct NCR_ESP *esp);
 static int  dma_irq_p(struct NCR_ESP *esp);
 static int  dma_ports_p(struct NCR_ESP *esp);
 static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
 static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
 static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static void dma_advance_sg(Scsi_Cmnd * sp);
+
+#ifdef PMAZ_A
+static void pmaz_dma_drain(struct NCR_ESP *esp);
+static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_ints_off(struct NCR_ESP *esp);
+static void pmaz_dma_ints_on(struct NCR_ESP *esp);
 static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
 static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
-// static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
-static void dma_advance_sg(Scsi_Cmnd * sp);
+static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+
+volatile int *scsi_pmaz_dma_ptr_tc;
+#endif
 
 #define TC_ESP_RAM_SIZE 0x20000
 #define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1))
@@ -89,18+103,18 @@ volatile unsigned long *ioasic_ssr;
 volatile unsigned long *scsi_sdr0;
 volatile unsigned long *scsi_sdr1;
 
-volatile int *scsi_pmaz_dma_ptr_tc;
-
 static void scsi_dma_int(int, void *, struct pt_regs *);
 
 /***************************************************************** Detection */
 int dec_esp_detect(Scsi_Host_Template * tpnt)
 {
-    struct NCR_ESP *esp;
-    struct ConfigDev *esp_dev;
+       struct NCR_ESP *esp;
+       struct ConfigDev *esp_dev;
+#ifdef PMAZ_A
        int slot, i;
        unsigned long mem_start;
        volatile unsigned char *buffer;
+#endif
 
        if (IOASIC) {
        esp_dev = 0;
@@ -150,10+164,10 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
        /* SCSI chip speed */
                esp->cfreq = 25000000;
 
-       /* 
+       /*
         * we don't give the address of DMA channel, but the number
         * of DMA channel, so we can use the jazz DMA functions
-        * 
+        *
         */
        esp->dregs = JAZZ_SCSI_DMA;
        
@@ -164,7+178,7 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
                esp->esp_command = (volatile unsigned char *) cmd_buffer;
        
        /* get virtual dma address for command buffer */
-               esp->esp_command_dvma = KSEG1ADDR((volatile unsigned char *) cmd_buffer);
+               esp->esp_command_dvma = (__u32) KSEG1ADDR((volatile unsigned char *) cmd_buffer);
        
                esp->irq = SCSI_INT;
        request_irq(esp->irq, esp_intr, SA_INTERRUPT, "NCR 53C94 SCSI",
@@ -181,8+195,9 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
        
        }
 
+#ifdef PMAZ_A  
        if (TURBOCHANNEL) {
-               while ((slot = search_tc_card("PMAZ-AA")) >= 0) {
+               while ((slot = search_tc_card("PMAZ_AA")) >= 0) {
                        claim_tc_card(slot);
                        mem_start = get_tc_base_addr(slot);
 
@@ -242,12+257,13 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
                        esp->dma_mmu_release_scsi_sgl = 0;
                        esp->dma_advance_sg = 0;
 
-                       request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ-AA", NULL);
+                       request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ_AA", NULL);
                        esp->scsi_id = 7;
                        esp->diff = 0;
                        esp_initialize(esp);
                }
        }
+#endif
 
        if(nesps) {
                printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
@@ -321,20+337,14 @@ static void dma_drain(struct NCR_ESP *esp)
        }
 }
 
-static void pmaz_dma_drain(struct NCR_ESP *esp)
-{
-       memcpy((volatile void *) (KSEG0ADDR(esp_virt_buffer)),
-               (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
-}
-
 static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp)
 {
        return sp->SCp.this_residual;;
 }
-    
+
 static void dma_dump_state(struct NCR_ESP *esp)
 {
-/*    
+/*
     ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
            esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_resdiue((int)esp->dregs)));
  */
@@ -400,6+410,66 @@ static void dma_ints_on(struct NCR_ESP *esp)
        enable_irq(SCSI_DMA_INT);
 }
 
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+    return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+/*
+ * FIXME: what's this good for?
+ */
+       return 1;
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+    /*
+     * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
+     * so when (write) is true, it actually means READ!
+     */
+       if (write) {
+       dma_init_read(esp, addr, count);
+    } else {
+       dma_init_write(esp, addr, count);
+    }
+}
+
+/*
+ * These aren't used yet
+ */
+static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+       sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer);
+       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in);
+}
+
+static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+    int sz = sp->SCp.buffers_residual;
+    struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
+
+    while (sz >= 0) {
+               sg[sz].dvma_addr = PHYSADDR(sg[sz].addr);
+       sz--;
+    }
+       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
+
+static void dma_advance_sg(Scsi_Cmnd * sp)
+{
+       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
+}
+
+#ifdef PMAZ_A
+
+static void pmaz_dma_drain(struct NCR_ESP *esp)
+{
+       memcpy((void *) (KSEG0ADDR(esp_virt_buffer)),
+               (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
+}
+
 static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
 {
 
@@ -413,7+483,7 @@ static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
 
 static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
 {
-       memcpy(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length);
+       memcpy((void *)scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length);
 
        *scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]);
 
@@ -427,35+497,9 @@ static void pmaz_dma_ints_on(struct NCR_ESP *esp)
 {
 }
 
-static int dma_irq_p(struct NCR_ESP *esp)
-{
-    return (esp->eregs->esp_status & ESP_STAT_INTR);
-}
-
-static int dma_ports_p(struct NCR_ESP *esp)
-{
-/*
- * FIXME: what's this good for?
- */
-       return 1;
-}
-
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
-{
-    /* 
-     * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
-     * so when (write) is true, it actually means READ!
-     */
-       if (write) {
-       dma_init_read(esp, addr, count);
-    } else {
-       dma_init_write(esp, addr, count);
-    }
-}
-
 static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
 {
-       /* 
+       /*
         * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
         * so when (write) is true, it actually means READ!
         */
@@ -474,35+518,10 @@ static void pmaz_dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
                        scsi_pmaz_dma_buff_used[x] = 0;
 }
 
-
 static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
 {
        sp->SCp.have_data_in = (int) sp->SCp.ptr =
            (char *) KSEG0ADDR((sp->request_buffer));
 }
 
-/*
- * These aren't used yet
- */
-static void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
-{
-       sp->SCp.have_data_in = PHYSADDR(sp->SCp.buffer);
-       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.have_data_in);
-}
-
-static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp)
-{
-    int sz = sp->SCp.buffers_residual;
-    struct mmu_sglist *sg = (struct mmu_sglist *) sp->SCp.buffer;
-    
-    while (sz >= 0) {
-               sg[sz].dvma_addr = PHYSADDR(sg[sz].addr);
-       sz--;
-    }
-       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
-}
-
-static void dma_advance_sg(Scsi_Cmnd * sp)
-{    
-       sp->SCp.ptr = (char *) ((unsigned long) sp->SCp.buffer->dvma_address);
-}
+#endif
\ No newline at end of file
index 51a4eab..a82cbd4 100644 (file)
@@ -136,7+136,6 @@ const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
  */
 extern void scsi_times_out(Scsi_Cmnd * SCpnt);
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
-static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
 
 /*
  * These are the interface to the old error handling code.  It should go away
@@ -2293,6+2292,8 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt)
        MOD_DEC_USE_COUNT;
 }
 
+static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
+
 /*
  * This entry point should be called by a loadable module if it is trying
  * add a high level scsi driver to the system.
index f19bc20..f7582d1 100644 (file)
@@ -5,6+5,9 @@ mainmenu_option next_comment
 comment 'SGI devices'
 
 bool 'SGI Zilog85C30 serial support' CONFIG_SGI_SERIAL
+if [ "$CONFIG_SGI_SERIAL" = "y" ]; then
+   bool '  Support for console on serial port' CONFIG_SERIAL_CONSOLE
+fi
 bool 'SGI DS1286  RTC support' CONFIG_SGI_DS1286
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then  
index b9d7451..415fec3 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: ds1286.c,v 1.7 2000/02/23 00:41:21 ralf Exp $
+/* $Id: ds1286.c,v 1.6 1999/10/09 00:01:31 ralf Exp $
  *
  *     Real Time Clock interface for Linux     
  *
index b0f3103..a060e98 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: graphics.c,v 1.23 2000/02/23 00:41:21 ralf Exp $
+/* $Id: graphics.c,v 1.22 2000/02/18 00:24:43 ralf Exp $
  *
  * gfx.c: support for SGI's /dev/graphics, /dev/opengl
  *
index 8fa9d1c..2ade5a3 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: sgicons.c,v 1.11 1999/01/04 16:07:19 ralf Exp $
+/* $Id: sgicons.c,v 1.10 1998/08/25 09:18:58 ralf Exp $
  *
  * sgicons.c: Setting up and registering console I/O on the SGI.
  *
index 09b32ab..b0ccff4 100644 (file)
@@ -665,19+665,6 @@ static void do_serial_hangup(void *private_)
 }
 
 
-/*
- * This subroutine is called when the RS_TIMER goes off.  It is used
- * by the serial driver to handle ports that do not have an interrupt
- * (irq=0).  This doesn't work at all for 16450's, as a sun has a Z8530.
- */
-static void rs_timer(void)
-{
-       printk("rs_timer called\n");
-       prom_halt();
-       return;
-}
-
 static int startup(struct sgi_serial * info)
 {
        volatile unsigned char junk;
@@ -2237,7+2224,8 @@ static struct console sgi_console_driver = {
 /*
  *     Register console.
  */
-void __init serial_console_init(void)
+void __init sgi_serial_console_init(void)
 {
        register_console(&sgi_console_driver);
 }
+__initcall(rs_init);
index 73e0067..03eab91 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: shmiq.c,v 1.20 2000/02/24 00:13:10 ralf Exp $
+/* $Id: shmiq.c,v 1.19 2000/02/23 00:41:21 ralf Exp $
  *
  * shmiq.c: shared memory input queue driver
  * written 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
 #include <linux/devfs_fs_kernel.h>
 
 #include <asm/shmiq.h>
+#include <asm/gfx.h>
 #include <asm/mman.h>
 #include <asm/uaccess.h>
 #include <asm/poll.h>
@@ -236,8+237,8 @@ shmiq_ioctl (struct inode *inode, struct file *f, unsigned int cmd, unsigned lon
        }
 
        return -EINVAL;
+
 bad_file:
-       unlock_kernel ();
        return -EBADF;
 }
 
@@ -250,51+251,62 @@ qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned
        struct vm_area_struct *vma;
        int v;
        
-       switch (cmd){
+       switch (cmd) {
                /*
                 * The address space is already mapped as a /dev/zero
                 * mapping.  FIXME: check that /dev/zero is what the user
                 * had mapped before :-)
                 */
-       case QIOCATTACH: {
-               unsigned long vaddr;
-               int s;
-               
-               v = verify_area (VERIFY_READ, (void *) arg, sizeof (struct shmiqreq));
-               if (v)
-                       return v;
-               if (copy_from_user (&req, (void *) arg, sizeof (req)))
-                       return -EFAULT;
-               /* Do not allow to attach to another region if it has been already attached */
-               if (shmiqs [minor].mapped){
-                       printk ("SHMIQ:The thingie is already mapped\n");
-                       return -EINVAL;
-               }
-
-               vaddr = (unsigned long) req.user_vaddr;
-               vma = find_vma (current->mm, vaddr);
-               if (!vma){
-                       printk ("SHMIQ: could not find %lx the vma\n", vaddr);
-                       return -EINVAL;
+               case QIOCATTACH: {
+                       unsigned long vaddr;
+                       int s;
+       
+                       v = verify_area (VERIFY_READ, (void *) arg,
+                                        sizeof (struct shmiqreq));
+                       if (v)
+                               return v;
+                       if (copy_from_user(&req, (void *) arg, sizeof (req)))
+                               return -EFAULT;
+                       /*
+                        * Do not allow to attach to another region if it has
+                        * already been attached
+                        */
+                       if (shmiqs [minor].mapped) {
+                               printk("SHMIQ:The thingie is already mapped\n");
+                               return -EINVAL;
+                       }
+
+                       vaddr = (unsigned long) req.user_vaddr;
+                       vma = find_vma (current->mm, vaddr);
+                       if (!vma) {
+                               printk ("SHMIQ: could not find %lx the vma\n",
+                                       vaddr);
+                               return -EINVAL;
+                       }
+                       s = req.arg * sizeof (struct shmqevent) +
+                           sizeof (struct sharedMemoryInputQueue);
+                       v = sys_munmap (vaddr, s);
+                       down(&current->mm->mmap_sem);
+                       do_munmap(current->mm, vaddr, s);
+                       do_mmap(filp, vaddr, s, PROT_READ | PROT_WRITE,
+                               MAP_PRIVATE|MAP_FIXED, 0);
+                       up(&current->mm->mmap_sem);
+                       shmiqs[minor].events = req.arg;
+                       shmiqs[minor].mapped = 1;
+
+                       return 0;
                }
-               s = req.arg * sizeof (struct shmqevent) + sizeof (struct sharedMemoryInputQueue);
-               down(&current->mm->mmap_sem);
-               do_munmap (current->mm, vaddr, s);
-               do_mmap (filp, vaddr, s, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 0);
-               up(&current->mm->mmap_sem);
-               shmiqs [minor].events = req.arg;
-               shmiqs [minor].mapped = 1;
-               return 0;
-       }
        }
+
        return -EINVAL;
 }
 
-unsigned long
-shmiq_nopage (struct vm_area_struct *vma, unsigned long address, int write_access)
+struct page *
+shmiq_nopage (struct vm_area_struct *vma, unsigned long address,
+              int write_access)
 {
        /* Do not allow for mremap to expand us */
-       return 0;
+       return NULL;
 }
 
 static struct vm_operations_struct qcntl_mmap = {
@@ -336,14+348,12 @@ shmiq_qcntl_mmap (struct file *file, struct vm_area_struct *vma)
        
        return error;
 }
-                 
+
 static int
 shmiq_qcntl_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int minor = MINOR (inode->i_rdev);
 
-       lock_kernel ();
-
        if (minor-- == 0)
                return shmiq_ioctl (inode, filp, cmd, arg);
 
@@ -387,6+397,7 @@ shmiq_qcntl_open (struct inode *inode, struct file *filp)
        shmiqs [minor].opened      = 1;
        shmiqs [minor].shmiq_vaddr = 0;
        unlock_kernel ();
+
        return 0;
 }
 
@@ -427,6+438,7 @@ shmiq_qcntl_close (struct inode *inode, struct file *filp)
        vfree (shmiqs [minor].shmiq_vaddr);
        shmiqs [minor].shmiq_vaddr = 0;
        unlock_kernel ();
+
        return 0;
 }
 
index b5a183b..1f354d8 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: streamable.c,v 1.11 2000/02/23 00:41:21 ralf Exp $
+/* $Id: streamable.c,v 1.10 2000/02/05 06:47:30 ralf Exp $
  *
  * streamable.c: streamable devices. /dev/gfx
  * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -52,14+52,14 @@ get_sioc (struct strioctl *sioc, unsigned long arg)
 static int
 sgi_gfx_open (struct inode *inode, struct file *file)
 {
-       printk ("GFX: Opened by %ld\n", current->pid);
+       printk ("GFX: Opened by %d\n", current->pid);
        return 0;
 }
 
 static int
 sgi_gfx_close (struct inode *inode, struct file *file)
 {
-       printk ("GFX: Closed by %ld\n", current->pid);
+       printk ("GFX: Closed by %d\n", current->pid);
        return 0;
 }
 
index 9ab379e..c9fbe87 100644 (file)
@@ -67,7+67,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
        struct irix_usema *usema = file->private_data;
        int retval;
        
-       printk("[%s:%ld] wants ioctl 0x%xd (arg 0x%lx)",
+       printk("[%s:%d] wants ioctl 0x%xd (arg 0x%lx)",
               current->comm, current->pid, cmd, arg);
 
        switch(cmd) {
@@ -79,7+79,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                usattach_t *attach = (usattach_t *)arg;
                retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
                if (retval) {
-                       printk("[%s:%ld] sgi_usema_ioctl(UIOCATTACHSEMA): "
+                       printk("[%s:%d] sgi_usema_ioctl(UIOCATTACHSEMA): "
                               "verify_area failure",
                               current->comm, current->pid);
                        return retval;
@@ -87,7+87,7 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if (usema == 0)
                        return -EINVAL;
 
-               printk("UIOCATTACHSEMA: attaching usema %p to process %ld\n",
+               printk("UIOCATTACHSEMA: attaching usema %p to process %d\n",
                       usema, current->pid);
                /* XXX what is attach->us_handle for? */
                return sgi_usema_attach(attach, usema);
@@ -101,12+101,12 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
                if (retval) {
-                       printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
+                       printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
                               "verify_area failure",
                               current->comm, current->pid);
                        return retval;
                }
-               printk("UIOC*BLOCK: putting process %ld to sleep on usema %p",
+               printk("UIOC*BLOCK: putting process %d to sleep on usema %p",
                       current->pid, usema);
                if (cmd == UIOCNOIBLOCK)
                        interruptible_sleep_on(&usema->proc_list);
@@ -121,13+121,13 @@ sgi_usemaclone_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
                retval = verify_area(VERIFY_READ, attach, sizeof(usattach_t));
                if (retval) {
-                       printk("[%s:%ld] sgi_usema_ioctl(UIOC*BLOCK): "
+                       printk("[%s:%d] sgi_usema_ioctl(UIOC*BLOCK): "
                               "verify_area failure",
                               current->comm, current->pid);
                        return retval;
                }
 
-               printk("[%s:%ld] releasing usema %p",
+               printk("[%s:%d] releasing usema %p",
                       current->comm, current->pid, usema);
                wake_up(&usema->proc_list);
                return 0;
@@ -141,7+141,7 @@ sgi_usemaclone_poll(struct file *filp, poll_table *wait)
 {
        struct irix_usema *usema = filp->private_data;
        
-       printk("[%s:%ld] wants to poll usema %p",
+       printk("[%s:%d] wants to poll usema %p",
               current->comm, current->pid, usema);
        
        return 0;
index 7a13236..7fa446c 100644 (file)
@@ -1572,7+1572,6 @@ static void __init probe_sccs(void)
 {
        struct dec_serial **pp;
        int i, n, n_chips = 0, n_channels, chip, channel;
-       unsigned long flags;
 
        /*
         * did we get here by accident?
@@ -1833,7+1832,6 @@ static void serial_console_write(struct console *co, const char *s,
 {
        struct dec_serial *info;
        int i;
-       unsigned char nine;
 
        info = zs_soft + co->index;
 
index cf35120..0770f44 100644 (file)
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x)         printk(KERN_DEBUG "aty128fb: %s\n",(x));
+#define DBG(fmt, args...)              printk(KERN_DEBUG "aty128fb: %s " fmt, __FUNCTION__, ##args);
 #else
-#define DBG(x)
+#define DBG(fmt, args...)
 #endif
 
 #ifndef CONFIG_PPC
@@ -104,10+104,20 @@ static struct fb_var_screeninfo default_var = {
 
 #ifndef MODULE
 /* default modedb mode */
+/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
 static struct fb_videomode defaultmode __initdata = {
-    /* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
-    NULL, 60, 640, 480, 39722, 48, 16, 33, 10, 96, 2,
-    0, FB_VMODE_NONINTERLACED
+       refresh:        60,
+       xres:           640,
+       yres:           480,
+       pixclock:       39722,
+       left_margin:    48,
+       right_margin:   16,
+       upper_margin:   33,
+       lower_margin:   10,
+       hsync_len:      96,
+       vsync_len:      2,
+       sync:           0,
+       vmode:          FB_VMODE_NONINTERLACED
 };
 #endif /* MODULE */
 
@@ -141,32+151,30 @@ static const struct aty128_chip_info aty128_pci_probe_list[] __initdata =
 
 /* packed BIOS settings */
 #ifndef CONFIG_PPC
-#pragma pack(1)
 typedef struct {
-    u8 clock_chip_type;
-    u8 struct_size;
-    u8 accelerator_entry;
-    u8 VGA_entry;
-    u16 VGA_table_offset;
-    u16 POST_table_offset;
-    u16 XCLK;
-    u16 MCLK;
-    u8 num_PLL_blocks;
-    u8 size_PLL_blocks;
-    u16 PCLK_ref_freq;
-    u16 PCLK_ref_divider;
-    u32 PCLK_min_freq;
-    u32 PCLK_max_freq;
-    u16 MCLK_ref_freq;
-    u16 MCLK_ref_divider;
-    u32 MCLK_min_freq;
-    u32 MCLK_max_freq;
-    u16 XCLK_ref_freq;
-    u16 XCLK_ref_divider;
-    u32 XCLK_min_freq;
-    u32 XCLK_max_freq;
-} PLL_BLOCK;
-#pragma pack()
+       u8 clock_chip_type;
+       u8 struct_size;
+       u8 accelerator_entry;
+       u8 VGA_entry;
+       u16 VGA_table_offset;
+       u16 POST_table_offset;
+       u16 XCLK;
+       u16 MCLK;
+       u8 num_PLL_blocks;
+       u8 size_PLL_blocks;
+       u16 PCLK_ref_freq;
+       u16 PCLK_ref_divider;
+       u32 PCLK_min_freq;
+       u32 PCLK_max_freq;
+       u16 MCLK_ref_freq;
+       u16 MCLK_ref_divider;
+       u32 MCLK_min_freq;
+       u32 MCLK_max_freq;
+       u16 XCLK_ref_freq;
+       u16 XCLK_ref_divider;
+       u32 XCLK_min_freq;
+       u32 XCLK_max_freq;
+} __attribute__ ((packed)) PLL_BLOCK;
 #endif /* !CONFIG_PPC */
 
 /* onboard memory information */
@@ -194,12+202,9 @@ static const struct aty128_meminfo sdr_sgram =
 static const struct aty128_meminfo ddr_sgram =
     { 4, 4, 3, 3, 2, 3, 1, 16, 31, 16, "64-bit DDR SGRAM" };
 
-static int currcon = 0;
-
-static char *aty128fb_name = "ATY Rage128";
+static const char *aty128fb_name = "ATY Rage128";
 static char fontname[40] __initdata = { 0 };
-static char noaccel __initdata = 0;
-static unsigned int initdepth __initdata = 8;
+static int  noaccel __initdata = 0;
 
 #ifndef MODULE
 static const char *mode_option __initdata = NULL;
@@ -291,13+296,14 @@ struct fb_info_aty128 {
     u32 cfb32[16];
 #endif
     } fbcon_cmap;
-    int blitter_may_be_busy;
 #ifdef CONFIG_PCI
     struct pci_dev *pdev;
 #endif
 #ifdef CONFIG_MTRR
     struct { int vram; int vram_valid; } mtrr;
 #endif
+    int currcon;
+    int blitter_may_be_busy;
     int fifo_slots;                 /* free slots in FIFO (64 max) */
 };
 
@@ -515,10+521,8 @@ aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
            break;
        }
 
-#ifdef DEBUG
     if (reset) /* reset engine?? */
-       DBG("PLL write timeout!");
-#endif
+       printk(KERN_DEBUG "aty128fb: PLL write timeout!");
 }
 
 
@@ -645,9+649,7 @@ aty128_reset_engine(const struct fb_info_aty128 *info)
     /* use old pio mode */
     aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
 
-#ifdef DEBUG
     DBG("engine reset");
-#endif
 }
 
 
@@ -1075,12+1077,10 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
     pll->feedback_divider = round_div(n, d);
     pll->vclk = vclk;
 
-#ifdef DEBUG
-    printk(KERN_DEBUG "var_to_pll: post %d feedback %d vlck %d output %d ref_divider %d\n", 
-           pll->post_divider, pll->feedback_divider, vclk, output_freq,
-           c.ref_divider);
-    printk(KERN_DEBUG "var_to_pll: vclk_per: %d\n", period_in_ps);
-#endif
+    DBG("post %d feedback %d vlck %d output %d ref_divider %d "
+                       "vclk_per: %d\n", pll->post_divider,
+                       pll->feedback_divider, vclk, output_freq,
+                       c.ref_divider, period_in_ps);
 
     return 0;
 }
@@ -1134,9+1134,8 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
        m->Tr2w +
        x;
 
-#ifdef DEBUG
-    printk(KERN_DEBUG "aty128fb: x %x\n", x);
-#endif
+    DBG("x %x\n", x);
+
     b = 0;
     while (x) {
        x >>= 1;
@@ -1155,10+1154,9 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
        return -EINVAL;
     }
 
-#ifdef DEBUG
-    printk(KERN_DEBUG "aty128fb: p: %x rloop: %x x: %x ron: %x roff: %x\n",
-                       p, m->Rloop, x, ron, roff);
-#endif
+    DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
+                       p, m->Rloop, x, ron, roff);
+
     dsp->dda_config = p << 16 | m->Rloop << 20 | x;
     dsp->dda_on_off = ron << 16 | roff;
 
@@ -1543,7+1541,12 @@ static int
 aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
                        struct fb_info *info)
 {
-    if (con == currcon) /* current console? */
+#if 1
+    fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2);
+#else
+    struct fb_info_aty128 fb = (struct fb_info_aty128 *)info;
+
+    if (con == fb->currcon) /* current console? */
        return fb_get_cmap(cmap, kspc, aty128_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
        fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -1551,6+1554,7 @@ aty128fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
        int size = (fb_display[con].var.bits_per_pixel <= 8) ? 256 : 32;
        fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
     }
+#endif
 
     return 0;
 }
@@ -1564,6+1568,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
                        struct fb_info *info)
 {
     int err;
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
     struct display *disp;  
 
     if (con >= 0)
@@ -1577,7+1582,7 @@ aty128fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
            return err;
     }
 
-    if (con == currcon) /* current console? */
+    if (con == fb->currcon) /* current console? */
        return fb_set_cmap(cmap, kspc, aty128_setcolreg, info);
     else
        fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
@@ -1632,24+1637,6 @@ aty128fb_setup(char *options)
            fontname[i] = 0;
        } else if (!strncmp(this_opt, "noaccel", 7)) {
            noaccel = 1;
-       } else if (!strncmp(this_opt, "depth:", 6)) {
-            unsigned int depth = simple_strtoul(this_opt+6, NULL, 0);
-            switch (depth) {
-            case 0 ... 8:
-                initdepth = 8;
-                break;
-            case 9 ... 16:
-                initdepth = 16;
-                break;
-            case 17 ... 24:
-                initdepth = 24;
-                break;
-            case 25 ... 32:
-                initdepth = 32;
-                break;
-            default:
-                initdepth = 8;
-            }
         }
 #ifdef CONFIG_MTRR
         else if(!strncmp(this_opt, "nomtrr", 6)) {
@@ -1762,7+1749,7 @@ aty128_init(struct fb_info_aty128 *info, const char *name)
 #endif /* CONFIG_PPC */
     {
         if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
-                          &defaultmode, initdepth) == 0)
+                          &defaultmode, 8) == 0)
             var = default_var;
     }
 #endif /* MODULE */
@@ -1859,16+1846,6 @@ aty128_pci_register(struct pci_dev *pdev,
     u32 fb_addr, reg_addr, io_addr = 0;
     int err;
 
-#if 0
-    /* Request resources we're going to use */
-    io_addr = pci_resource_start(pdev, 1);
-    if (!request_region(io_addr, pci_resource_len(pdev, 1),
-                        "aty128fb IO")) {
-        printk(KERN_ERR "aty128fb: cannot reserve I/O ports\n");
-        goto err_out_none;
-    }
-#endif
-
     fb_addr = pci_resource_start(pdev, 0);
     if (!request_mem_region(fb_addr, pci_resource_len(pdev, 0),
                             "aty128fb FB")) {
@@ -1894,6+1871,8 @@ aty128_pci_register(struct pci_dev *pdev,
     /* Copy PCI device info into info->pdev */
     info->pdev = pdev;
 
+    info->currcon = -1;
+
     /* Virtualize mmio region */
     info->regbase_phys = reg_addr;
     info->regbase = ioremap(reg_addr, 0x1FFF);
@@ -1966,7+1945,6 @@ err_free_mmio:
 err_free_fb:
     release_mem_region(pci_resource_start(pdev, 1),
                        pci_resource_len(pdev, 1));
-err_out_none:
     return -ENODEV;
 }
 #endif /* CONFIG_PCI */
@@ -2072,13+2050,12 @@ aty128_get_pllinfo(struct fb_info_aty128 *info)
     if (bios_seg)
         iounmap(bios_seg);
 
-#ifdef DEBUG
-    printk(KERN_DEBUG "get_pllinfo: ppll_max %d ppll_min %d xclk %d "
-                      "ref_divider %d dotclock %d\n", 
-                   info->constants.ppll_max, info->constants.ppll_min,
-                   info->constants.xclk, info->constants.ref_divider,
-                   info->constants.dotclock);
-#endif
+    DBG("ppll_max %d ppll_min %d xclk %d "
+                       "ref_divider %d dotclock %d\n",
+                       info->constants.ppll_max, info->constants.ppll_min,
+                       info->constants.xclk, info->constants.ref_divider,
+                       info->constants.dotclock);
+
     return;
 }           
 #endif /* !CONFIG_PPC */
@@ -2159,11+2136,12 @@ aty128fbcon_switch(int con, struct fb_info *fb)
     struct aty128fb_par par;
 
     /* Do we have to save the colormap? */
-    if (fb_display[currcon].cmap.len)
-       fb_get_cmap(&fb_display[currcon].cmap, 1, aty128_getcolreg, fb);
+    if (fb_display[info->currcon].cmap.len)
+       fb_get_cmap(&fb_display[info->currcon].cmap, 1,
+                       aty128_getcolreg, fb);
 
     /* set the current console */
-    currcon = con;
+    info->currcon = con;
 
     aty128_decode_var(&fb_display[con].var, &par, info);
     aty128_set_par(&par, info);
@@ -2319,7+2297,9 @@ aty128_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 static void
 do_install_cmap(int con, struct fb_info *info)
 {
-    if (con != currcon)
+    struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
+
+    if (con != fb->currcon)
        return;
 
     if (fb_display[con].cmap.len)
index f482476..fff0a4f 100644 (file)
@@ -85,7+85,7 @@ static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
                int mode,
                unsigned int pos) {
        u_int32_t tmp;
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
        switch (mode) {
                case 15:
@@ -250,9+250,9 @@ static void initMatroxDH(struct matroxfb_dh_fb_info* m2info, struct display* p)
 
 static int matroxfb_dh_open(struct fb_info* info, int user) {
 #define m2info ((struct matroxfb_dh_fb_info*)info)
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
-       if (minfo) {
+       if (MINFO) {
                if (ACCESS_FBINFO(dead)) {
                        return -ENXIO;
                }
@@ -263,9+263,9 @@ static int matroxfb_dh_open(struct fb_info* info, int user) {
 
 static int matroxfb_dh_release(struct fb_info* info, int user) {
 #define m2info ((struct matroxfb_dh_fb_info*)info)
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
-       if (minfo) {
+       if (MINFO) {
        }
        return 0;
 #undef m2info
@@ -320,7+320,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
        int cmap_len;
        int mode;
        int err;
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
        if (con < 0)
                p = m2info->fbcon.disp;
@@ -477,7+477,7 @@ static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con,
 static int matroxfb_dh_switch(int con, struct fb_info* info);
 
 static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
        memset(vblank, 0, sizeof(*vblank));
        vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
@@ -496,7+496,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
                int con,
                struct fb_info* info) {
 #define m2info ((struct matroxfb_dh_fb_info*)info)
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       MINFO_FROM(m2info->primary_dev);
 
        DBG("matroxfb_crtc2_ioctl")
 
@@ -516,7+516,7 @@ static int matroxfb_dh_ioctl(struct inode* inode,
                case MATROXFB_GET_OUTPUT_MODE:
                case MATROXFB_GET_ALL_OUTPUTS:
                        {
-                               return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &minfo->fbcon);
+                               return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &ACCESS_FBINFO(fbcon));
                        }
                case MATROXFB_SET_OUTPUT_CONNECTION:
                        {
@@ -660,15+660,15 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
        if (mem < 64*1024)
                mem *= 1024;
        mem &= ~0x00000FFF;     /* PAGE_MASK? */
-       if (minfo->video.len_usable + mem <= minfo->video.len)
-               m2info->video.offbase = minfo->video.len - mem;
-       else if (minfo->video.len < mem) {
+       if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len))
+               m2info->video.offbase = ACCESS_FBINFO(video.len) - mem;
+       else if (ACCESS_FBINFO(video.len) < mem) {
                kfree(d);
                return -ENOMEM;
        } else { /* check yres on first head... */
                m2info->video.borrowed = mem;
-               minfo->video.len_usable -= mem;
-               m2info->video.offbase = minfo->video.len_usable;
+               ACCESS_FBINFO(video.len_usable) -= mem;
+               m2info->video.offbase = ACCESS_FBINFO(video.len_usable);
        }
        m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase;
        m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
@@ -698,8+698,8 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {
                matroxfb_dh_set_var(&matroxfb_dh_defined, -1, &m2info->fbcon);
        }
        down_write(&ACCESS_FBINFO(crtc2.lock));
-       oldcrtc2 = minfo->crtc2.info;
-       minfo->crtc2.info = &m2info->fbcon;
+       oldcrtc2 = ACCESS_FBINFO(crtc2.info);
+       ACCESS_FBINFO(crtc2.info) = &m2info->fbcon;
        up_write(&ACCESS_FBINFO(crtc2.lock));
        if (oldcrtc2) {
                printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
@@ -731,9+731,9 @@ static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
                struct fb_info* crtc2;
 
                down_write(&ACCESS_FBINFO(crtc2.lock));
-               crtc2 = minfo->crtc2.info;
+               crtc2 = ACCESS_FBINFO(crtc2.info);
                if (crtc2 == &m2info->fbcon)
-                       minfo->crtc2.info = NULL;
+                       ACCESS_FBINFO(crtc2.info) = NULL;
                up_write(&ACCESS_FBINFO(crtc2.lock));
                if (crtc2 != &m2info->fbcon) {
                        printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
@@ -756,7+756,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
        struct matroxfb_dh_fb_info* m2info;
 
        /* hardware is CRTC2 incapable... */
-       if (!minfo->devflags.crtc2)
+       if (!ACCESS_FBINFO(devflags.crtc2))
                return NULL;
        m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);
        if (!m2info) {
@@ -764,7+764,7 @@ static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
                return NULL;
        }
        memset(m2info, 0, sizeof(*m2info));
-       m2info->primary_dev = minfo;
+       m2info->primary_dev = MINFO;
        if (matroxfb_dh_registerfb(m2info)) {
                kfree(m2info);
                printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
index e7d515e..57b8222 100644 (file)
@@ -892,9+892,9 @@ static struct matrox_altout maven_altout = {
 
 static int maven_init_client(struct i2c_client* clnt) {
        struct i2c_adapter* a = clnt->adapter;
-       struct matroxfb_dh_maven_info* m2info = ((struct i2c_bit_adapter*)a)->minfo;
        struct maven_data* md = clnt->data;
-       struct matrox_fb_info* minfo = m2info->primary_dev;
+       struct matroxfb_dh_maven_info* m2info __attribute__((unused)) = ((struct i2c_bit_adapter*)a)->minfo;
+       MINFO_FROM(m2info->primary_dev);
 
        md->mode = MODE_MONITOR;
        md->primary_head = MINFO;
index 3d461df..eae607e 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: newport_con.c,v 1.14 1999/06/24 01:10:24 ulfc Exp $
- *
+/*
  * newport_con.c: Abscon for newport hardware
  * 
  * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
@@ -504,7+503,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, int lines)
        x = 0; y = b-lines;
        for (count = 0; count < (lines * vc->vc_cols); count++) {
            if (scr_readw(d) != vc->vc_video_erase_char) {
-               newport_putc (vc, chattr, y, x);
+               newport_putc (vc, vc->vc_video_erase_char, y, x);
                scr_writew (vc->vc_video_erase_char, d);
            }
            d++;
index 6a4e41e..23fc979 100644 (file)
@@ -4,7+4,7 @@
  *  Created 8 August 1998 by Martin Costabel and Kevin Schoedel
  *
  *  Vmode-switching changes and vmode 15/17 modifications created 29 August
- *  1998 by Barry Nathan <barryn@pobox.com>.
+ *  1998 by Barry K. Nathan <barryn@pobox.com>.
  *
  *  Derived directly from:
  *
index ee246a4..c8984b3 100644 (file)
@@ -4,7+4,7 @@
  * Created 8 August 1998 by Martin Costabel and Kevin Schoedel
  *
  * Vmode-switching changes and vmode 15/17 modifications created 29 August
- * 1998 by Barry Nathan <barryn@pobox.com>.
+ * 1998 by Barry K. Nathan <barryn@pobox.com>.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 38f16f0..7f0e511 100644 (file)
@@ -407,13+407,21 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                goto out;
        if (!elf_check_arch(elf_ex.e_machine))
                goto out;
-#ifdef __mips__
-       /* IRIX binaries handled elsewhere. */
+#if defined(__mips__) && !defined(__mips64)
+       /* IRIX5 binaries handled elsewhere.  */
        if (elf_ex.e_flags & EF_MIPS_ARCH) {
                retval = -ENOEXEC;
                goto out;
        }
 #endif
+#if defined(__mips__) && defined(__mips64)
+       /* Linux/MIPS 32-bit binaries handled elsewhere.  */
+       if (sizeof(elf_caddr_t) == 8 &&
+           elf_ex.e_ident[EI_CLASS] == ELFCLASS32) {
+               retval = -ENOEXEC;
+               goto out;
+       }
+#endif
        if (!bprm->file->f_op||!bprm->file->f_op->mmap)
                goto out;
 
index 3de8547..0f9c59c 100644 (file)
@@ -557,7+557,7 @@ int shrink_dcache_memory(int priority, unsigned int gfp_mask)
 {
        int count = 0;
        if (priority)
-               count = dentry_stat.nr_unused >> (priority >> 2);
+               count = dentry_stat.nr_unused / priority;
        prune_dcache(count);
        /* FIXME: kmem_cache_shrink here should tell us
           the number of pages freed, and it should
index 046d384..0874d6d 100644 (file)
@@ -854,6+854,7 @@ retry:
        if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
                return;
        }
+       lock_kernel();
        if (!(bh = fat_bread(sb, i_pos >> MSDOS_DPB_BITS))) {
                printk("dev = %s, ino = %d\n", kdevname(inode->i_dev), i_pos);
                fat_fs_panic(sb, "msdos_write_inode: unable to read i-node block");
index 3dc0cba..6fadbd8 100644 (file)
@@ -25,13+25,15 @@ if [ "$CONFIG_PARTITION_ADVANCED" = "y" ]; then
       bool '    Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
    fi
    bool '  SGI partition support' CONFIG_SGI_PARTITION
+   bool '  Ultrix partition table support' CONFIG_ULTRIX_PARTITION
    bool '  Sun partition tables support' CONFIG_SUN_PARTITION
 else
    if [ "$ARCH" = "alpha" ]; then
       define_bool CONFIG_OSF_PARTITION y
    fi
    if [ "$CONFIG_AMIGA" != "y" -a "$CONFIG_ATARI" != "y" -a \
-        "$CONFIG_MAC" != "y" ]; then
+        "$CONFIG_MAC" != "y" -a "$CONFIG_SGI_IP22" != "y" -a \
+       "$CONFIG_SGI_IP27" != "y" ]; then
       define_bool CONFIG_MSDOS_PARTITION y
    fi
    if [ "$CONFIG_AMIGA" = "y" ]; then
@@ -51,9+53,12 @@ else
    if [ "$CONFIG_ATARI" = "y" ]; then
       define_bool CONFIG_ATARI_PARTITION y
    fi
-   if [ "$CONFIG_SGI" = "y" ]; then
+   if [ "$CONFIG_SGI_IP22" = "y" -o "$CONFIG_SGI_IP27" = "y" ]; then
       define_bool CONFIG_SGI_PARTITION y
    fi
+   if [ "$CONFIG_DECSTATION" = "y" ]; then
+      define_bool CONFIG_ULTRIX_PARTITION y
+   fi
    if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
       define_bool CONFIG_SUN_PARTITION y
    fi
index 0fb8c4c..291e8e6 100644 (file)
 #include "sgi.h"
 #include "sun.h"
 #include "ibm.h"
+#include "ultrix.h"
 
 extern void device_init(void);
 extern void md_run_setup(void);
index a001735..aa49ba5 100644 (file)
 
 #include "check.h"
 
-static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
+int ultrix_partition(struct gendisk *hd, kdev_t dev,
+                            unsigned long first_sector, int first_part_minor)
 {
-       int i, minor = current_minor;
+       int i;
        struct buffer_head *bh;
        struct ultrix_disklabel {
                s32     pt_magic;       /* magic no. indicating part. info exits */
@@ -44,9+45,9 @@ static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_
                                             - sizeof(struct ultrix_disklabel));
 
        if (label->pt_magic == PT_MAGIC && label->pt_valid == PT_VALID) {
-               for (i=0; i<8; i++, minor++)
+               for (i=0; i<8; i++, first_part_minor++)
                        if (label->pt_part[i].pi_nblocks)
-                               add_gd_partition(hd, minor, 
+                               add_gd_partition(hd, first_part_minor, 
                                              label->pt_part[i].pi_blkoff,
                                              label->pt_part[i].pi_nblocks);
                brelse(bh);
@@ -57,4+58,3 @@ static int ultrix_partition(struct gendisk *hd, kdev_t dev, unsigned long first_
                return 0;
        }
 }
-
diff --git a/fs/partitions/ultrix.h b/fs/partitions/ultrix.h
new file mode 100644 (file)
index 0000000..d2259db
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ *  fs/partitions/ultrix.h
+ */
+
+int ultrix_partition(struct gendisk *hd, kdev_t dev,
+                     unsigned long first_sector, int first_part_minor);
+
index d731122..3ca996e 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -259,7+259,7 @@ asmlinkage long sys_readlink(const char * path, char * buf, int bufsiz)
 
 
 /* ---------- LFS-64 ----------- */
-#if !defined(__alpha__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined (__ia64__) && !defined(__mips64)
 
 static long cp_new_stat64(struct inode * inode, struct stat64 * statbuf)
 {
index a7ad1fb..637889c 100644 (file)
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             19
index 595ba22..a421e6d 100644 (file)
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 9dc6c33..c44d16b 100644 (file)
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nasty libc5 fixup - bletch */
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
index f6cf730..1cb3b96 100644 (file)
  * four billion cycles just basically sounds like a good idea,
  * regardless of how fast the machine is. 
  */
-typedef unsigned long cycles_t;
+typedef unsigned long long cycles_t;
 
 extern cycles_t cacheflush_time;
 
@@ -38,10+38,10 @@ static inline cycles_t get_cycles (void)
 #ifndef CONFIG_X86_TSC
        return 0;
 #else
-       unsigned long eax, edx;
+       unsigned long long ret;
 
-       rdtsc(eax,edx);
-       return eax;
+       rdtscll(ret);
+       return ret;
 #endif
 }
 
index 877ed2e..5d5eb7b 100644 (file)
 #define SO_DETACH_FILTER       27
 
 #define SO_PEERNAME            28
-
-#define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 2d97e06..fa13cd8 100644 (file)
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 98fe1ec..7628fe4 100644 (file)
@@ -36,11+36,12 @@ __delay(unsigned long loops)
  */
 extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 {
+       unsigned long lo;
+
        usecs *= 0x000010c6;            /* 2**32 / 1000000 */
-       __asm__("multu\t%0,%2\n\t"
-               "mfhi\t%0"
-               :"=r" (usecs)
-               :"0" (usecs),"r" (lps));
+       __asm__("multu\t%2,%3"
+               :"=h" (usecs), "=l" (lo)
+               :"r" (usecs),"r" (lps));
        __delay(usecs);
 }
 
index 67d8051..ffdf1b8 100644 (file)
-/* $Id: floppy.h,v 1.6 1999/01/04 16:09:21 ralf Exp $
- *
+/*
  * Architecture specific parts of the Floppy driver
  *
  * 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) 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1995 - 2000 Ralf Baechle
  */
 #ifndef _ASM_FLOPPY_H
 #define _ASM_FLOPPY_H
@@ -41,30+40,30 @@ struct fd_ops {
 
 extern struct fd_ops *fd_ops;
 
-#define fd_inb(port)                   fd_ops->fd_inb(port)
-#define fd_outb(value,port)            fd_ops->fd_outb(value,port)
-
-#define fd_enable_dma(channel)         fd_ops->fd_enable_dma(channel)
-#define fd_disable_dma(channel)                fd_ops->fd_disable_dma(channel)
-#define fd_request_dma(channel)                fd_ops->fd_request_dma(channel)
-#define fd_free_dma(channel)           fd_ops->fd_free_dma(channel)
-#define fd_clear_dma_ff(channel)       fd_ops->fd_clear_dma_ff(channel)
-#define fd_set_dma_mode(channel, mode) fd_ops->fd_set_dma_mode(channel, mode)
-#define fd_set_dma_addr(channel, addr) fd_ops->fd_set_dma_addr(channel, \
-                                                virt_to_bus(addr))
-#define fd_set_dma_count(channel,count)        fd_ops->fd_set_dma_count(channel,count)
-#define fd_get_dma_residue(channel)    fd_ops->fd_get_dma_residue(channel)
-
-#define fd_enable_irq(irq)             fd_ops->fd_enable_irq(irq)
-#define fd_disable_irq(irq)            fd_ops->fd_disable_irq(irq)
-#define fd_request_irq(irq)            request_irq(irq, floppy_interrupt, \
-                                                   SA_INTERRUPT \
-                                                   | SA_SAMPLE_RANDOM, \
-                                                   "floppy", NULL)
-#define fd_free_irq(irq)               free_irq(irq, NULL);
-#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
+#define fd_inb(port)           fd_ops->fd_inb(port)
+#define fd_outb(value,port)    fd_ops->fd_outb(value,port)
+
+#define fd_enable_dma()                fd_ops->fd_enable_dma(FLOPPY_DMA)
+#define fd_disable_dma()       fd_ops->fd_disable_dma(FLOPPY_DMA)
+#define fd_request_dma()       fd_ops->fd_request_dma(FLOPPY_DMA)
+#define fd_free_dma()          fd_ops->fd_free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff()      fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode)  fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
+#define fd_set_dma_addr(addr)  fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
+                                                      virt_to_bus(addr))
+#define fd_set_dma_count(count)        fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
+#define fd_get_dma_residue()   fd_ops->fd_get_dma_residue(FLOPPY_DMA)
+
+#define fd_enable_irq()                fd_ops->fd_enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq()       fd_ops->fd_disable_irq(FLOPPY_IRQ)
+#define fd_request_irq()       request_irq(FLOPPY_IRQ, floppy_interrupt, \
+                                           SA_INTERRUPT | SA_SAMPLE_RANDOM, \
+                                           "floppy", NULL)
+#define fd_free_irq()          free_irq(FLOPPY_IRQ, NULL);
+#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
 #define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n)               fd_ops->fd_drive_type(n)
+#define fd_drive_type(n)       fd_ops->fd_drive_type(n)
+#define fd_cacheflush(addr,size) dma_cache_wback_inv(addr,size)
 
 #define MAX_BUFFER_SECTORS 24
 
@@ -79,7+78,14 @@ extern struct fd_ops *fd_ops;
 #define FLOPPY1_TYPE                   fd_drive_type(1)
 
 #define FDC1                   fd_ops->fd_getfdaddr1();
-static int FDC2=-1;
+
+/*
+ * Hack: The floppy drivrer defines this, before including fdreg.h.  We use
+ * to define FDC2 only one and keep it a static variable in floppy.c.
+ */
+#ifdef FDPATCHES
+static int FDC2 = -1;
+#endif
 
 #define N_FDC 1                        /* do you *really* want a second controller? */
 #define N_DRIVE 8
index 032acd2..011247f 100644 (file)
@@ -20,9+20,17 @@ extern pte_t *kmap_pte;
 extern pgprot_t kmap_prot;
 
 #define kmap_init()                    do { } while(0)
-#define kmap(page)                     page_address(page)
+
+static __inline__ unsigned long kmap(struct page * page) {
+       return page_address(page);
+}
+
 #define kunmap(page)                   do { } while(0)
-#define kmap_atomic(page, type)                page_address(page)
+
+static __inline__ unsigned long kmap_atomic(struct page *page, int type) {
+       return page_address(page)
+}
+
 #define kunmap_atomic(page, type)      do { } while(0)
 
 #endif /* _ASM_HIGHMEM_H */
index d668356..ed20997 100644 (file)
-/* $Id: ide.h,v 1.6 1999/10/09 00:01:42 ralf Exp $
+/*
+ * 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.
  *
- *  linux/include/asm-mips/ide.h
+ * This file contains the MIPS architecture specific IDE code.
  *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ * Copyright (C) 1994-1996  Linus Torvalds & authors
  */
 
 /*
  *  This file contains the MIPS architecture specific IDE code.
  */
 
-#ifndef __ASM_MIPS_IDE_H
-#define __ASM_MIPS_IDE_H
+#ifndef __ASM_IDE_H
+#define __ASM_IDE_H
 
 #ifdef __KERNEL__
 
@@ -53,27+56,34 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index)
        return ide_ops->ide_default_io_base(index);
 }
 
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
-                                           ide_ioreg_t data_port,
-                                           ide_ioreg_t ctrl_port, int *irq)
+static inline void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
+                                       ide_ioreg_t ctrl_port, int *irq)
 {
-       ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, &hw->irq);
+       ide_ioreg_t reg = data_port;
+       int i;
 
-       hw->irq = ide_ops->ide_default_irq(data_port);
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+               hw->io_ports[i] = reg;
+               reg += 1;
+       }
+       if (ctrl_port) {
+               hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+       } else {
+               hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+       }
+       if (irq != NULL)
+               *irq = 0;
+       hw->io_ports[IDE_IRQ_OFFSET] = 0;
 }
 
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
 static __inline__ void ide_init_default_hwifs(void)
 {
 #ifndef CONFIG_BLK_DEV_IDEPCI
        hw_regs_t hw;
        int index;
 
-       for (index = 0; index < MAX_HWIFS; index++) {
-               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+       for(index = 0; index < MAX_HWIFS; index++) {
+               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
                hw.irq = ide_default_irq(ide_default_io_base(index));
                ide_register_hw(&hw, NULL);
        }
@@ -129,4+139,4 @@ static __inline__ void ide_release_region(ide_ioreg_t from,
 
 #endif /* __KERNEL__ */
 
-#endif /* __ASM_MIPS_IDE_H */
+#endif /* __ASM_IDE_H */
index 70c4d81..303f989 100644 (file)
@@ -25,6+25,7 @@ extern char pckbd_unexpected_up(unsigned char keycode);
 extern void pckbd_leds(unsigned char leds);
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
+extern void kbd_forward_char (int ch);
 
 #define kbd_setkeycode         pckbd_setkeycode
 #define kbd_getkeycode         pckbd_getkeycode
index 23ed82c..f7a29a8 100644 (file)
@@ -234,6+234,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 #define ST0_UX                 0x00000020
 #define ST0_SX                 0x00000040
 #define ST0_KX                         0x00000080
+#define ST0_DE                 0x00010000
+#define ST0_CE                 0x00020000
 
 /*
  * Bitfields in the R[23]000 cp0 status register.
@@ -245,6+247,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 #define ST0_IEO                        0x00000010
 #define ST0_KUO                        0x00000020
 /* bits 6 & 7 are reserved on R[23]000 */
+#define ST0_ISC                        0x00010000
+#define ST0_SWC                        0x00020000
 
 /*
  * Bits specific to the R4640/R4650
@@ -273,8+277,6 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 #define  STATUSF_IP6           (1   << 14)
 #define  STATUSB_IP7           15
 #define  STATUSF_IP7           (1   << 15)
-#define ST0_DE                 0x00010000
-#define ST0_CE                 0x00020000
 #define ST0_CH                 0x00040000
 #define ST0_SR                 0x00100000
 #define ST0_BEV                        0x00400000
diff --git a/include/asm-mips/offset.h b/include/asm-mips/offset.h
deleted file mode 100644 (file)
index 42d7a5b..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
-
-#ifndef _MIPS_OFFSET_H
-#define _MIPS_OFFSET_H
-
-/* MIPS pt_regs offsets. */
-#define PT_R0     24
-#define PT_R1     28
-#define PT_R2     32
-#define PT_R3     36
-#define PT_R4     40
-#define PT_R5     44
-#define PT_R6     48
-#define PT_R7     52
-#define PT_R8     56
-#define PT_R9     60
-#define PT_R10    64
-#define PT_R11    68
-#define PT_R12    72
-#define PT_R13    76
-#define PT_R14    80
-#define PT_R15    84
-#define PT_R16    88
-#define PT_R17    92
-#define PT_R18    96
-#define PT_R19    100
-#define PT_R20    104
-#define PT_R21    108
-#define PT_R22    112
-#define PT_R23    116
-#define PT_R24    120
-#define PT_R25    124
-#define PT_R26    128
-#define PT_R27    132
-#define PT_R28    136
-#define PT_R29    140
-#define PT_R30    144
-#define PT_R31    148
-#define PT_LO     152
-#define PT_HI     156
-#define PT_EPC    160
-#define PT_BVADDR 164
-#define PT_STATUS 168
-#define PT_CAUSE  172
-#define PT_SIZE   176
-
-/* MIPS task_struct offsets. */
-#define TASK_STATE         0
-#define TASK_FLAGS         4
-#define TASK_SIGPENDING    8
-#define TASK_NEED_RESCHED  20
-#define TASK_COUNTER       32
-#define TASK_PRIORITY      36
-#define TASK_MM            44
-#define TASK_STRUCT_SIZE   880
-
-/* MIPS specific thread_struct offsets. */
-#define THREAD_REG16   584
-#define THREAD_REG17   588
-#define THREAD_REG18   592
-#define THREAD_REG19   596
-#define THREAD_REG20   600
-#define THREAD_REG21   604
-#define THREAD_REG22   608
-#define THREAD_REG23   612
-#define THREAD_REG29   616
-#define THREAD_REG30   620
-#define THREAD_REG31   624
-#define THREAD_STATUS  628
-#define THREAD_FPU     632
-#define THREAD_BVADDR  768
-#define THREAD_BUADDR  772
-#define THREAD_ECODE   776
-#define THREAD_TRAPNO  780
-#define THREAD_MFLAGS  784
-#define THREAD_CURDS   788
-#define THREAD_TRAMP   792
-#define THREAD_OLDCTX  796
-
-/* Linux mm_struct offsets. */
-#define MM_USERS      16
-#define MM_PGD        12
-#define MM_CONTEXT    68
-
-/* Linux sigcontext offsets. */
-#define SC_REGS       16
-#define SC_FPREGS     272
-#define SC_MDHI       544
-#define SC_MDLO       552
-#define SC_PC         8
-#define SC_STATUS     4
-#define SC_OWNEDFP    528
-#define SC_FPC_CSR    532
-#define SC_FPC_EIR    536
-#define SC_CAUSE      560
-#define SC_BADVADDR   564
-
-#endif /* !(_MIPS_OFFSET_H) */
index 09380c8..82110a4 100644 (file)
     */
 #  define QUOTIENT ((1UL << (32 - LOG_2_HZ)) * 100)
 #  define HZ_TO_STD(a)                            \
-   ({ int __res;                                  \
-        __asm__(                                  \
-           "multu\t%0,%2\n\t"                    \
-           "mfhi\t%0"                            \
-        : "=r" (__res): "0" (a), "r" (QUOTIENT)); \
-        __res;})
+   ({ unsigned int __res;                        \
+      unsigned long lo;                                  \
+        __asm__("multu\t%2,%3\n\t"               \
+               :"=h" (__res), "=l" (lo)          \
+               :"r" (a),"r" (QUOTIENT));         \
+        (__typeof__(a)) __res;})
 #else
 #  define HZ 100
 #  define HZ_TO_STD(a) (a)
index a21e78b..f72b7dd 100644 (file)
@@ -1,5+1,4 @@
-/* $Id: pgtable.h,v 1.31 2000/03/02 02:37:13 ralf Exp $
- *
+/*
  * 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.
@@ -43,7+42,13 @@ extern void (*_flush_page_to_ram)(struct page * page);
 #define flush_page_to_ram(page)                _flush_page_to_ram(page)
 
 #define flush_icache_range(start, end) flush_cache_all()
-#define flush_icache_page(start,page)  do { } while(0)
+
+#define flush_icache_page(vma, page)                                   \
+do {                                                                   \
+       unsigned long addr;                                             \
+       addr = page_address(page);                                      \
+       _flush_cache_page(vma, addr);                                   \
+} while (0)
 
 
 /*
index a1e1080..6c48b3f 100644 (file)
  * assume GCC is being used.
  */
 
-typedef unsigned long  __kernel_dev_t;
+typedef unsigned int   __kernel_dev_t;
 typedef unsigned long  __kernel_ino_t;
-typedef unsigned long  __kernel_mode_t;
-typedef unsigned long  __kernel_nlink_t;
+typedef unsigned int   __kernel_mode_t;
+typedef int            __kernel_nlink_t;
 typedef long           __kernel_off_t;
-typedef long           __kernel_pid_t;
-typedef long           __kernel_ipc_pid_t;
-typedef long           __kernel_uid_t;
-typedef long           __kernel_gid_t;
+typedef int            __kernel_pid_t;
+typedef int            __kernel_ipc_pid_t;
+typedef int            __kernel_uid_t;
+typedef int            __kernel_gid_t;
 typedef unsigned int   __kernel_size_t;
 typedef int            __kernel_ssize_t;
 typedef int            __kernel_ptrdiff_t;
@@ -35,8+35,8 @@ typedef char *                __kernel_caddr_t;
 
 typedef unsigned short __kernel_uid16_t;
 typedef unsigned short __kernel_gid16_t;
-typedef long           __kernel_uid32_t;
-typedef long           __kernel_gid32_t;
+typedef int            __kernel_uid32_t;
+typedef int            __kernel_gid32_t;
 typedef __kernel_uid_t __kernel_old_uid_t;
 typedef __kernel_gid_t __kernel_old_gid_t;
 
index 559edac..b395fe1 100644 (file)
 #define FPC_CSR                69
 #define FPC_EIR                70
 
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
 /*
  * This struct defines the way the registers are stored on the stack during a
  * system call/exception. As usual the registers k0/k1 aren't being saved.
@@ -50,13+50,15 @@ struct pt_regs {
        unsigned long cp0_cause;
 };
 
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY) */
 
+#ifdef _LANGUAGE_ASSEMBLY
 #include <asm/offset.h>
+#endif
 
 #ifdef __KERNEL__
 
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
 /*
  * Does the process account for user or for system time?
  */
@@ -65,7+67,7 @@ struct pt_regs {
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 
 extern void show_regs(struct pt_regs *);
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY) */
 
 #endif
 
index 6b9c6ba..b6eb8e4 100644 (file)
@@ -133,8+133,6 @@ waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
 {
        long ret, tmp;
 
-#ifdef __MIPSEB__
-
         __asm__ __volatile__("
        .set    push
        .set    mips3
@@ -159,46+157,6 @@ waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
        : "=&r"(ret), "=&r"(tmp), "=m"(*sem)
        : "r"(signal_pending(tsk)), "i"(-EINTR));
 
-#elif defined(__MIPSEL__)
-
-       __asm__ __volatile__("
-       .set    mips3
-       .set    push
-       .set    noat
-0:
-       lld     %1, %2
-       li      %0, 0
-       blez    %1, 1f
-       dli     $1, 0x0000000100000000
-       dsubu   %1, %1, $1
-       li      %0, 1
-       b       2f
-1:
-       beqz    %3, 2f
-       li      %0, %4
-       /* 
-        * It would be nice to assume that sem->count
-        * is != -1, but we will guard against that case
-        */
-       daddiu  $1, %1, 1
-       dsll32  $1, $1, 0
-       dsrl32  $1, $1, 0
-       dsrl32  %1, %1, 0
-       dsll32  %1, %1, 0
-       or      %1, %1, $1
-2:
-       scd     %1, %2
-       beqz    %1, 0b
-
-       .set    pop
-       .set    mips0"
-       : "=&r"(ret), "=&r"(tmp), "=m"(*sem)
-       : "r"(signal_pending(tsk)), "i"(-EINTR));
-
-#else
-#error "MIPS but neither __MIPSEL__ nor __MIPSEB__?"
-#endif
-
        return ret;
 }
 
diff --git a/include/asm-mips/sfp-machine.h b/include/asm-mips/sfp-machine.h
new file mode 100644 (file)
index 0000000..3b2a40f
--- /dev/null
@@ -0,0 +1,47 @@
+#define _FP_W_TYPE_SIZE                32
+#define _FP_W_TYPE             unsigned long
+#define _FP_WS_TYPE            signed long
+#define _FP_I_TYPE             long
+
+#define _FP_MUL_MEAT_S(R,X,Y)                          \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y)                          \
+  _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)                          \
+  _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S          ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D          ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q          ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+/* From my experiments it seems X is chosen unless one of the
+   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                     \
+  do {                                                         \
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) |                           \
+        _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs)         \
+      {                                                                \
+       R##_s = _FP_NANSIGN_##fs;                               \
+        _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs);                 \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+       R##_s = X##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,X);                               \
+      }                                                                \
+    R##_c = FP_CLS_NAN;                                                \
+  } while (0)
+
+#define FP_EX_INVALID           (1 << 4)
+#define FP_EX_DIVZERO           (1 << 3)
+#define FP_EX_OVERFLOW          (1 << 2)
+#define FP_EX_UNDERFLOW         (1 << 1)
+#define FP_EX_INEXACT           (1 << 0)
index 59a30e9..50d6224 100644 (file)
 #define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
 
 typedef struct {
-       __u32 sig[_NSIG_WORDS];
+       unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
 typedef unsigned long old_sigset_t;            /* at least 32 bits */
index b98107c..a0e63bb 100644 (file)
@@ -1,6+1,3 @@
-/*
- * $Id: socket.h,v 1.6 2000/02/25 21:52:09 ralf Exp $
- */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
@@ -56,9+53,9 @@ To add: #define SO_REUSEPORT 0x0200   /* Allow local address and port reuse.  */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
-#ifdef __KERNEL__
-
 #define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 8dc6698..e8892d3 100644 (file)
@@ -1,5+1,5 @@
-#ifndef __ASM_MIPS_STAT_H
-#define __ASM_MIPS_STAT_H
+#ifndef _ASM_STAT_H
+#define _ASM_STAT_H
 
 #include <linux/types.h>
 
@@ -52,41+52,35 @@ struct stat {
        unsigned int    st_gen;
 };
 
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- * XXX We don't ship glibc 2.1 for MIPS yet, so this structure may be
- * changed without breaking compatibility.  You've been warned.
+/*
+ * This matches struct stat64 in glibc2.1, hence the absolutely insane
+ * amounts of padding around dev_t's.  The memory layout is the same as of
+ * struct stat of the 64-bit kernel.
  */
+
 struct stat64 {
        unsigned long   st_dev;
-       unsigned char   __pad0[8];
-
-       unsigned long   st_ino;
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned short  st_rdev;
-       unsigned char   __pad3[10];
-
+       unsigned long   st_pad0[3];     /* Reserved for st_dev expansion  */
+       ino_t           st_ino;
+       mode_t          st_mode;
+       nlink_t         st_nlink;
+       uid_t           st_uid;
+       gid_t           st_gid;
+       unsigned long   st_rdev;
+       unsigned long   st_pad1[3];     /* Reserved for st_rdev expansion  */
        long long       st_size;
+       /*
+        * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+        * but we don't have it under Linux.
+        */
+       time_t          st_atime;
+       unsigned long   reserved0;      /* Reserved for st_atime expansion  */
+       time_t          st_mtime;
+       unsigned long   reserved1;      /* Reserved for st_atime expansion  */
+       time_t          st_ctime;
+       unsigned long   reserved2;      /* Reserved for st_atime expansion  */
        unsigned long   st_blksize;
-
-       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
-       unsigned long   __pad4;         /* future possible st_blocks high bits */
-
-       unsigned long   st_atime;
-       unsigned long   __pad5;
-
-       unsigned long   st_mtime;
-       unsigned long   __pad6;
-
-       unsigned long   st_ctime;
-       unsigned long   __pad7;         /* will be high 32 bits of ctime someday */
-
-       unsigned long   __unused1;
-       unsigned long   __unused2;
+       long long       st_blocks;
 };
-#endif /* __ASM_MIPS_STAT_H */
+
+#endif /* _ASM_STAT_H */
index a1f5534..91a7b05 100644 (file)
@@ -267,6+267,7 @@ extern void __die(const char *, struct pt_regs *, const char *where,
        unsigned long line) __attribute__((noreturn));
 extern void __die_if_kernel(const char *, struct pt_regs *, const char *where,
        unsigned long line);
+extern int abs(int);
 
 #define die(msg, regs)                                                 \
        __die(msg, regs, __FILE__ ":"__FUNCTION__, __LINE__)
index d7bf84e..638f751 100644 (file)
 #ifndef _ASM_TYPES_H
 #define _ASM_TYPES_H
 
-typedef unsigned long umode_t;
+typedef unsigned short umode_t;
 
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
index 6235cf4..2d3cc95 100644 (file)
-/* $Id: uaccess.h,v 1.12 2000/02/21 18:05:07 ralf Exp $
- *
+/*
  * 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) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
@@ -70,16+69,20 @@ extern inline int verify_area(int type, const void * addr, unsigned long size)
  * (a) re-use the arguments for side effects (sizeof is ok)
  * (b) require any knowledge of processes at this stage
  */
-#define put_user(x,ptr)        __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define put_user(x,ptr)        \
+       __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) \
+       __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /*
  * The "__xxx" versions do not do address space checking, useful when
  * doing multiple accesses to the same area (the user has to do the
  * checks by hand with "access_ok()")
  */
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) \
+       __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) \
+       __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /*
  * The "xxx_ret" versions return constant specified in third argument, if
@@ -127,14+130,14 @@ case 8: __GET_USER_DW; break; \
 default: __get_user_unknown(); break; \
 } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
 
-#define __get_user_check(x,ptr,size,mask) ({ \
+#define __get_user_check(x,ptr,size) ({ \
 long __gu_err; \
 __typeof__(*(ptr)) __gu_val; \
 long __gu_addr; \
 __asm__("":"=r" (__gu_val)); \
 __gu_addr = (long) (ptr); \
 __asm__("":"=r" (__gu_err)); \
-if (__access_ok(__gu_addr,size,mask)) { \
+if (__access_ok(__gu_addr,size,__access_mask)) { \
 switch (size) { \
 case 1: __get_user_asm("lb"); break; \
 case 2: __get_user_asm("lh"); break; \
@@ -210,14+213,14 @@ case 8: __PUT_USER_DW; break; \
 default: __put_user_unknown(); break; \
 } __pu_err; })
 
-#define __put_user_check(x,ptr,size,mask) ({ \
+#define __put_user_check(x,ptr,size) ({ \
 long __pu_err; \
 __typeof__(*(ptr)) __pu_val; \
 long __pu_addr; \
 __pu_val = (x); \
 __pu_addr = (long) (ptr); \
 __asm__("":"=r" (__pu_err)); \
-if (__access_ok(__pu_addr,size,mask)) { \
+if (__access_ok(__pu_addr,size,__access_mask)) { \
 switch (size) { \
 case 1: __put_user_asm("sb"); break; \
 case 2: __put_user_asm("sh"); break; \
index 1591e10..bfbdebb 100644 (file)
 #define PHYS_TO_COMPATK1(x)    ((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
 #endif
 
+#define KDM_TO_PHYS(x) ((unsigned long)(x) & TO_PHYS_MASK)
+#define PHYS_TO_K0(x)  ((unsigned long)(x) | K0BASE)
+
 #endif /* _ASM_ADDRSPACE_H */
index 2913275..b2d28e9 100644 (file)
-/* $Id$
- *
+/*
  * 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 Waldorf Electronics
- * Copyright (C) 1995 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_DELAY_H
 #define _ASM_DELAY_H
 
 #include <linux/config.h>
 
+#include <linux/config.h>
+
 extern __inline__ void
 __delay(unsigned long loops)
 {
@@ -37,11+38,12 @@ __delay(unsigned long loops)
  */
 extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 {
+       unsigned long lo;
+
        usecs *= 0x000010c6f7a0b5edUL;          /* 2**64 / 1000000 */
-       __asm__("dmultu\t%0,%2\n\t"
-               "mfhi\t%0"
-               :"=r" (usecs)
-               :"0" (usecs),"r" (lps));
+       __asm__("dmultu\t%2,%3"
+               :"=h" (usecs), "=l" (lo)
+               :"r" (usecs),"r" (lps));
        __delay(usecs);
 }
 
index e1caa02..df2f47f 100644 (file)
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
-#include <linux/config.h>
 #include <asm/io.h>                    /* need byte IO */
 #include <linux/spinlock.h>            /* And spinlocks */
 #include <linux/delay.h>
similarity index 62%
copy from include/asm-mips/floppy.h
copy to include/asm-mips64/floppy.h
index 67d8051..8eac1c7 100644 (file)
-/* $Id: floppy.h,v 1.6 1999/01/04 16:09:21 ralf Exp $
- *
+/*
  * Architecture specific parts of the Floppy driver
  *
  * 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) 1995, 1996, 1997, 1998 Ralf Baechle
+ * Copyright (C) 1995 - 2000 Ralf Baechle
  */
 #ifndef _ASM_FLOPPY_H
 #define _ASM_FLOPPY_H
 
 #include <asm/bootinfo.h>
-#include <asm/jazz.h>
-#include <asm/jazzdma.h>
 
 struct fd_ops {
        unsigned char (*fd_inb)(unsigned int port);
@@ -41,30+38,30 @@ struct fd_ops {
 
 extern struct fd_ops *fd_ops;
 
-#define fd_inb(port)                   fd_ops->fd_inb(port)
-#define fd_outb(value,port)            fd_ops->fd_outb(value,port)
-
-#define fd_enable_dma(channel)         fd_ops->fd_enable_dma(channel)
-#define fd_disable_dma(channel)                fd_ops->fd_disable_dma(channel)
-#define fd_request_dma(channel)                fd_ops->fd_request_dma(channel)
-#define fd_free_dma(channel)           fd_ops->fd_free_dma(channel)
-#define fd_clear_dma_ff(channel)       fd_ops->fd_clear_dma_ff(channel)
-#define fd_set_dma_mode(channel, mode) fd_ops->fd_set_dma_mode(channel, mode)
-#define fd_set_dma_addr(channel, addr) fd_ops->fd_set_dma_addr(channel, \
-                                                virt_to_bus(addr))
-#define fd_set_dma_count(channel,count)        fd_ops->fd_set_dma_count(channel,count)
-#define fd_get_dma_residue(channel)    fd_ops->fd_get_dma_residue(channel)
-
-#define fd_enable_irq(irq)             fd_ops->fd_enable_irq(irq)
-#define fd_disable_irq(irq)            fd_ops->fd_disable_irq(irq)
-#define fd_request_irq(irq)            request_irq(irq, floppy_interrupt, \
-                                                   SA_INTERRUPT \
-                                                   | SA_SAMPLE_RANDOM, \
-                                                   "floppy", NULL)
-#define fd_free_irq(irq)               free_irq(irq, NULL);
-#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
+#define fd_inb(port)           fd_ops->fd_inb(port)
+#define fd_outb(value,port)    fd_ops->fd_outb(value,port)
+
+#define fd_enable_dma()                fd_ops->fd_enable_dma(FLOPPY_DMA)
+#define fd_disable_dma()       fd_ops->fd_disable_dma(FLOPPY_DMA)
+#define fd_request_dma()       fd_ops->fd_request_dma(FLOPPY_DMA)
+#define fd_free_dma()          fd_ops->fd_free_dma(FLOPPY_DMA)
+#define fd_clear_dma_ff()      fd_ops->fd_clear_dma_ff(FLOPPY_DMA)
+#define fd_set_dma_mode(mode)  fd_ops->fd_set_dma_mode(FLOPPY_DMA, mode)
+#define fd_set_dma_addr(addr)  fd_ops->fd_set_dma_addr(FLOPPY_DMA, \
+                                                      virt_to_bus(addr))
+#define fd_set_dma_count(count)        fd_ops->fd_set_dma_count(FLOPPY_DMA,count)
+#define fd_get_dma_residue()   fd_ops->fd_get_dma_residue(FLOPPY_DMA)
+
+#define fd_enable_irq()                fd_ops->fd_enable_irq(FLOPPY_IRQ)
+#define fd_disable_irq()       fd_ops->fd_disable_irq(FLOPPY_IRQ)
+#define fd_request_irq()       request_irq(FLOPPY_IRQ, floppy_interrupt, \
+                                           SA_INTERRUPT | SA_SAMPLE_RANDOM, \
+                                           "floppy", NULL)
+#define fd_free_irq()          free_irq(FLOPPY_IRQ, NULL);
+#define fd_dma_mem_alloc(size) fd_ops->fd_dma_mem_alloc(size)
 #define fd_dma_mem_free(mem,size) fd_ops->fd_dma_mem_free(mem,size)
-#define fd_drive_type(n)               fd_ops->fd_drive_type(n)
+#define fd_drive_type(n)       fd_ops->fd_drive_type(n)
+#define fd_cacheflush(addr,size) dma_cache_wback_inv(addr,size)
 
 #define MAX_BUFFER_SECTORS 24
 
@@ -79,7+76,14 @@ extern struct fd_ops *fd_ops;
 #define FLOPPY1_TYPE                   fd_drive_type(1)
 
 #define FDC1                   fd_ops->fd_getfdaddr1();
+
+/*
+ * Hack: The floppy drivrer defines this, before including fdreg.h.  We use
+ * to define FDC2 only one and keep it a static variable in floppy.c.
+ */
+#ifdef FDPATCHES
 static int FDC2=-1;
+#endif
 
 #define N_FDC 1                        /* do you *really* want a second controller? */
 #define N_DRIVE 8
similarity index 75%
copy from include/asm-mips/ide.h
copy to include/asm-mips64/ide.h
index d668356..ed20997 100644 (file)
-/* $Id: ide.h,v 1.6 1999/10/09 00:01:42 ralf Exp $
+/*
+ * 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.
  *
- *  linux/include/asm-mips/ide.h
+ * This file contains the MIPS architecture specific IDE code.
  *
- *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ * Copyright (C) 1994-1996  Linus Torvalds & authors
  */
 
 /*
  *  This file contains the MIPS architecture specific IDE code.
  */
 
-#ifndef __ASM_MIPS_IDE_H
-#define __ASM_MIPS_IDE_H
+#ifndef __ASM_IDE_H
+#define __ASM_IDE_H
 
 #ifdef __KERNEL__
 
@@ -53,27+56,34 @@ static __inline__ ide_ioreg_t ide_default_io_base(int index)
        return ide_ops->ide_default_io_base(index);
 }
 
-static __inline__ void ide_init_hwif_ports(hw_regs_t *hw,
-                                           ide_ioreg_t data_port,
-                                           ide_ioreg_t ctrl_port, int *irq)
+static inline void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port,
+                                       ide_ioreg_t ctrl_port, int *irq)
 {
-       ide_ops->ide_init_hwif_ports(hw, data_port, ctrl_port, &hw->irq);
+       ide_ioreg_t reg = data_port;
+       int i;
 
-       hw->irq = ide_ops->ide_default_irq(data_port);
+       for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+               hw->io_ports[i] = reg;
+               reg += 1;
+       }
+       if (ctrl_port) {
+               hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+       } else {
+               hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+       }
+       if (irq != NULL)
+               *irq = 0;
+       hw->io_ports[IDE_IRQ_OFFSET] = 0;
 }
 
-/*
- * This registers the standard ports for this architecture with the IDE
- * driver.
- */
 static __inline__ void ide_init_default_hwifs(void)
 {
 #ifndef CONFIG_BLK_DEV_IDEPCI
        hw_regs_t hw;
        int index;
 
-       for (index = 0; index < MAX_HWIFS; index++) {
-               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+       for(index = 0; index < MAX_HWIFS; index++) {
+               ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
                hw.irq = ide_default_irq(ide_default_io_base(index));
                ide_register_hw(&hw, NULL);
        }
@@ -129,4+139,4 @@ static __inline__ void ide_release_region(ide_ioreg_t from,
 
 #endif /* __KERNEL__ */
 
-#endif /* __ASM_MIPS_IDE_H */
+#endif /* __ASM_IDE_H */
index a1ca449..dcedea9 100644 (file)
@@ -162,7+162,7 @@ out:
  */
 
 #define __OUT1(s) \
-extern inline void __out##s(unsigned int value, unsigned int port) {
+extern inline void __out##s(unsigned int value, unsigned long port) {
 
 #define __OUT2(m) \
 __asm__ __volatile__ ("s" #m "\t%0,%1(%2)"
@@ -176,7+176,7 @@ __OUT1(s##c_p) __OUT2(m) : : "r" (value), "ir" (port), "r" (mips_io_port_base));
        SLOW_DOWN_IO; }
 
 #define __IN1(t,s) \
-extern __inline__ t __in##s(unsigned int port) { t _v;
+extern __inline__ t __in##s(unsigned long port) { t _v;
 
 /*
  * Required nops will be inserted by the assembler
@@ -191,7+191,7 @@ __IN1(t,s##_p) __IN2(m) : "=r" (_v) : "i" (0), "r" (mips_io_port_base+port)); SL
 __IN1(t,s##c_p) __IN2(m) : "=r" (_v) : "ir" (port), "r" (mips_io_port_base)); SLOW_DOWN_IO; return _v; }
 
 #define __INS1(s) \
-extern inline void __ins##s(unsigned int port, void * addr, unsigned long count) {
+extern inline void __ins##s(unsigned long port, void * addr, unsigned long count) {
 
 #define __INS2(m) \
 if (count) \
@@ -217,7+217,7 @@ __INS1(s##c) __INS2(m) \
        : "$1");}
 
 #define __OUTS1(s) \
-extern inline void __outs##s(unsigned int port, const void * addr, unsigned long count) {
+extern inline void __outs##s(unsigned long port, const void * addr, unsigned long count) {
 
 #define __OUTS2(m) \
 if (count) \
index 5baa58f..0319556 100644 (file)
 #ifndef _ASM_IRQ_H
 #define _ASM_IRQ_H
 
-#define NR_IRQS 64
+#define NR_IRQS 256
 
 #define TIMER_IRQ 0
 
index cddc66d..08ef50e 100644 (file)
@@ -213,6+213,8 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 #define ST0_UX                 0x00000020
 #define ST0_SX                 0x00000040
 #define ST0_KX                         0x00000080
+#define ST0_DE                 0x00010000
+#define ST0_CE                 0x00020000
 
 /*
  * Status register bits available in all MIPS CPUs.
@@ -234,8+236,6 @@ __BUILD_SET_CP0(config,CP0_CONFIG)
 #define  STATUSF_IP6           (1   << 14)
 #define  STATUSB_IP7           15
 #define  STATUSF_IP7           (1   << 15)
-#define ST0_DE                 0x00010000
-#define ST0_CE                 0x00020000
 #define ST0_CH                 0x00040000
 #define ST0_SR                 0x00100000
 #define ST0_TS                 0x00200000
index eeb8d90..0a31078 100644 (file)
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 
+/*
+ * For the fast tlb miss handlers, we currently keep a per cpu array
+ * of pointers to the current pgd for each processor. Also, the proc.
+ * id is stuffed into the context register. This should be changed to 
+ * use the processor id via current->processor, where current is stored
+ * in watchhi/lo. The context register should be used to contiguously
+ * map the page tables.
+ */
+#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
+       pgd_current[smp_processor_id()] = (unsigned long)(pgd)
+#define TLBMISS_HANDLER_SETUP() \
+       set_context((unsigned long) smp_processor_id() << (23 + 3)); \
+       TLBMISS_HANDLER_SETUP_PGD(swapper_pg_dir)
+extern unsigned long pgd_current[];
+
 #ifndef CONFIG_SMP
 #define CPU_CONTEXT(cpu, mm)   (mm)->context
 #else
@@ -85,7+100,8 @@ extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
        if ((CPU_CONTEXT(cpu, next) ^ ASID_CACHE(cpu)) & ASID_VERSION_MASK)
                get_new_cpu_mmu_context(next, cpu);
 
-       set_entryhi(CPU_CONTEXT(cpu, next));
+       set_entryhi(CPU_CONTEXT(cpu, next) & 0xff);
+       TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 }
 
 /*
@@ -110,7+126,8 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
        /* Unconditionally get a new ASID.  */
        get_new_cpu_mmu_context(next, smp_processor_id());
 
-       set_entryhi(CPU_CONTEXT(smp_processor_id(), next));
+       set_entryhi(CPU_CONTEXT(smp_processor_id(), next) & 0xff);
+       TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 }
 
 #endif /* _ASM_MMU_CONTEXT_H */
index 795aed3..2c6af1d 100644 (file)
@@ -8,9+8,11 @@
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
+#include <asm/sn/klkernvars.h>
 
 typedef struct plat_pglist_data {
        pg_data_t       gendata;
+       kern_vars_t     kern_vars;
 } plat_pg_data_t;
 
 /*
@@ -27,6+29,8 @@ extern plat_pg_data_t *plat_node_data[];
 #define PLAT_NODE_DATA_LOCALNR(p, n) \
                (((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
 
+#define numa_node_id() cputocnode(current->processor)
+
 #ifdef CONFIG_DISCONTIGMEM
 
 /*
diff --git a/include/asm-mips64/offset.h b/include/asm-mips64/offset.h
deleted file mode 100644 (file)
index 1397e32..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */
-
-#ifndef _MIPS_OFFSET_H
-#define _MIPS_OFFSET_H
-
-/* MIPS pt_regs offsets. */
-#define PT_R0     0
-#define PT_R1     8
-#define PT_R2     16
-#define PT_R3     24
-#define PT_R4     32
-#define PT_R5     40
-#define PT_R6     48
-#define PT_R7     56
-#define PT_R8     64
-#define PT_R9     72
-#define PT_R10    80
-#define PT_R11    88
-#define PT_R12    96
-#define PT_R13    104
-#define PT_R14    112
-#define PT_R15    120
-#define PT_R16    128
-#define PT_R17    136
-#define PT_R18    144
-#define PT_R19    152
-#define PT_R20    160
-#define PT_R21    168
-#define PT_R22    176
-#define PT_R23    184
-#define PT_R24    192
-#define PT_R25    200
-#define PT_R26    208
-#define PT_R27    216
-#define PT_R28    224
-#define PT_R29    232
-#define PT_R30    240
-#define PT_R31    248
-#define PT_LO     256
-#define PT_HI     264
-#define PT_EPC    272
-#define PT_BVADDR 280
-#define PT_STATUS 288
-#define PT_CAUSE  296
-#define PT_SIZE   304
-
-/* MIPS task_struct offsets. */
-#define TASK_STATE         0
-#define TASK_FLAGS         8
-#define TASK_SIGPENDING    16
-#define TASK_NEED_RESCHED  40
-#define TASK_COUNTER       56
-#define TASK_PRIORITY      64
-#define TASK_MM            80
-#define TASK_PROCESSOR     100
-#define TASK_STRUCT_SIZE   1432
-
-/* MIPS specific thread_struct offsets. */
-#define THREAD_REG16   896
-#define THREAD_REG17   904
-#define THREAD_REG18   912
-#define THREAD_REG19   920
-#define THREAD_REG20   928
-#define THREAD_REG21   936
-#define THREAD_REG22   944
-#define THREAD_REG23   952
-#define THREAD_REG29   960
-#define THREAD_REG30   968
-#define THREAD_REG31   976
-#define THREAD_STATUS  984
-#define THREAD_FPU     992
-#define THREAD_BVADDR  1256
-#define THREAD_BUADDR  1264
-#define THREAD_ECODE   1272
-#define THREAD_TRAPNO  1280
-#define THREAD_MFLAGS  1288
-#define THREAD_CURDS   1296
-#define THREAD_TRAMP   1304
-#define THREAD_OLDCTX  1312
-
-/* Linux mm_struct offsets. */
-#define MM_USERS      32
-#define MM_PGD        24
-#define MM_CONTEXT    112
-
-/* Linux sigcontext offsets. */
-#define SC_REGS       0
-#define SC_FPREGS     256
-#define SC_MDHI       512
-#define SC_MDLO       520
-#define SC_PC         528
-#define SC_STATUS     536
-#define SC_OWNEDFP    540
-#define SC_FPC_CSR    544
-#define SC_FPC_EIR    548
-#define SC_CAUSE      552
-#define SC_BADVADDR   556
-
-#endif /* !(_MIPS_OFFSET_H) */
index 27bcf83..16c45aa 100644 (file)
-/* $Id: page.h,v 1.6 2000/02/24 00:13:20 ralf Exp $
- *
+/*
  * 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 - 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_PAGE_H
 #define _ASM_PAGE_H
index 981baa1..f958c4d 100644 (file)
 #ifndef HZ
 #define HZ 100
 #  define HZ 100
+#ifdef __KERNEL__
 #  define HZ_TO_STD(a) (a)
 #endif
+#endif
 
 #define EXEC_PAGESIZE  4096
 
index 74d3e29..d9a7660 100644 (file)
@@ -149,32+149,11 @@ extern void __bad_pte(pmd_t *pmd);
 extern void __bad_pte_kernel(pmd_t *pmd);
 extern void __bad_pmd(pgd_t *pgd);
 
-#define pte_free_kernel(pte)    free_pte_fast(pte)
 #define pte_free(pte)           free_pte_fast(pte)
-#define pmd_free_kernel(pte)    free_pmd_fast(pte)
 #define pmd_free(pte)           free_pmd_fast(pte)
 #define pgd_free(pgd)           free_pgd_fast(pgd)
 #define pgd_alloc()             get_pgd_fast()
 
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
-       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-       if (pmd_none(*pmd)) {
-               pte_t *page = get_pte_fast();
-               if (page) {
-                       pmd_val(*pmd) = (unsigned long) page;
-                       return page + address;
-               }
-               return get_pte_kernel_slow(pmd, address);
-       }
-       if (pmd_bad(*pmd)) {
-               __bad_pte_kernel(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + address;
-}
-
 extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
 {
        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
@@ -212,35+191,22 @@ extern inline pmd_t *pmd_alloc(pgd_t * pgd, unsigned long address)
        return (pmd_t *) pgd_page(*pgd) + address;
 }
 
-#define pmd_alloc_kernel       pmd_alloc
+extern pte_t kptbl[(PAGE_SIZE<<KPTBL_PAGE_ORDER)/sizeof(pte_t)];
+extern pmd_t kpmdtbl[PTRS_PER_PMD];
+
+#define pmd_alloc_kernel(d,a)  (pmd_t *)kpmdtbl
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+       return (kptbl + (address >> PAGE_SHIFT));
+}
 
 extern int do_check_pgt_cache(int, int);
 
 extern inline void set_pgdir(unsigned long address, pgd_t entry)
 {
-       struct task_struct * p;
-       pgd_t *pgd;
-#ifdef CONFIG_SMP
-       int i;
-#endif 
-        
-       read_lock(&tasklist_lock);
-       for_each_task(p) {
-               if (!p->mm)
-                       continue;
-               *pgd_offset(p->mm, address) = entry;
-       }
-       read_unlock(&tasklist_lock);
-#ifndef CONFIG_SMP
-       for (pgd = (pgd_t *)pgd_quicklist; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-               pgd[address >> PGDIR_SHIFT] = entry;
-#else
-       /* To pgd_alloc/pgd_free, one holds master kernel lock and so does our
-          callee, so we can modify pgd caches of other CPUs as well. -jj */
-       for (i = 0; i < NR_CPUS; i++)
-               for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd; pgd = (pgd_t *)*(unsigned long *)pgd)
-                       pgd[address >> PGDIR_SHIFT] = entry;
-#endif
+       printk("set_pgdir!\n");
+       while(1);
 }
 
 #endif /* _ASM_PGALLOC_H */
index af4251f..b0c97ce 100644 (file)
-/* $Id: pgtable.h,v 1.14 2000/03/02 02:37:13 ralf Exp $
- *
+/*
  * 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 - 1999 by Ralf Baechle at alii
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1994 - 2000 by Ralf Baechle at alii
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_PGTABLE_H
 #define _ASM_PGTABLE_H
@@ -44,14+43,32 @@ extern void (*_flush_page_to_ram)(struct page * page);
 #define flush_page_to_ram(page)                _flush_page_to_ram(page)
 
 #define flush_icache_range(start, end) flush_cache_all()
-#define flush_icache_page(start, page) do { } while(0)
 
+#define flush_icache_page(vma, page)                                   \
+do {                                                                   \
+       unsigned long addr;                                             \
+       addr = page_address(page);                                      \
+       _flush_cache_page(vma, addr);                                   \
+} while (0)                                                              
 
-/* Basically we have the same two-level (which is the logical three level
- * Linux page table layout folded) page tables as the i386.  Some day
- * when we have proper page coloring support we can have a 1% quicker
- * tlb refill handling mechanism, but for now it is a bit slower but
- * works even with the cache aliasing problem the R4k and above have.
+/*
+ * Each address space has 2 4K pages as its page directory, giving 1024
+ * (== PTRS_PER_PGD) 8 byte pointers to pmd tables. Each pmd table is a
+ * pair of 4K pages, giving 1024 (== PTRS_PER_PMD) 8 byte pointers to
+ * page tables. Each page table is a single 4K page, giving 512 (==
+ * PTRS_PER_PTE) 8 byte ptes. Each pgde is initialized to point to
+ * invalid_pmd_table, each pmde is initialized to point to 
+ * invalid_pte_table, each pte is initialized to 0. When memory is low,
+ * and a pmd table or a page table allocation fails, empty_bad_pmd_table
+ * and empty_bad_page_table is returned back to higher layer code, so
+ * that the failure is recognized later on. Linux does not seem to 
+ * handle these failures very well though. The empty_bad_page_table has
+ * invalid pte entries in it, to force page faults.
+ * Vmalloc handling: vmalloc uses swapper_pg_dir[0] (returned by 
+ * pgd_offset_k), which is initalized to point to kpmdtbl. kpmdtbl is 
+ * the only single page pmd in the system. kpmdtbl entries point into 
+ * kptbl[] array. We reserve 1<<KPTBL_PAGE_ORDER pages to hold the
+ * vmalloc range translations, which the fault handler looks at.
  */
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
@@ -74,9+91,11 @@ extern void (*_flush_page_to_ram)(struct page * page);
 #define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
 #define FIRST_USER_PGD_NR      0
 
+#define KPTBL_PAGE_ORDER  1
 #define VMALLOC_START     XKSEG
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END       (KSEG3 + (1UL << 40))        /* 1 TB */
+#define VMALLOC_END       \
+  (VMALLOC_START + ((1 << KPTBL_PAGE_ORDER) * PTRS_PER_PTE * PAGE_SIZE))
 
 /* Note that we shift the lower 32bits of each EntryLo[01] entry
  * 6 bits to the left. That way we can convert the PFN into the
@@ -205,8+224,10 @@ extern unsigned long zero_page_mask;
 #define PAGE_PTR(address) \
 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 
-extern pte_t invalid_pte_table[2*PAGE_SIZE/sizeof(pte_t)];
+extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)];
+extern pte_t empty_bad_page_table[PAGE_SIZE/sizeof(pte_t)];
 extern pmd_t invalid_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
+extern pmd_t empty_bad_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
 
 /*
  * Conversion functions: convert a page and protection to a page entry,
@@ -271,13+292,7 @@ extern inline int pmd_none(pmd_t pmd)
 
 extern inline int pmd_bad(pmd_t pmd)
 {
-       return ((pmd_page(pmd) > (unsigned long) high_memory) ||
-               (pmd_page(pmd) < PAGE_OFFSET));
-}
-
-extern inline int pmd_present(pmd_t pmd)
-{
-       return pmd_val(pmd) != (unsigned long) invalid_pte_table;
+       return pmd_val(pmd) == (unsigned long) empty_bad_page_table;
 }
 
 extern inline void pmd_clear(pmd_t *pmdp)
@@ -295,13+310,7 @@ extern inline int pgd_none(pgd_t pgd)
 
 extern inline int pgd_bad(pgd_t pgd)
 {
-       return ((pgd_page(pgd) > (unsigned long) high_memory) ||
-               (pgd_page(pgd) < PAGE_OFFSET));
-}
-
-extern inline int pgd_present(pgd_t pgd)
-{
-       return pgd_val(pgd) != (unsigned long) invalid_pmd_table;
+       return pgd_val(pgd) == (unsigned long) empty_bad_pmd_table;
 }
 
 extern inline void pgd_clear(pgd_t *pgdp)
@@ -438,7+447,7 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define page_pte(page) page_pte_prot(page, __pgprot(0))
 
 /* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+#define pgd_offset_k(address) pgd_offset(&init_mm, 0)
 
 #define pgd_index(address)     ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
 
@@ -465,9+474,8 @@ extern inline pte_t *pte_offset(pmd_t * dir, unsigned long address)
 /*
  * Initialize a new pgd / pmd table with invalid pointers.
  */
-extern void pte_init(unsigned long page);
 extern void pgd_init(unsigned long page);
-extern void pmd_init(unsigned long page);
+extern void pmd_init(unsigned long page, unsigned long pagetable);
 
 extern pgd_t swapper_pg_dir[1024];
 extern void paging_init(void);
index 44ab256..e1395fb 100644 (file)
-/* $Id: posix_types.h,v 1.5 2000/02/29 20:49:16 ulfc Exp $
- *
+/*
  * 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) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_POSIX_TYPES_H
 #define _ASM_POSIX_TYPES_H
@@ -28,9+27,9 @@ typedef int           __kernel_gid_t;
 typedef unsigned long  __kernel_size_t;
 typedef long           __kernel_ssize_t;
 typedef long            __kernel_ptrdiff_t;
-typedef int            __kernel_time_t;
+typedef long           __kernel_time_t;
 typedef long           __kernel_suseconds_t;
-typedef int            __kernel_clock_t;
+typedef long           __kernel_clock_t;
 typedef long           __kernel_daddr_t;
 typedef char *         __kernel_caddr_t;
 
@@ -66,7+65,7 @@ typedef int           __kernel_time_t32;
 typedef int            __kernel_suseconds_t32;
 typedef int            __kernel_clock_t32;
 typedef int            __kernel_daddr_t32;
-typedef char *         __kernel_caddr_t32;
+typedef unsigned int   __kernel_caddr_t32;
 typedef __kernel_fsid_t        __kernel_fsid_t32;
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
index 1932672..565d6cb 100644 (file)
-/* $Id: processor.h,v 1.11 2000/03/14 01:39:27 ralf Exp $
- *
+/*
  * 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 Waldorf GMBH
- * Copyright (C) 1995, 1996, 1997, 1998, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Ralf Baechle
  * Modified further for R[236]000 compatibility by Paul M. Antoine
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 #include <linux/config.h>
 
 /*
- * Default implementation of macro that returns current
- * instruction pointer ("program counter").
+ * Return current * instruction pointer ("program counter").
+ *
+ * Two implementations.  The ``la'' version results in shorter code for
+ * the kernel which we assume to reside in the 32-bit compat address space.
+ * The  ``jal'' version is for use by modules which live in outer space.
+ * This is just a single instruction unlike the long dla macro expansion.
  */
-#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+#ifdef MODULE
+#define current_text_addr()                                            \
+({                                                                     \
+       void *_a;                                                       \
+                                                                       \
+       __asm__ ("jal\t1f, 1f\n\t"                                      \
+               "1:"                                                    \
+               : "=r" (_a));                                           \
+                                                                       \
+       _a;                                                             \
+})
+#else
+#define current_text_addr()                                            \
+({                                                                     \
+       void *_a;                                                       \
+                                                                       \
+       __asm__ ("dla\t%0, 1f\n\t"                                      \
+               "1:"                                                    \
+               : "=r" (_a));                                           \
+                                                                       \
+       _a;                                                             \
+})
+#endif
 
 #if !defined (_LANGUAGE_ASSEMBLY)
 #include <asm/cachectl.h>
@@ -41,6+66,7 @@ struct cpuinfo_mips {
        unsigned int irq_count, bh_count;
        unsigned long asid_cache;
 #if defined(CONFIG_SGI_IP27)
+       cpuid_t         p_cpuid;        /* PROM assigned cpuid */
        cnodeid_t       p_nodeid;       /* my node ID in compact-id-space */
        nasid_t         p_nasid;        /* my node ID in numa-as-id-space */
        unsigned char   p_slice;        /* Physical position on node board */
index ff5745e..fcf067d 100644 (file)
 #define FPC_CSR                69
 #define FPC_EIR                70
 
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
 
 #define abi64_no_regargs                                               \
        unsigned long __dummy0,                                         \
@@ -55,19+55,21 @@ struct pt_regs {
        unsigned long cp0_cause;
 };
 
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY__) */
 
+#ifdef _LANGUAGE_ASSEMBLY
 #include <asm/offset.h>
+#endif /* (_LANGUAGE_ASSEMBLY__) */
 
 #ifdef __KERNEL__
 
-#ifndef __ASSEMBLY__
+#ifndef _LANGUAGE_ASSEMBLY
 #define instruction_pointer(regs) ((regs)->cp0_epc)
 
 extern void (*_show_regs)(struct pt_regs *);
 #define show_regs(regs)        _show_regs(regs)
 
-#endif /* !(__ASSEMBLY__) */
+#endif /* !(_LANGUAGE_ASSEMBLY__) */
 
 #endif
 
index 199a9a4..b4af331 100644 (file)
        { RLIM_INFINITY, RLIM_INFINITY },               \
        { _STK_LIM,      RLIM_INFINITY },               \
        {        0,      RLIM_INFINITY },               \
-       { NR_OPEN,       NR_OPEN },                     \
+       { INR_OPEN,      INR_OPEN },                    \
        { RLIM_INFINITY, RLIM_INFINITY },               \
        { RLIM_INFINITY, RLIM_INFINITY },               \
        { 0,             0             },               \
index 82abb1f..4da0ce9 100644 (file)
  * The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
  */
 #define IOC3_BAUD (22000000 / (3*16))
-#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_IOC3)
+#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
 /* Let the compiler figure out the size.  */
 #define RS_TABLE_SIZE
diff --git a/include/asm-mips64/sfp-machine.h b/include/asm-mips64/sfp-machine.h
new file mode 100644 (file)
index 0000000..730deae
--- /dev/null
@@ -0,0 +1,47 @@
+#define _FP_W_TYPE_SIZE                64
+#define _FP_W_TYPE             unsigned long
+#define _FP_WS_TYPE            signed long
+#define _FP_I_TYPE             long
+
+#define _FP_MUL_MEAT_S(R,X,Y)                                  \
+  _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
+#define _FP_MUL_MEAT_D(R,X,Y)                                  \
+  _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y)                                  \
+  _FP_MUL_MEAT_2_wide_3mul(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y)  _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
+#define _FP_DIV_MEAT_D(R,X,Y)  _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y)  _FP_DIV_MEAT_2_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S          ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D          ((_FP_QNANBIT_D << 1) - 1)
+#define _FP_NANFRAC_Q          ((_FP_QNANBIT_Q << 1) - 1), -1
+#define _FP_NANSIGN_S          0
+#define _FP_NANSIGN_D          0
+#define _FP_NANSIGN_Q          0
+
+#define _FP_KEEPNANFRACP 1
+/* From my experiments it seems X is chosen unless one of the
+   NaNs is sNaN,  in which case the result is NANSIGN/NANFRAC.  */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)                     \
+  do {                                                         \
+    if ((_FP_FRAC_HIGH_RAW_##fs(X) |                           \
+        _FP_FRAC_HIGH_RAW_##fs(Y)) & _FP_QNANBIT_##fs)         \
+      {                                                                \
+       R##_s = _FP_NANSIGN_##fs;                               \
+        _FP_FRAC_SET_##wc(R,_FP_NANFRAC_##fs);                 \
+      }                                                                \
+    else                                                       \
+      {                                                                \
+       R##_s = X##_s;                                          \
+        _FP_FRAC_COPY_##wc(R,X);                               \
+      }                                                                \
+    R##_c = FP_CLS_NAN;                                                \
+  } while (0)
+
+#define FP_EX_INVALID           (1 << 4)
+#define FP_EX_DIVZERO           (1 << 3)
+#define FP_EX_OVERFLOW          (1 << 2)
+#define FP_EX_UNDERFLOW         (1 << 1)
+#define FP_EX_INEXACT           (1 << 0)
index 706d8fb..ab7719a 100644 (file)
 #ifndef _ASM_SN_ADDRS_H
 #define _ASM_SN_ADDRS_H
 
-#include <linux/config.h>
 #if _LANGUAGE_C
 #include <linux/types.h>
 #endif /* _LANGUAGE_C */
 #define UALIAS_FLIP_BASE       UALIAS_BASE
 #define UALIAS_FLIP_SIZE       0x20000
 #define UALIAS_FLIP_BIT                0x10000
-#define UALIAS_FLIP_ADDR(_x)   (cputoslice(getcpuid()) ? \
+#define UALIAS_FLIP_ADDR(_x)   (cputoslice(smp_processor_id()) ? \
                                 (_x) ^ UALIAS_FLIP_BIT : (_x))
 
 #define LBOOT_BASE             (HSPEC_BASE + 0x10000000)
index 7600433..f911580 100644 (file)
 #ifndef _ASM_SGI_SN_AGENT_H
 #define _ASM_SGI_SN_AGENT_H
 
-#include <linux/config.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 //#include <asm/sn/io.h>
index b6f59b2..9edd5e1 100644 (file)
@@ -54,7+54,7 @@ typedef u64   nic_t;
 #define        INVALID_PARTID          (partid_t)-1
 
 extern nasid_t get_nasid(void);
-extern cnodeid_t get_cpu_cnode(int);
+extern cnodeid_t get_cpu_cnode(cpuid_t);
 extern int get_cpu_slice(cpuid_t);
 
 /*
index b0f7a21..4c95ae1 100644 (file)
 #ifndef _ASM_SN_IO_H
 #define _ASM_SN_IO_H
 
-#include <linux/config.h>
 #if !defined(CONFIG_SGI_IO)
 #include <asm/sn/sn0/addrs.h>
 
index 3f042a9..46433db 100644 (file)
  *      that offsets of existing fields do not change.
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
-#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35)
-#include <asm/sn/agent.h>
-#include <asm/arc/types.h>
-#include <asm/arc/hinv.h>
-#endif /* !CONFIG_SGI_IP27 || !CONFIG_SGI_IP35 */
 #if defined(CONFIG_SGI_IP27)
 #include <asm/sn/sn0/addrs.h>
 //#include <sys/SN/router.h>
 // XXX Stolen from <sys/SN/router.h>:
 #define MAX_ROUTER_PORTS (6)    /* Max. number of ports on a router */
 #include <asm/sn/sn0/sn0_fru.h>
+#include <asm/sn/agent.h>
 //#include <sys/graph.h>
+#include <asm/arc/types.h>
+#include <asm/arc/hinv.h>
 //#include <sys/xtalk/xbow.h>
+#if defined(CONFIG_SGI_IO)
+// The hack file has to be before vector and after sn0_fru....
+#include <asm/hack.h>
+#include <asm/sn/vector.h>
+#include <asm/xtalk/xtalk.h>
+#endif  /* CONFIG_SGI_IO */
 #elif defined(CONFIG_SGI_IP35)
+#include <asm/hack.h>
 #include <asm/sn/sn1/addrs.h>
+#include <asm/sn/vector.h>
 #include <sys/sn/router.h>
+#include <asm/sn/agent.h>
 #include <sys/graph.h>
+#include <asm/arc/types.h>
+#include <asm/arc/hinv.h>
 #include <asm/xtalk/xbow.h>
-#endif  /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
-#if (defined(CONFIG_SGI_IP27) && defined(CONFIG_SGI_IO)) || \
-     defined(CONFIG_SGI_IP35)
-// The hack file has to be before vector and after sn0_fru....
-#include <asm/hack.h>
-#include <asm/sn/vector.h>
 #include <asm/xtalk/xtalk.h>
-#endif  /* !(CONFIG_SGI_IP27 && CONFIG_SGI_IO) || !CONFIG_SGI_IP35 */
+#endif  /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
 
 #define KLCFGINFO_MAGIC        0xbeedbabe
 
index 3ca2400..67d6509 100644 (file)
 #ifndef _ASM_SN_KLDIR_H
 #define _ASM_SN_KLDIR_H
 
-#include <linux/config.h>
 #if defined(CONFIG_SGI_IO)
 #include <asm/hack.h>
 #endif
diff --git a/include/asm-mips64/sn/klkernvars.h b/include/asm-mips64/sn/klkernvars.h
new file mode 100644 (file)
index 0000000..cc1b732
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * File ported from IRIX to Linux by Kanoj Sarcar, 06/08/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_KLKERNVARS_H
+#define __ASM_SN_KLKERNVARS_H
+
+#define KV_MAGIC_OFFSET                0x0
+#define KV_RO_NASID_OFFSET     0x4
+#define KV_RW_NASID_OFFSET     0x6
+
+#define KV_MAGIC               0x5f4b565f
+
+#if _LANGUAGE_C
+
+#include <asm/sn/types.h>
+
+typedef struct kern_vars_s {
+       int             kv_magic;
+       nasid_t         kv_ro_nasid;
+       nasid_t         kv_rw_nasid;
+       unsigned long   kv_ro_baseaddr;
+       unsigned long   kv_rw_baseaddr;
+} kern_vars_t;
+
+#endif /* _LANGUAGE_C */
+
+#endif /* __ASM_SN_KLKERNVARS_H */
+
diff --git a/include/asm-mips64/sn/mapped_kernel.h b/include/asm-mips64/sn/mapped_kernel.h
new file mode 100644 (file)
index 0000000..3724b27
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * File created by Kanoj Sarcar 06/06/00.
+ * Copyright 2000 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_MAPPED_KERNEL_H
+#define __ASM_SN_MAPPED_KERNEL_H
+
+/*
+ * Note on how mapped kernels work: the text and data section is 
+ * compiled at cksseg segment (LOADADDR = 0xc001c000), and the 
+ * init/setup/data section gets a 16M virtual address bump in the 
+ * ld.script file (so that tlblo0 and tlblo1 maps the sections). 
+ * The vmlinux.64 section addresses are put in the xkseg range 
+ * using the change-addresses makefile option. Use elfdump -of 
+ * on IRIX to see where the sections go. The Origin loader loads 
+ * the two sections contiguously in physical memory. The loader 
+ * sets the entry point into kernel_entry using a xkphys address, 
+ * but instead of using 0xa800000001160000, it uses the address 
+ * 0xa800000000160000, which is where it physically loaded that 
+ * code. So no jumps can be done before we have switched to using 
+ * cksseg addresses.
+ */
+#include <linux/config.h>
+#include <asm/addrspace.h>
+
+#ifdef CONFIG_MAPPED_KERNEL
+
+#define MAPPED_KERN_RO_TO_PHYS(x)      (x - CKSSEG)
+#define MAPPED_KERN_RW_TO_PHYS(x)      (x - CKSSEG - 16777216)
+
+#else /* CONFIG_MAPPED_KERNEL */
+
+#define MAPPED_KERN_RO_TO_PHYS(x)      (x - CKSEG0)
+#define MAPPED_KERN_RW_TO_PHYS(x)      (x - CKSEG0)
+
+#endif /* CONFIG_MAPPED_KERNEL */
+
+#define MAPPED_KERN_RO_TO_K0(x)        PHYS_TO_K0(MAPPED_KERN_RO_TO_PHYS(x))
+#define MAPPED_KERN_RW_TO_K0(x)        PHYS_TO_K0(MAPPED_KERN_RW_TO_PHYS(x))
+
+#endif __ASM_SN_MAPPED_KERNEL_H
index b1ea725..d2dada9 100644 (file)
@@ -8,7+8,7 @@
 #ifndef __ASM_SN_NMI_H
 #define __ASM_SN_NMI_H
 
-#ident "$Revision: 1.1 $"
+#ident "$Revision: 1.2 $"
 
 #include <asm/sn/addrs.h>
 
index 206c043..cac1939 100644 (file)
 
 /* Sanity hazzard ...  Below all the Origin hacks are following.  */
 
-#define SCSI0_INT              0
-#define SCSI1_INT              1
-#define CPU_RESCHED_A_IRQ      3
-#define CPU_RESCHED_B_IRQ      4
-#define QLOGICFC_SLOT5          5
-#define CPU_CALL_A_IRQ         6
-#define CPU_CALL_B_IRQ         7
-#define IOC3_SERIAL_INT                8
-/*#define IOC3_ETH_INT         9*/
-#define IOC3_ETH_INT           0x0809  /* nasid 0, wid 0x8 */
+#define CPU_RESCHED_A_IRQ      0
+#define CPU_RESCHED_B_IRQ      1
+#define CPU_CALL_A_IRQ         2
+#define CPU_CALL_B_IRQ         3
+#define IOC3_ETH_INT           4
+#define BASE_PCI_IRQ           4
 
 #define SN00_BRIDGE            0x9200000008000000
 #define SN00I_BRIDGE0          0x920000000b000000
index 08d31c9..2715ce5 100644 (file)
@@ -1,6+1,11 @@
+extern nasid_t master_nasid;
+
 extern cnodeid_t get_compact_nodeid(void);
 extern void hub_rtc_init(cnodeid_t);
 extern void cpu_time_init(void);
 extern void per_cpu_init(void);
-extern void install_cpuintr(cpuid_t cpu);
-extern void install_tlbintr(cpuid_t cpu);
+extern void install_cpuintr(int cpu);
+extern void install_tlbintr(int cpu);
+extern void setup_replication_mask(int);
+extern void replicate_kernel_text(int);
+extern pfn_t node_getfirstfree(cnodeid_t);
index c3905ad..40aced5 100644 (file)
@@ -21,6+21,7 @@ typedef signed char   partid_t;       /* partition ID type */
 typedef signed short   moduleid_t;     /* user-visible module number type */
 typedef signed short   cmoduleid_t;    /* kernel compact module id type */
 typedef unsigned char  clusterid_t;    /* Clusterid of the cell */
+typedef unsigned long  pfn_t;
 
 typedef dev_t          vertex_hdl_t;   /* hardware graph vertex handle */
 
index b9098ca..c9e7b4d 100644 (file)
@@ -62,6+62,8 @@ To add: #define SO_REUSEPORT 0x0200   /* Allow local address and port reuse.  */
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 8fdcd95..e84dcb7 100644 (file)
@@ -3,7+3,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1999 Ralf Baechle
+ * Copyright (C) 1995, 1999, 2000 Ralf Baechle
+ * Copyright (C) 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_STAT_H
 #define _ASM_STAT_H
@@ -54,35+55,30 @@ struct stat32 {
        unsigned int        st_gen;
 };
 
+/* The memory layout is the same as of struct stat64 of the 32-bit kernel.  */
 struct stat {
        dev_t           st_dev;
-       long            st_pad1[3];             /* Reserved for network id */
+       unsigned int    st_pad0[3];     /* Reserved for st_dev expansion  */
        ino_t           st_ino;
        mode_t          st_mode;
        nlink_t         st_nlink;
        uid_t           st_uid;
        gid_t           st_gid;
        dev_t           st_rdev;
-       long            st_pad2[2];
+       unsigned int    st_pad1[3];     /* Reserved for st_rdev expansion  */
        off_t           st_size;
-       long            st_pad3;
        /*
         * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
         * but we don't have it under Linux.
         */
        time_t          st_atime;
-       long            reserved0;
+       unsigned int    reserved0;      /* Reserved for st_atime expansion  */
        time_t          st_mtime;
-       long            reserved1;
+       unsigned int    reserved1;      /* Reserved for st_atime expansion  */
        time_t          st_ctime;
-       long            reserved2;
-       long            st_blksize;
-       long            st_blocks;
-       char            st_fstype[16];  /* Filesystem type name */
-       long            st_pad4[8];
-       /* Linux specific fields */
-       unsigned int    st_flags;
-       unsigned int    st_gen;
+       unsigned int    reserved2;      /* Reserved for st_atime expansion  */
+       unsigned int    st_blksize;
+       unsigned long   st_blocks;
 };
 
 #endif /* _ASM_STAT_H */
index 887b08e..2a9f2ee 100644 (file)
-/* $Id: uaccess.h,v 1.4 2000/02/19 00:33:10 ralf Exp $
- *
+/*
  * 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) 1996, 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
@@ -70,16+69,20 @@ extern inline int verify_area(int type, const void * addr, unsigned long size)
  * (a) re-use the arguments for side effects (sizeof is ok)
  * (b) require any knowledge of processes at this stage
  */
-#define put_user(x,ptr)        __put_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
-#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define put_user(x,ptr)        \
+       __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) \
+       __get_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /*
  * The "__xxx" versions do not do address space checking, useful when
  * doing multiple accesses to the same area (the user has to do the
  * checks by hand with "access_ok()")
  */
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
-#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) \
+       __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) \
+       __get_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 /*
  * The "xxx_ret" versions return constant specified in third argument, if
@@ -87,17+90,11 @@ extern inline int verify_area(int type, const void * addr, unsigned long size)
  * case of just returning from the function xxx_ret is used.
  */
 
-#define put_user_ret(x,ptr,ret) ({ \
-if (put_user(x,ptr)) return ret; })
-
-#define get_user_ret(x,ptr,ret) ({ \
-if (get_user(x,ptr)) return ret; })
-
-#define __put_user_ret(x,ptr,ret) ({ \
-if (__put_user(x,ptr)) return ret; })
+#define put_user_ret(x,ptr,ret) ({ if (put_user(x,ptr)) return ret; })
+#define get_user_ret(x,ptr,ret) ({ if (get_user(x,ptr)) return ret; })
 
-#define __get_user_ret(x,ptr,ret) ({ \
-if (__get_user(x,ptr)) return ret; })
+#define __put_user_ret(x,ptr,ret) ({ if (__put_user(x,ptr)) return ret; })
+#define __get_user_ret(x,ptr,ret) ({ if (__get_user(x,ptr)) return ret; })
 
 struct __large_struct { unsigned long buf[100]; };
 #define __m(x) (*(struct __large_struct *)(x))
@@ -117,14+114,14 @@ case 8:  __get_user_asm("ld"); break; \
 default: __get_user_unknown(); break; \
 } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
 
-#define __get_user_check(x,ptr,size,mask) ({ \
+#define __get_user_check(x,ptr,size) ({ \
 long __gu_err; \
 __typeof__(*(ptr)) __gu_val; \
 long __gu_addr; \
 __asm__("":"=r" (__gu_val)); \
 __gu_addr = (long) (ptr); \
 __asm__("":"=r" (__gu_err)); \
-if (__access_ok(__gu_addr,size,mask)) { \
+if (__access_ok(__gu_addr,size,__access_mask)) { \
 switch (size) { \
 case 1: __get_user_asm("lb"); break; \
 case 2: __get_user_asm("lh"); break; \
@@ -167,14+164,14 @@ case 8: __put_user_asm("sd"); break; \
 default: __put_user_unknown(); break; \
 } __pu_err; })
 
-#define __put_user_check(x,ptr,size,mask) ({ \
+#define __put_user_check(x,ptr,size) ({ \
 long __pu_err; \
 __typeof__(*(ptr)) __pu_val; \
 long __pu_addr; \
 __pu_val = (x); \
 __pu_addr = (long) (ptr); \
 __asm__("":"=r" (__pu_err)); \
-if (__access_ok(__pu_addr,size,mask)) { \
+if (__access_ok(__pu_addr,size,__access_mask)) { \
 switch (size) { \
 case 1: __put_user_asm("sb"); break; \
 case 2: __put_user_asm("sh"); break; \
index c6c1899..40b648d 100644 (file)
 #define SO_DETACH_FILTER       27
 
 #define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index 703a7bd..0d00c3b 100644 (file)
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
-#define SO_PEERNAME            28
+#define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index ebcb6a3..6bba730 100644 (file)
 #define SO_DETACH_FILTER        27
 
 #define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
index cbcebff..256f5c1 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: socket.h,v 1.14 2000/06/09 07:35:28 davem Exp $ */
+/* $Id: socket.h,v 1.15 2000/07/08 00:20:43 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
 #define SO_DETACH_FILTER        0x001b
 
 #define SO_PEERNAME            0x001c
+#define SO_TIMESTAMP           0x001d
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
index 387ee17..e28c54a 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: socket.h,v 1.7 2000/06/09 07:35:28 davem Exp $ */
+/* $Id: socket.h,v 1.8 2000/07/08 00:20:43 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
 #define SO_DETACH_FILTER        0x001b
 
 #define SO_PEERNAME            0x001c
+#define SO_TIMESTAMP           0x001d
+#define SCM_TIMESTAMP          SO_TIMESTAMP
 
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
diff --git a/include/linux/dmascc.h b/include/linux/dmascc.h
deleted file mode 100644 (file)
index 01b46df..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * $Id: dmascc.h,v 1.1 1997/12/01 10:44:55 oe1kib Exp $
- *
- * Driver for high-speed SCC boards (those with DMA support)
- * Copyright (C) 1997 Klaus Kudielka
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/* Ioctls */
-#define SIOCGSCCPARAM SIOCDEVPRIVATE
-#define SIOCSSCCPARAM (SIOCDEVPRIVATE+1)
-
-/* Frequency of timer 0 */
-#define TMR_0_HZ      25600
-
-/* Configurable parameters */
-struct scc_param {
-  int pclk_hz;  /* frequency of BRG input (read-only - don't change) */
-  int brg_tc;   /* baud rate generator terminal count - BRG disabled if < 0 */
-  int nrzi;     /* 0 (nrz), 1 (nrzi) */
-  int clocks;   /* see documentation */
-  int txdelay;  /* [1/TMR_0_HZ] */
-  int txtime;   /* [1/HZ] */
-  int sqdelay;  /* [1/TMR_0_HZ] */
-  int waittime; /* [1/TMR_0_HZ] */
-  int slottime; /* [1/TMR_0_HZ] */
-  int persist;  /* 0 ... 255 */
-  int dma;      /* 1, 3 */
-};
-
index 13eed62..fdae6ab 100644 (file)
@@ -138,7+138,7 @@ struct in6_flowlabel_req
  */
 #define IPV6_TLV_PAD0          0
 #define IPV6_TLV_PADN          1
-#define IPV6_TLV_ROUTERALERT   20
+#define IPV6_TLV_ROUTERALERT   5
 #define IPV6_TLV_JUMBO         194
 
 /*
index 5ccee05..04ae938 100644 (file)
 
 #define PCI_VENDOR_ID_NEC              0x1033
 #define PCI_DEVICE_ID_NEC_PCX2         0x0046
+#define PCI_DEVICE_ID_NEC_NILE4                0x005a
 
 #define PCI_VENDOR_ID_FD               0x1036
 #define PCI_DEVICE_ID_FD_36C70         0x0000
index 073355b..5316f0c 100644 (file)
@@ -259,7+259,6 @@ struct task_struct {
        struct exec_domain *exec_domain;
        volatile long need_resched;
 
-       cycles_t avg_slice;
        int lock_depth;         /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */  
 /* begin intel cache line */
        long counter;
@@ -267,8+266,8 @@ struct task_struct {
        unsigned long policy;
 /* memory management info */
        struct mm_struct *mm, *active_mm;
-       int has_cpu;
-       int processor;
+       int has_cpu, processor;
+       unsigned long cpus_allowed;
        unsigned long ptrace;
        struct list_head run_list;
        struct task_struct *next_task, *prev_task;
@@ -399,6+398,7 @@ struct task_struct {
     policy:            SCHED_OTHER,                                    \
     mm:                        NULL,                                           \
     active_mm:         &init_mm,                                       \
+    cpus_allowed:      -1,                                             \
     run_list:          LIST_HEAD_INIT(tsk.run_list),                   \
     next_task:         &tsk,                                           \
     prev_task:         &tsk,                                           \
index 71f8772..850837a 100644 (file)
@@ -148,16+148,8 @@ struct sk_buff {
 #endif
 };
 
-/* These are just the default values. This is run time configurable.
- * FIXME: Probably the config option should go away. -- erics
- */
-#ifdef CONFIG_SKB_LARGE
 #define SK_WMEM_MAX    65535
 #define SK_RMEM_MAX    65535
-#else
-#define SK_WMEM_MAX    32767
-#define SK_RMEM_MAX    32767
-#endif
 
 #ifdef __KERNEL__
 /*
index 1e9626a..bb5bebd 100644 (file)
@@ -108,7+108,12 @@ extern struct screen_info screen_info;
 #define VIDEO_TYPE_EGAM                0x20    /* EGA/VGA in Monochrome Mode   */
 #define VIDEO_TYPE_EGAC                0x21    /* EGA in Color Mode            */
 #define VIDEO_TYPE_VGAC                0x22    /* VGA+ in Color Mode           */
-#define VIDEO_TYPE_VLFB                0x23    /* VESA VGA in graphic mode     */
+#define VIDEO_TYPE_VLFB                0x23    /* VESA VGA in graphic mode     */
+
+#define VIDEO_TYPE_PICA_S3     0x30    /* ACER PICA-61 local S3 video  */
+#define VIDEO_TYPE_MIPS_G364   0x31    /* MIPS Magnum 4000 G364 video  */
+#define VIDEO_TYPE_SNI_RM      0x32    /* SNI RM200 PCI video          */
+#define VIDEO_TYPE_SGI          0x33    /* Various SGI graphics hardware */
 
 #define VIDEO_TYPE_TGAC                0x40    /* DEC TGA */
 
@@ -117,9+122,6 @@ extern struct screen_info screen_info;
 
 #define VIDEO_TYPE_PMAC                0x60    /* PowerMacintosh frame buffer. */
 
-#define VIDEO_TYPE_SGI          0x70    /* Various SGI graphics hardware */
-#define VIDEO_TYPE_MIPS_G364   0x71    /* MIPS Magnum 4000 G364 video  */
-
 /*
  * This character is the same as _POSIX_VDISABLE: it cannot be used as
  * a c_cc[] character, but indicates that a particular special character
index de32869..6793f19 100644 (file)
@@ -124,5+124,10 @@ static __inline__ unsigned int csum_and_copy_to_user
 }
 #endif
 
+static inline unsigned int csum_chain(unsigned int csum, unsigned int addend)
+{
+       csum += addend;
+       return csum + (csum < addend);
+}
 
 #endif
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
new file mode 100644 (file)
index 0000000..2ddf767
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef _INET_ECN_H_
+#define _INET_ECN_H_
+
+#include <linux/config.h>
+
+#ifdef CONFIG_INET_ECN
+
+static inline int INET_ECN_is_ce(__u8 dsfield)
+{
+       return (dsfield&3) == 3;
+}
+
+static inline int INET_ECN_is_not_ce(__u8 dsfield)
+{
+       return (dsfield&3) == 2;
+}
+
+static inline int INET_ECN_is_capable(__u8 dsfield)
+{
+       return (dsfield&2);
+}
+
+static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
+{
+       outer &= ~3;
+       if (INET_ECN_is_capable(inner))
+               outer |= (inner & 3);
+       return outer;
+}
+
+#define        INET_ECN_xmit(sk) do { (sk)->protinfo.af_inet.tos |= 2; } while (0)
+#define        INET_ECN_dontxmit(sk) do { (sk)->protinfo.af_inet.tos &= ~3; } while (0)
+
+#define IP6_ECN_flow_init(label) do {  \
+      (label) &= ~htonl(3<<20);                \
+    } while (0)
+
+#define        IP6_ECN_flow_xmit(sk, label) do {                       \
+       if (INET_ECN_is_capable((sk)->protinfo.af_inet.tos))    \
+               (label) |= __constant_htons(2 << 4);            \
+    } while (0)
+
+
+#else
+#define INET_ECN_is_ce(x...)           (0)
+#define INET_ECN_is_not_ce(x...)       (0)
+#define INET_ECN_is_capable(x...)      (0)
+#define INET_ECN_encapsulate(x, y)     (x)
+#define IP6_ECN_flow_init(x...)                do { } while (0)
+#define        IP6_ECN_flow_xmit(x...)         do { } while (0)
+#define        INET_ECN_xmit(x...)             do { } while (0)
+#define        INET_ECN_dontxmit(x...)         do { } while (0)
+#endif
+
+static inline void IP_ECN_set_ce(struct iphdr *iph)
+{
+       u32 check = iph->check;
+       check += __constant_htons(0xFFFE);
+       iph->check = check + (check>=0xFFFF);
+       iph->tos |= 1;
+}
+
+struct ipv6hdr;
+
+static inline void IP6_ECN_set_ce(struct ipv6hdr *iph)
+{
+       *(u32*)iph |= htonl(1<<20);
+}
+
+#define ip6_get_dsfield(iph) ((ntohs(*(u16*)(iph)) >> 4) & 0xFF)
+
+#endif
index f3ab5ac..45a85ab 100644 (file)
@@ -167,12+167,14 @@ extern __inline__ int ip_send(struct sk_buff *skb)
                return ip_finish_output(skb);
 }
 
+/* The function in 2.2 was invalid, producing wrong result for
+ * check=0xFEFF. It was noticed by Arthur Skawina _year_ ago. --ANK(000625) */
 extern __inline__
 int ip_decrease_ttl(struct iphdr *iph)
 {
        u32 check = iph->check;
        check += __constant_htons(0x0100);
-       iph->check = check + (check>>16);
+       iph->check = check + (check>=0xFFFF);
        return --iph->ttl;
 }
 
@@ -220,6+222,8 @@ extern int  ip_call_ra_chain(struct sk_buff *skb);
  */
  
 struct sk_buff *ip_defrag(struct sk_buff *skb);
+extern int ip_frag_nqueues;
+extern atomic_t ip_frag_mem;
 
 /*
  *     Functions provided by ip_forward.c
index aef0d26..235ae40 100644 (file)
@@ -4,7+4,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: ipv6.h,v 1.20 2000/02/27 19:51:38 davem Exp $
+ *     $Id: ipv6.h,v 1.21 2000/07/07 22:29:42 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -189,6+189,9 @@ extern u8 *                 ipv6_parse_exthdrs(struct sk_buff **skb, u8 *nhptr);
 
 extern struct ipv6_txoptions *  ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
 
+extern int ip6_frag_nqueues;
+extern atomic_t ip6_frag_mem;
+
 #define IPV6_FRAG_TIMEOUT      (60*HZ)         /* 60 seconds */
 
 /*
index b633988..c849070 100644 (file)
@@ -259,6+259,19 @@ __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev
        if (n || !creat)
                return n;
 
+       n = neigh_create(tbl, pkey, dev);
+       return IS_ERR(n) ? NULL : n;
+}
+
+extern __inline__ struct neighbour *
+__neigh_lookup_errno(struct neigh_table *tbl, const void *pkey,
+  struct net_device *dev)
+{
+       struct neighbour *n = neigh_lookup(tbl, pkey, dev);
+
+       if (n)
+               return n;
+
        return neigh_create(tbl, pkey, dev);
 }
 
index 180daad..20536ca 100644 (file)
@@ -118,6+118,13 @@ extern __inline__ void ip_rt_put(struct rtable * rt)
                dst_release(&rt->u.dst);
 }
 
+#ifdef CONFIG_INET_ECN
+#define IPTOS_RT_MASK  (IPTOS_TOS_MASK & ~3)
+#else
+#define IPTOS_RT_MASK  IPTOS_TOS_MASK
+#endif
+
+
 extern __u8 ip_tos2prio[16];
 
 extern __inline__ char rt_tos2priority(u8 tos)
index c0451c1..60756db 100644 (file)
@@ -515,6+515,8 @@ struct sock {
                                broadcast,
                                bsdism;
        unsigned char           debug;
+       unsigned char           rcvtstamp;
+       unsigned char           userlocks;
        int                     proc;
        unsigned long           lingertime;
 
@@ -1222,7+1224,7 @@ extern __inline__ long sock_sndtimeo(struct sock *sk, int noblock)
 
 extern __inline__ int sock_rcvlowat(struct sock *sk, int waitall, int len)
 {
-       return waitall ? len : min(sk->rcvlowat, len);
+       return (waitall ? len : min(sk->rcvlowat, len)) ? : 1;
 }
 
 /* Alas, with timeout socket operations are not restartable.
@@ -1233,6+1235,15 @@ extern __inline__ int sock_intr_errno(long timeo)
        return timeo == MAX_SCHEDULE_TIMEOUT ? -ERESTARTSYS : -EINTR;
 }
 
+static __inline__ void
+sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
+{
+       if (sk->rcvtstamp)
+               put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP, sizeof(skb->stamp), &skb->stamp);
+       else
+               sk->stamp = skb->stamp;
+}
+
 /* 
  *     Enable debug/info messages 
  */
index 518a86f..b99440b 100644 (file)
@@ -133,6+133,7 @@ EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(get_super);
 EXPORT_SYMBOL(get_empty_super);
 EXPORT_SYMBOL(getname);
+EXPORT_SYMBOL(names_cachep);
 EXPORT_SYMBOL(_fput);
 EXPORT_SYMBOL(igrab);
 EXPORT_SYMBOL(iunique);
index 3b007e5..dd055d9 100644 (file)
@@ -78,18+78,20 @@ static union {
 } aligned_data [NR_CPUS] __cacheline_aligned = { {{&init_task,0}}};
 
 #define cpu_curr(cpu) aligned_data[(cpu)].schedule_data.curr
+#define last_schedule(cpu) aligned_data[(cpu)].schedule_data.last_schedule
 
 struct kernel_stat kstat = { 0 };
 
 #ifdef CONFIG_SMP
 
 #define idle_task(cpu) (init_tasks[cpu_number_map(cpu)])
-#define can_schedule(p)        (!(p)->has_cpu)
+#define can_schedule(p,cpu) ((!(p)->has_cpu) && \
+                               ((p)->cpus_allowed & (1 << cpu)))
 
 #else
 
 #define idle_task(cpu) (&init_task)
-#define can_schedule(p) (1)
+#define can_schedule(p,cpu) (1)
 
 #endif
 
@@ -119,7+121,7 @@ static inline int goodness(struct task_struct * p, int this_cpu, struct mm_struc
         * into account).
         */
        if (p->policy != SCHED_OTHER) {
-               weight = 1000 + p->rt_priority;
+               weight = 1000 + 2*DEF_PRIORITY + p->rt_priority;
                goto out;
        }
 
@@ -183,87+185,108 @@ static inline int preemption_goodness(struct task_struct * prev, struct task_str
  * up unlocking it early, so the caller must not unlock the
  * runqueue, it's always done by reschedule_idle().
  */
-static inline void reschedule_idle(struct task_struct * p, unsigned long flags)
+static void reschedule_idle(struct task_struct * p, unsigned long flags)
 {
 #ifdef CONFIG_SMP
-       int this_cpu = smp_processor_id(), target_cpu;
-       struct task_struct *tsk;
-       int cpu, best_cpu, i;
+       int this_cpu = smp_processor_id();
+       struct task_struct *tsk, *target_tsk;
+       int cpu, best_cpu, i, max_prio;
+       cycles_t oldest_idle;
 
        /*
         * shortcut if the woken up task's last CPU is
         * idle now.
         */
        best_cpu = p->processor;
-       tsk = idle_task(best_cpu);
-       if (cpu_curr(best_cpu) == tsk)
-               goto send_now;
+       if (can_schedule(p, best_cpu)) {
+               tsk = idle_task(best_cpu);
+               if (cpu_curr(best_cpu) == tsk)
+                       goto send_now_idle;
+
+               /*
+                * Maybe this process has enough priority to preempt
+                * its preferred CPU. (this is a shortcut):
+                */
+               tsk = cpu_curr(best_cpu);
+               if (preemption_goodness(tsk, p, best_cpu) > 1)
+                       goto preempt_now;
+       }
 
        /*
         * We know that the preferred CPU has a cache-affine current
         * process, lets try to find a new idle CPU for the woken-up
-        * process:
+        * process. Select the least recently active idle CPU. (that
+        * one will have the least active cache context.) Also find
+        * the executing process which has the least priority.
         */
-       for (i = smp_num_cpus - 1; i >= 0; i--) {
+       oldest_idle = -1ULL;
+       target_tsk = NULL;
+       max_prio = 1;
+
+       for (i = 0; i < smp_num_cpus; i++) {
                cpu = cpu_logical_map(i);
-               if (cpu == best_cpu)
+               if (!can_schedule(p, cpu))
                        continue;
                tsk = cpu_curr(cpu);
                /*
-                * We use the last available idle CPU. This creates
+                * We use the first available idle CPU. This creates
                 * a priority list between idle CPUs, but this is not
                 * a problem.
                 */
-               if (tsk == idle_task(cpu))
-                       goto send_now;
-       }
-
-       /*
-        * No CPU is idle, but maybe this process has enough priority
-        * to preempt it's preferred CPU.
-        */
-       tsk = cpu_curr(best_cpu);
-       if (preemption_goodness(tsk, p, best_cpu) > 0)
-               goto send_now;
+               if (tsk == idle_task(cpu)) {
+                       if (last_schedule(cpu) < oldest_idle) {
+                               oldest_idle = last_schedule(cpu);
+                               target_tsk = tsk;
+                       }
+               } else {
+                       if (oldest_idle == -1ULL) {
+                               int prio = preemption_goodness(tsk, p, cpu);
 
-       /*
-        * We will get here often - or in the high CPU contention
-        * case. No CPU is idle and this process is either lowprio or
-        * the preferred CPU is highprio. Try to preempt some other CPU
-        * only if it's RT or if it's iteractive and the preferred
-        * cpu won't reschedule shortly.
-        */
-       if (p->avg_slice < cacheflush_time || (p->policy & ~SCHED_YIELD) != SCHED_OTHER) {
-               for (i = smp_num_cpus - 1; i >= 0; i--) {
-                       cpu = cpu_logical_map(i);
-                       if (cpu == best_cpu)
-                               continue;
-                       tsk = cpu_curr(cpu);
-                       if (preemption_goodness(tsk, p, cpu) > 0)
-                               goto send_now;
+                               if (prio > max_prio) {
+                                       max_prio = prio;
+                                       target_tsk = tsk;
+                               }
+                       }
                }
        }
+       tsk = target_tsk;
+       if (tsk) {
+               if (oldest_idle != -1ULL)
+                       goto send_now_idle;
+               goto preempt_now;
+       }
 
        spin_unlock_irqrestore(&runqueue_lock, flags);
        return;
                
-send_now:
-       target_cpu = tsk->processor;
+send_now_idle:
+       /*
+        * If need_resched == -1 then we can skip sending the IPI
+        * altogether, tsk->need_resched is actively watched by the
+        * idle thread.
+        */
+       if (!tsk->need_resched)
+               smp_send_reschedule(tsk->processor);
+       tsk->need_resched = 1;
+       spin_unlock_irqrestore(&runqueue_lock, flags);
+       return;
+
+preempt_now:
        tsk->need_resched = 1;
        spin_unlock_irqrestore(&runqueue_lock, flags);
        /*
         * the APIC stuff can go outside of the lock because
         * it uses no task information, only CPU#.
         */
-       if (target_cpu != this_cpu)
-               smp_send_reschedule(target_cpu);
+       if (tsk->processor != this_cpu)
+               smp_send_reschedule(tsk->processor);
        return;
 #else /* UP */
        int this_cpu = smp_processor_id();
        struct task_struct *tsk;
 
        tsk = cpu_curr(this_cpu);
-       if (preemption_goodness(tsk, p, this_cpu) > 0)
+       if (preemption_goodness(tsk, p, this_cpu) > 1)
                tsk->need_resched = 1;
        spin_unlock_irqrestore(&runqueue_lock, flags);
 #endif
@@ -413,10+436,12 @@ static inline void __schedule_tail(struct task_struct *prev)
                unsigned long flags;
 
                spin_lock_irqsave(&runqueue_lock, flags);
+               prev->has_cpu = 0;
                reschedule_idle(prev, flags); // spin_unlocks runqueue
+       } else {
+               wmb();
+               prev->has_cpu = 0;
        }
-       wmb();
-       prev->has_cpu = 0;
 #endif /* CONFIG_SMP */
 }
 
@@ -501,7+526,7 @@ repeat_schedule:
 still_running_back:
        list_for_each(tmp, &runqueue_head) {
                p = list_entry(tmp, struct task_struct, run_list);
-               if (can_schedule(p)) {
+               if (can_schedule(p, this_cpu)) {
                        int weight = goodness(p, this_cpu, prev->active_mm);
                        if (weight > c)
                                c = weight, next = p;
@@ -540,13+565,6 @@ still_running_back:
                t = get_cycles();
                this_slice = t - sched_data->last_schedule;
                sched_data->last_schedule = t;
-
-               /*
-                * Exponentially fading average calculation, with
-                * some weight so it doesnt get fooled easily by
-                * smaller irregularities.
-                */
-               prev->avg_slice = (this_slice*1 + prev->avg_slice*1)/2;
        }
 
        /*
@@ -641,15+659,20 @@ scheduling_in_interrupt:
        return;
 }
 
-static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, const int sync)
+static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
+                                               const int sync)
 {
        struct list_head *tmp, *head;
-       struct task_struct *p;
+       struct task_struct *p, *best_exclusive;
        unsigned long flags;
+       int best_cpu, irq;
 
         if (!q)
                goto out;
 
+       best_cpu = smp_processor_id();
+       irq = in_interrupt();
+       best_exclusive = NULL;
        wq_write_lock_irqsave(&q->lock, flags);
 
 #if WAITQUEUE_DEBUG
@@ -661,10+684,13 @@ static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, con
         if (!head->next || !head->prev)
                 WQ_BUG();
 #endif
-       list_for_each(tmp, head) {
+       tmp = head->next;
+       while (tmp != head) {
                unsigned int state;
                 wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
 
+               tmp = tmp->next;
+
 #if WAITQUEUE_DEBUG
                CHECK_MAGIC(curr->__magic);
 #endif
@@ -674,15+700,37 @@ static inline void __wake_up_common(wait_queue_head_t *q, unsigned int mode, con
 #if WAITQUEUE_DEBUG
                        curr->__waker = (long)__builtin_return_address(0);
 #endif
-                       if (sync)
-                               wake_up_process_synchronous(p);
-                       else
-                               wake_up_process(p);
-                       if (state & mode & TASK_EXCLUSIVE)
-                               break;
+                       /*
+                        * If waking up from an interrupt context then
+                        * prefer processes which are affine to this
+                        * CPU.
+                        */
+                       if (irq && (state & mode & TASK_EXCLUSIVE)) {
+                               if (!best_exclusive)
+                                       best_exclusive = p;
+                               else if ((p->processor == best_cpu) &&
+                                       (best_exclusive->processor != best_cpu))
+                                               best_exclusive = p;
+                       } else {
+                               if (sync)
+                                       wake_up_process_synchronous(p);
+                               else
+                                       wake_up_process(p);
+                               if (state & mode & TASK_EXCLUSIVE)
+                                       break;
+                       }
                }
        }
+       if (best_exclusive)
+               best_exclusive->state = TASK_RUNNING;
        wq_write_unlock_irqrestore(&q->lock, flags);
+
+       if (best_exclusive) {
+               if (sync)
+                       wake_up_process_synchronous(best_exclusive);
+               else
+                       wake_up_process(best_exclusive);
+       }
 out:
        return;
 }
@@ -697,6+745,7 @@ void __wake_up_sync(wait_queue_head_t *q, unsigned int mode)
        __wake_up_common(q, mode, 1);
 }
 
+
 #define        SLEEP_ON_VAR                            \
        unsigned long flags;                    \
        wait_queue_t wait;                      \
@@ -798,7+847,7 @@ asmlinkage long sys_nice(int increment)
         * timeslice instead (default 200 ms). The rounding is
         * why we want to avoid negative values.
         */
-       newprio = (newprio * DEF_PRIORITY + 10) / 20;
+       newprio = (newprio * DEF_PRIORITY + 10)/20;
        increment = newprio;
        if (increase)
                increment = -increment;
@@ -812,7+861,7 @@ asmlinkage long sys_nice(int increment)
         */
        newprio = current->priority - increment;
        if ((signed) newprio < 1)
-               newprio = 1;
+               newprio = DEF_PRIORITY/20;
        if (newprio > DEF_PRIORITY*2)
                newprio = DEF_PRIORITY*2;
        current->priority = newprio;
index 207b9ec..a24e465 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -355,7+355,6 @@ static kmem_cache_t cache_cache = {
        spinlock:       SPIN_LOCK_UNLOCKED,
        colour_off:     L1_CACHE_BYTES,
        name:           "kmem_cache",
-       next:           LIST_HEAD_INIT(cache_cache.next)
 };
 
 /* Guard access to the cache-chain. */
@@ -412,7+411,7 @@ void __init kmem_cache_init(void)
        size_t left_over;
 
        init_MUTEX(&cache_chain_sem);
-       list_add(&cache_cache.next,&cache_chain);
+       INIT_LIST_HEAD(&cache_chain);
 
        kmem_cache_estimate(0, cache_cache.objsize, 0,
                        &left_over, &cache_cache.num);
@@ -443,7+442,7 @@ void __init kmem_cache_sizes_init(void)
                 * eliminates "false sharing".
                 * Note for systems short on memory removing the alignment will
                 * allow tighter packing of the smaller caches. */
-               sprintf(name,"size-%d",sizes->cs_size);
+               sprintf(name,"size-%Zd",sizes->cs_size);
                if (!(sizes->cs_cachep =
                        kmem_cache_create(name, sizes->cs_size,
                                        0, SLAB_HWCACHE_ALIGN, NULL, NULL))) {
@@ -455,7+454,7 @@ void __init kmem_cache_sizes_init(void)
                        offslab_limit = sizes->cs_size-sizeof(slab_t);
                        offslab_limit /= 2;
                }
-               sprintf(name, "size-%d(DMA)",sizes->cs_size);
+               sprintf(name, "size-%Zd(DMA)",sizes->cs_size);
                sizes->cs_dmacachep = kmem_cache_create(name, sizes->cs_size, 0,
                              SLAB_CACHE_DMA|SLAB_HWCACHE_ALIGN, NULL, NULL);
                if (!sizes->cs_dmacachep)
index 88322c8..b0d9895 100644 (file)
@@ -281,25+281,27 @@ struct neighbour * neigh_create(struct neigh_table *tbl, const void *pkey,
        struct neighbour *n, *n1;
        u32 hash_val;
        int key_len = tbl->key_len;
+       int error;
 
        n = neigh_alloc(tbl);
        if (n == NULL)
-               return NULL;
+               return ERR_PTR(-ENOBUFS);
 
        memcpy(n->primary_key, pkey, key_len);
        n->dev = dev;
        dev_hold(dev);
 
        /* Protocol specific setup. */
-       if (tbl->constructor && tbl->constructor(n) < 0) {
+       if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
                neigh_release(n);
-               return NULL;
+               return ERR_PTR(error);
        }
 
        /* Device specific setup. */
-       if (n->parms && n->parms->neigh_setup && n->parms->neigh_setup(n) < 0) {
+       if (n->parms && n->parms->neigh_setup &&
+           (error = n->parms->neigh_setup(n)) < 0) {
                neigh_release(n);
-               return NULL;
+               return ERR_PTR(error);
        }
 
        n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
@@ -1242,6+1244,7 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                if (nda[NDA_LLADDR-1] != NULL &&
                    nda[NDA_LLADDR-1]->rta_len != RTA_LENGTH(dev->addr_len))
                        goto out;
+               err = 0;
                n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
                if (n) {
                        if (nlh->nlmsg_flags&NLM_F_EXCL)
@@ -1249,9+1252,11 @@ int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
                } else if (!(nlh->nlmsg_flags&NLM_F_CREATE))
                        err = -ENOENT;
                else {
-                       n = __neigh_lookup(tbl, RTA_DATA(nda[NDA_DST-1]), dev, 1);
-                       if (n == NULL)
-                               err = -ENOBUFS;
+                       n = __neigh_lookup_errno(tbl, RTA_DATA(nda[NDA_DST-1]), dev);
+                       if (IS_ERR(n)) {
+                               err = PTR_ERR(n);
+                               n = NULL;
+                       }
                }
                if (err == 0) {
                        err = neigh_update(n, nda[NDA_LLADDR-1] ? RTA_DATA(nda[NDA_LLADDR-1]) : NULL,
index 4044a7f..fcb6246 100644 (file)
@@ -7,7+7,7 @@
  *             handler for protocols to use and generic option handler.
  *
  *
- * Version:    $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $
+ * Version:    $Id: sock.c,v 1.95 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -308,6+308,10 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                        sock->passcred = valbool;
                        break;
 
+               case SO_TIMESTAMP:
+                       sk->rcvtstamp = valbool;
+                       break;
+
                case SO_RCVLOWAT:
                        if (val < 0)
                                val = INT_MAX;
@@ -485,7+489,11 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                case SO_BSDCOMPAT:
                        v.val = sk->bsdism;
                        break;
-                       
+
+               case SO_TIMESTAMP:
+                       v.val = sk->rcvtstamp;
+                       break;
+
                case SO_RCVTIMEO:
                        lv=sizeof(struct timeval);
                        if (sk->rcvtimeo == MAX_SCHEDULE_TIMEOUT) {
@@ -599,7+607,16 @@ void __init sk_init(void)
 {
        sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
                                      SLAB_HWCACHE_ALIGN, 0, 0);
-
+       
+       if (num_physpages <= 4096) {
+               sysctl_wmem_max = 32767;
+               sysctl_rmem_max = 32767;
+               sysctl_wmem_default = 32767;
+               sysctl_wmem_default = 32767;
+       } else if (num_physpages >= 131072) {
+               sysctl_wmem_max = 131071;
+               sysctl_rmem_max = 131071;
+       }
 }
 
 /*
index 5ce55eb..d97558a 100644 (file)
@@ -789,13+789,14 @@ static int dn_route_input_slow(struct sk_buff *skb)
        if (dn_db->router && ((neigh = neigh_clone(dn_db->router)) != NULL))
                goto add_entry;
 
-       if ((neigh = neigh_create(&dn_neigh_table, &cb->src, dev)) != NULL) {
+       neigh = neigh_create(&dn_neigh_table, &cb->src, dev);
+       if (!IS_ERR(neigh)) {
                if (dev->type == ARPHRD_ETHER)
                        memcpy(neigh->ha, skb->mac.ethernet->h_source, ETH_ALEN);
                goto add_entry;
        }
 
-       return -ENOBUFS;
+       return PTR_ERR(neigh);
 
 non_local_input:
 
index 68fea02..7a44fa5 100644 (file)
@@ -44,15+44,8 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool '  IP: ARP daemon support (EXPERIMENTAL)' CONFIG_ARPD
    fi
 fi
+bool '  IP: TCP Explicit Congestion Notification support' CONFIG_INET_ECN
 bool '  IP: TCP syncookie support (disabled per default)' CONFIG_SYN_COOKIES
-comment '(it is safe to leave these untouched)'
-#bool '  IP: PC/TCP compatibility mode' CONFIG_INET_PCTCP
-#bool '  IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
-#bool '  IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
-bool '  IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
-#   bool '  IP: support checksum copy to user for UDP (EXPERIMENTAL)'  CONFIG_UDP_DELAY_CSUM
-#fi
 if [ "$CONFIG_NETFILTER" != "n" ]; then
    source net/ipv4/netfilter/Config.in
 fi
index 9def6b1..81d8ebe 100644 (file)
@@ -1,6+1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:    $Id: arp.c,v 1.86 2000/04/26 09:36:36 davem Exp $
+ * Version:    $Id: arp.c,v 1.87 2000/07/07 22:40:35 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
@@ -424,20+424,24 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
 int arp_bind_neighbour(struct dst_entry *dst)
 {
        struct net_device *dev = dst->dev;
+       struct neighbour *n = dst->neighbour;
 
        if (dev == NULL)
-               return 0;
-       if (dst->neighbour == NULL) {
+               return -EINVAL;
+       if (n == NULL) {
                u32 nexthop = ((struct rtable*)dst)->rt_gateway;
                if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
                        nexthop = 0;
-               dst->neighbour = __neigh_lookup(
+               n = __neigh_lookup_errno(
 #ifdef CONFIG_ATM_CLIP
                    dev->type == ARPHRD_ATM ? &clip_tbl :
 #endif
-                   &arp_tbl, &nexthop, dev, 1);
+                   &arp_tbl, &nexthop, dev);
+               if (IS_ERR(n))
+                       return PTR_ERR(n);
+               dst->neighbour = n;
        }
-       return (dst->neighbour != NULL);
+       return 0;
 }
 
 /*
@@ -847,9+851,9 @@ int arp_req_set(struct arpreq *r, struct net_device * dev)
        if (r->arp_ha.sa_family != dev->type)   
                return -EINVAL;
 
-       err = -ENOBUFS;
-       neigh = __neigh_lookup(&arp_tbl, &ip, dev, 1);
-       if (neigh) {
+       neigh = __neigh_lookup_errno(&arp_tbl, &ip, dev);
+       err = PTR_ERR(neigh);
+       if (!IS_ERR(neigh)) {
                unsigned state = NUD_STALE;
                if (r->arp_flags & ATF_PERM)
                        state = NUD_PERMANENT;
index 70f8cfb..07041a3 100644 (file)
@@ -5,7+5,7 @@
  *
  *             The IP fragmentation functionality.
  *             
- * Version:    $Id: ip_fragment.c,v 1.49 2000/04/15 01:48:10 davem Exp $
+ * Version:    $Id: ip_fragment.c,v 1.50 2000/07/07 22:29:42 davem Exp $
  *
  * Authors:    Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox <Alan.Cox@linux.org>
  *             Ultima          :       ip_expire() kernel panic.
  *             Bill Hawes      :       Frag accounting and evictor fixes.
  *             John McDonald   :       0 length frag bug.
+ *             Alexey Kuznetsov:       SMP races, threading, cleanup.
  */
 
 #include <linux/config.h>
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
+#include <net/checksum.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
 #include <linux/inet.h>
 #include <linux/netfilter_ipv4.h>
 
+/* NOTE. Logic of IP defragmentation is parallel to corresponding IPv6
+ * code now. If you change something here, _PLEASE_ update ipv6/reassembly.c
+ * as well. Or notify me, at least. --ANK
+ */
+
 /* Fragment cache limits. We will commit 256K at one time. Should we
  * cross that limit we will prune down to 192K. This should cope with
  * even the most extreme cases without allowing an attacker to measurably
@@ -46,38+53,77 @@ int sysctl_ipfrag_low_thresh = 192*1024;
 
 int sysctl_ipfrag_time = IP_FRAG_TIME;
 
-/* Describe an IP fragment. */
-struct ipfrag {
-       int             offset;         /* offset of fragment in IP datagram    */
-       int             end;            /* last byte of data in datagram        */
-       int             len;            /* length of this fragment              */
-       struct sk_buff  *skb;           /* complete received fragment           */
-       unsigned char   *ptr;           /* pointer into real fragment data      */
-       struct ipfrag   *next;          /* linked list pointers                 */
-       struct ipfrag   *prev;
+struct ipfrag_skb_cb
+{
+       struct inet_skb_parm    h;
+       int                     offset;
 };
 
+#define FRAG_CB(skb)   ((struct ipfrag_skb_cb*)((skb)->cb))
+
 /* Describe an entry in the "incomplete datagrams" queue. */
 struct ipq {
-       struct iphdr    *iph;           /* pointer to IP header                 */
        struct ipq      *next;          /* linked list pointers                 */
-       struct ipfrag   *fragments;     /* linked list of received fragments    */
+       u32             saddr;
+       u32             daddr;
+       u16             id;
+       u8              protocol;
+       u8              last_in;
+#define COMPLETE               4
+#define FIRST_IN               2
+#define LAST_IN                        1
+
+       struct sk_buff  *fragments;     /* linked list of received fragments    */
        int             len;            /* total length of original datagram    */
-       short           ihlen;          /* length of the IP header              */      
+       int             meat;
+       spinlock_t      lock;
+       atomic_t        refcnt;
        struct timer_list timer;        /* when will this queue expire?         */
        struct ipq      **pprev;
-       struct net_device       *dev;           /* Device - for icmp replies */
+       struct net_device       *dev;   /* Device - for icmp replies */
 };
 
+/* Hash table. */
+
 #define IPQ_HASHSZ     64
 
+/* Per-bucket lock is easy to add now. */
 static struct ipq *ipq_hash[IPQ_HASHSZ];
-static spinlock_t ipfrag_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+int ip_frag_nqueues = 0;
 
-#define ipqhashfn(id, saddr, daddr, prot) \
-       ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
+static __inline__ void __ipq_unlink(struct ipq *qp)
+{
+       if(qp->next)
+               qp->next->pprev = qp->pprev;
+       *qp->pprev = qp->next;
+       ip_frag_nqueues--;
+}
+
+static __inline__ void ipq_unlink(struct ipq *ipq)
+{
+       write_lock(&ipfrag_lock);
+       __ipq_unlink(ipq);
+       write_unlock(&ipfrag_lock);
+}
 
-static atomic_t ip_frag_mem = ATOMIC_INIT(0);  /* Memory used for fragments */
+/*
+ * Was:        ((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
+ *
+ * I see, I see evil hand of bigendian mafia. On Intel all the packets hit
+ * one hash bucket with this hash function. 8)
+ */
+static __inline__ unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
+{
+       unsigned int h = saddr ^ daddr;
+
+       h ^= (h>>16)^id;
+       h ^= (h>>8)^prot;
+       return h & (IPQ_HASHSZ - 1);
+}
+
+
+atomic_t ip_frag_mem = ATOMIC_INIT(0); /* Memory used for fragments */
 
 /* Memory Tracking Functions. */
 extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
@@ -86,112+132,106 @@ extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
        kfree_skb(skb);
 }
 
-extern __inline__ void frag_kfree_s(void *ptr, int len)
+extern __inline__ void frag_free_queue(struct ipq *qp)
 {
-       atomic_sub(len, &ip_frag_mem);
-       kfree(ptr);
+       atomic_sub(sizeof(struct ipq), &ip_frag_mem);
+       kfree(qp);
 }
-extern __inline__ void *frag_kmalloc(int size, int pri)
+
+extern __inline__ struct ipq *frag_alloc_queue(void)
 {
-       void *vp = kmalloc(size, pri);
+       struct ipq *qp = kmalloc(sizeof(struct ipq), GFP_ATOMIC);
 
-       if(!vp)
+       if(!qp)
                return NULL;
-       atomic_add(size, &ip_frag_mem);
-       return vp;
+       atomic_add(sizeof(struct ipq), &ip_frag_mem);
+       return qp;
 }
-/* Create a new fragment entry. */
-static struct ipfrag *ip_frag_create(int offset, int end,
-                                    struct sk_buff *skb, unsigned char *ptr)
+
+
+/* Destruction primitives. */
+
+/* Complete destruction of ipq. */
+static void ip_frag_destroy(struct ipq *qp)
 {
-       struct ipfrag *fp;
+       struct sk_buff *fp;
 
-       fp = (struct ipfrag *) frag_kmalloc(sizeof(struct ipfrag), GFP_ATOMIC);
-       if (fp == NULL)
-               goto out_nomem;
+       BUG_TRAP(qp->last_in&COMPLETE);
+       BUG_TRAP(del_timer(&qp->timer) == 0);
 
-       /* Fill in the structure. */
-       fp->offset = offset;
-       fp->end = end;
-       fp->len = end - offset;
-       fp->skb = skb;
-       fp->ptr = ptr;
-       fp->next = fp->prev = NULL;
-       
-       /* Charge for the SKB as well. */
-       atomic_add(skb->truesize, &ip_frag_mem);
+       /* Release all fragment data. */
+       fp = qp->fragments;
+       while (fp) {
+               struct sk_buff *xp = fp->next;
 
-       return(fp);
+               frag_kfree_skb(fp);
+               fp = xp;
+       }
 
-out_nomem:
-       NETDEBUG(printk(KERN_ERR "IP: frag_create: no memory left !\n"));
-       return(NULL);
+       /* Finally, release the queue descriptor itself. */
+       frag_free_queue(qp);
 }
 
-/* Find the correct entry in the "incomplete datagrams" queue for
- * this IP datagram, and return the queue entry address if found.
- */
-static inline struct ipq *ip_find(struct iphdr *iph, struct dst_entry *dst)
+static __inline__ void ipq_put(struct ipq *ipq)
 {
-       __u16 id = iph->id;
-       __u32 saddr = iph->saddr;
-       __u32 daddr = iph->daddr;
-       __u8 protocol = iph->protocol;
-       unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
-       struct ipq *qp;
-
-       /* We are always in BH context, and protected by the
-        * ipfrag lock.
-        */
-       for(qp = ipq_hash[hash]; qp; qp = qp->next) {
-               if(qp->iph->id == id            &&
-                  qp->iph->saddr == saddr      &&
-                  qp->iph->daddr == daddr      &&
-                  qp->iph->protocol == protocol) {
-                       del_timer(&qp->timer);
-                       break;
-               }
-       }
-       return qp;
+       if (atomic_dec_and_test(&ipq->refcnt))
+               ip_frag_destroy(ipq);
 }
 
-/* Remove an entry from the "incomplete datagrams" queue, either
- * because we completed, reassembled and processed it, or because
- * it timed out.
- *
- * This is called _only_ from BH contexts with the ipfrag lock held,
- * on packet reception processing and from frag queue expiration
- * timers.  -DaveM
+/* Kill ipq entry. It is not destroyed immediately,
+ * because caller (and someone more) holds reference count.
  */
-static void ip_free(struct ipq *qp)
+static __inline__ void ipq_kill(struct ipq *ipq)
 {
-       struct ipfrag *fp;
-
-       /* Stop the timer for this entry. */
-       del_timer(&qp->timer);
-
-       /* Remove this entry from the "incomplete datagrams" queue. */
-       if(qp->next)
-               qp->next->pprev = qp->pprev;
-       *qp->pprev = qp->next;
-
-       /* Release all fragment data. */
-       fp = qp->fragments;
-       while (fp) {
-               struct ipfrag *xp = fp->next;
+       if (del_timer(&ipq->timer))
+               atomic_dec(&ipq->refcnt);
 
-               frag_kfree_skb(fp->skb);
-               frag_kfree_s(fp, sizeof(struct ipfrag));
-               fp = xp;
+       if (!(ipq->last_in & COMPLETE)) {
+               ipq_unlink(ipq);
+               atomic_dec(&ipq->refcnt);
+               ipq->last_in |= COMPLETE;
        }
+}
 
-       /* Release the IP header. */
-       frag_kfree_s(qp->iph, 64 + 8);
+/* Memory limiting on fragments.  Evictor trashes the oldest 
+ * fragment queue until we are back under the low threshold.
+ */
+static void ip_evictor(void)
+{
+       int i, progress;
 
-       /* Finally, release the queue descriptor itself. */
-       frag_kfree_s(qp, sizeof(struct ipq));
+       do {
+               if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
+                       return;
+               progress = 0;
+               /* FIXME: Make LRU queue of frag heads. -DaveM */
+               for (i = 0; i < IPQ_HASHSZ; i++) {
+                       struct ipq *qp;
+                       if (ipq_hash[i] == NULL)
+                               continue;
+
+                       write_lock(&ipfrag_lock);
+                       if ((qp = ipq_hash[i]) != NULL) {
+                               /* find the oldest queue for this hash bucket */
+                               while (qp->next)
+                                       qp = qp->next;
+                               __ipq_unlink(qp);
+                               write_unlock(&ipfrag_lock);
+
+                               spin_lock(&qp->lock);
+                               if (del_timer(&qp->timer))
+                                       atomic_dec(&qp->refcnt);
+                               qp->last_in |= COMPLETE;
+                               spin_unlock(&qp->lock);
+
+                               ipq_put(qp);
+                               IP_INC_STATS_BH(IpReasmFails);
+                               progress = 1;
+                               continue;
+                       }
+                       write_unlock(&ipfrag_lock);
+               }
+       } while (progress);
 }
 
 /*
@@ -201,181+241,310 @@ static void ip_expire(unsigned long arg)
 {
        struct ipq *qp = (struct ipq *) arg;
 
-       spin_lock(&ipfrag_lock);
-       if(!qp->fragments)
-        {      
-#ifdef IP_EXPIRE_DEBUG
-               printk("warning: possible ip-expire attack\n");
-#endif
+       spin_lock(&qp->lock);
+
+       if (qp->last_in & COMPLETE)
                goto out;
-       }
-  
-       /* Send an ICMP "Fragment Reassembly Timeout" message. */
+
+       ipq_kill(qp);
+
        IP_INC_STATS_BH(IpReasmTimeout);
        IP_INC_STATS_BH(IpReasmFails);
-       icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
 
+       if ((qp->last_in&FIRST_IN) && qp->fragments != NULL) {
+               /* Send an ICMP "Fragment Reassembly Timeout" message. */
+               icmp_send(qp->fragments, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
+       }
 out:
-       /* Nuke the fragment queue. */
-       ip_free(qp);
-       spin_unlock(&ipfrag_lock);
+       spin_unlock(&qp->lock);
+       ipq_put(qp);
 }
 
-/* Memory limiting on fragments.  Evictor trashes the oldest 
- * fragment queue until we are back under the low threshold.
- *
- * We are always called in BH with the ipfrag lock held.
- */
-static void ip_evictor(void)
+/* Creation primitives. */
+
+static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in)
 {
-       int i, progress;
+       struct ipq *qp;
 
-restart:
-       progress = 0;
-       /* FIXME: Make LRU queue of frag heads. -DaveM */
-       for (i = 0; i < IPQ_HASHSZ; i++) {
-               struct ipq *qp;
-               if (atomic_read(&ip_frag_mem) <= sysctl_ipfrag_low_thresh)
-                       return;
-               qp = ipq_hash[i];
-               if (qp) {
-                       /* find the oldest queue for this hash bucket */
-                       while (qp->next)
-                               qp = qp->next;
-                       ip_free(qp);
-                       progress = 1;
+       write_lock(&ipfrag_lock);
+#ifdef CONFIG_SMP
+       /* With SMP race we have to recheck hash table, because
+        * such entry could be created on other cpu, while we
+        * promoted read lock to write lock.
+        */
+       for(qp = ipq_hash[hash]; qp; qp = qp->next) {
+               if(qp->id == qp_in->id          &&
+                  qp->saddr == qp_in->saddr    &&
+                  qp->daddr == qp_in->daddr    &&
+                  qp->protocol == qp_in->protocol) {
+                       atomic_inc(&qp->refcnt);
+                       write_unlock(&ipfrag_lock);
+                       qp_in->last_in |= COMPLETE;
+                       ipq_put(qp_in);
+                       return qp;
                }
        }
-       if (progress)
-               goto restart;
-       panic("ip_evictor: memcount");
+#endif
+       qp = qp_in;
+
+       atomic_inc(&qp->refcnt);
+       if((qp->next = ipq_hash[hash]) != NULL)
+               qp->next->pprev = &qp->next;
+       ipq_hash[hash] = qp;
+       qp->pprev = &ipq_hash[hash];
+       ip_frag_nqueues++;
+       write_unlock(&ipfrag_lock);
+       return qp;
 }
 
-/* Add an entry to the 'ipq' queue for a newly received IP datagram.
- * We will (hopefully :-) receive all other fragments of this datagram
- * in time, so we just create a queue for this datagram, in which we
- * will insert the received fragments at their respective positions.
- */
-static struct ipq *ip_create(struct sk_buff *skb, struct iphdr *iph)
+/* Add an entry to the 'ipq' queue for a newly received IP datagram. */
+static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph)
 {
        struct ipq *qp;
-       unsigned int hash;
-       int ihlen;
 
-       qp = (struct ipq *) frag_kmalloc(sizeof(struct ipq), GFP_ATOMIC);
-       if (qp == NULL)
+       if ((qp = frag_alloc_queue()) == NULL)
                goto out_nomem;
 
-       /* Allocate memory for the IP header (plus 8 octets for ICMP). */
-       ihlen = iph->ihl * 4;
-
-       qp->iph = (struct iphdr *) frag_kmalloc(64 + 8, GFP_ATOMIC);
-       if (qp->iph == NULL)
-               goto out_free;
-
-       memcpy(qp->iph, iph, ihlen + 8);
+       qp->protocol = iph->protocol;
+       qp->last_in = 0;
+       qp->id = iph->id;
+       qp->saddr = iph->saddr;
+       qp->daddr = iph->daddr;
        qp->len = 0;
-       qp->ihlen = ihlen;
+       qp->meat = 0;
        qp->fragments = NULL;
-       qp->dev = skb->dev;
 
        /* Initialize a timer for this entry. */
        init_timer(&qp->timer);
-       qp->timer.expires = 0;                  /* (to be set later)    */
        qp->timer.data = (unsigned long) qp;    /* pointer to queue     */
        qp->timer.function = ip_expire;         /* expire function      */
+       qp->lock = SPIN_LOCK_UNLOCKED;
+       atomic_set(&qp->refcnt, 1);
 
-       /* Add this entry to the queue. */
-       hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
+       return ip_frag_intern(hash, qp);
 
-       /* In a BH context and ipfrag lock is held.  -DaveM */
-       if((qp->next = ipq_hash[hash]) != NULL)
-               qp->next->pprev = &qp->next;
-       ipq_hash[hash] = qp;
-       qp->pprev = &ipq_hash[hash];
+out_nomem:
+       NETDEBUG(printk(KERN_ERR "ip_frag_create: no memory left !\n"));
+       return NULL;
+}
 
-       return qp;
+/* Find the correct entry in the "incomplete datagrams" queue for
+ * this IP datagram, and create new one, if nothing is found.
+ */
+static inline struct ipq *ip_find(struct iphdr *iph)
+{
+       __u16 id = iph->id;
+       __u32 saddr = iph->saddr;
+       __u32 daddr = iph->daddr;
+       __u8 protocol = iph->protocol;
+       unsigned int hash = ipqhashfn(id, saddr, daddr, protocol);
+       struct ipq *qp;
 
-out_free:
-       frag_kfree_s(qp, sizeof(struct ipq));
-out_nomem:
-       NETDEBUG(printk(KERN_ERR "IP: create: no memory left !\n"));
-       return(NULL);
+       read_lock(&ipfrag_lock);
+       for(qp = ipq_hash[hash]; qp; qp = qp->next) {
+               if(qp->id == id         &&
+                  qp->saddr == saddr   &&
+                  qp->daddr == daddr   &&
+                  qp->protocol == protocol) {
+                       atomic_inc(&qp->refcnt);
+                       read_unlock(&ipfrag_lock);
+                       return qp;
+               }
+       }
+       read_unlock(&ipfrag_lock);
+
+       return ip_frag_create(hash, iph);
 }
 
-/* See if a fragment queue is complete. */
-static int ip_done(struct ipq *qp)
+/* Add new segment to existing queue. */
+static void ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
 {
-       struct ipfrag *fp;
-       int offset;
+       struct iphdr *iph = skb->nh.iph;
+       struct sk_buff *prev, *next;
+       int flags, offset;
+       int ihl, end;
 
-       /* Only possible if we received the final fragment. */
-       if (qp->len == 0)
-               return 0;
+       if (qp->last_in & COMPLETE)
+               goto err;
 
-       /* Check all fragment offsets to see if they connect. */
-       fp = qp->fragments;
-       offset = 0;
-       while (fp) {
-               if (fp->offset > offset)
-                       return(0);      /* fragment(s) missing */
-               offset = fp->end;
-               fp = fp->next;
+       if (!mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time))
+               atomic_inc(&qp->refcnt);
+
+       offset = ntohs(iph->frag_off);
+       flags = offset & ~IP_OFFSET;
+       offset &= IP_OFFSET;
+       offset <<= 3;           /* offset is in 8-byte chunks */
+       ihl = iph->ihl * 4;
+
+       /* Determine the position of this fragment. */
+       end = offset + (ntohs(iph->tot_len) - ihl);
+
+       /* Is this the final fragment? */
+       if ((flags & IP_MF) == 0) {
+               /* If we already have some bits beyond end
+                * or have different end, the segment is corrrupted.
+                */
+               if (end < qp->len ||
+                   ((qp->last_in & LAST_IN) && end != qp->len))
+                       goto err;
+               qp->last_in |= LAST_IN;
+               qp->len = end;
+       } else {
+               if (end&7) {
+                       end &= ~7;
+                       if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+                               skb->ip_summed = CHECKSUM_NONE;
+               }
+               if (end > qp->len) {
+                       /* Some bits beyond end -> corruption. */
+                       if (qp->last_in & LAST_IN)
+                               goto err;
+                       qp->len = end;
+               }
        }
+       if (end == offset)
+               goto err;
+
+       /* Point into the IP datagram 'data' part. */
+       skb_pull(skb, (skb->nh.raw+ihl) - skb->data);
+       skb_trim(skb, end - offset);
+
+       /* Find out which fragments are in front and at the back of us
+        * in the chain of fragments so far.  We must know where to put
+        * this fragment, right?
+        */
+       prev = NULL;
+       for(next = qp->fragments; next != NULL; next = next->next) {
+               if (FRAG_CB(next)->offset >= offset)
+                       break;  /* bingo! */
+               prev = next;
+       }
+
+       /* We found where to put this one.  Check for overlap with
+        * preceding fragment, and, if needed, align things so that
+        * any overlaps are eliminated.
+        */
+       if (prev) {
+               int i = (FRAG_CB(prev)->offset + prev->len) - offset;
+
+               if (i > 0) {
+                       offset += i;
+                       if (end <= offset)
+                               goto err;
+                       skb_pull(skb, i);
+                       if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+                               skb->ip_summed = CHECKSUM_NONE;
+               }
+       }
+
+       while (next && FRAG_CB(next)->offset < end) {
+               int i = end - FRAG_CB(next)->offset; /* overlap is 'i' bytes */
+
+               if (i < next->len) {
+                       /* Eat head of the next overlapped fragment
+                        * and leave the loop. The next ones cannot overlap.
+                        */
+                       FRAG_CB(next)->offset += i;
+                       skb_pull(next, i);
+                       qp->meat -= i;
+                       if (next->ip_summed != CHECKSUM_UNNECESSARY)
+                               next->ip_summed = CHECKSUM_NONE;
+                       break;
+               } else {
+                       struct sk_buff *free_it = next;
 
-       /* All fragments are present. */
-       return 1;
+                       /* Old fragmnet is completely overridden with
+                        * new one drop it.
+                        */
+                       next = next->next;
+
+                       if (prev)
+                               prev->next = next;
+                       else
+                               qp->fragments = next;
+
+                       qp->meat -= free_it->len;
+                       frag_kfree_skb(free_it);
+               }
+       }
+
+       FRAG_CB(skb)->offset = offset;
+
+       /* Insert this fragment in the chain of fragments. */
+       skb->next = next;
+       if (prev)
+               prev->next = skb;
+       else
+               qp->fragments = skb;
+
+       qp->dev = skb->dev;
+       qp->meat += skb->len;
+       atomic_add(skb->truesize, &ip_frag_mem);
+       if (offset == 0)
+               qp->last_in |= FIRST_IN;
+
+       return;
+
+err:
+       kfree_skb(skb);
 }
 
+
 /* Build a new IP datagram from all its fragments.
  *
  * FIXME: We copy here because we lack an effective way of handling lists
  * of bits on input. Until the new skb data handling is in I'm not going
  * to touch this with a bargepole. 
  */
-static struct sk_buff *ip_glue(struct ipq *qp)
+static struct sk_buff *ip_frag_reasm(struct ipq *qp)
 {
        struct sk_buff *skb;
        struct iphdr *iph;
-       struct ipfrag *fp;
-       unsigned char *ptr;
-       int count, len;
+       struct sk_buff *fp, *head = qp->fragments;
+       int len;
+       int ihlen;
+
+       ipq_kill(qp);
+
+       BUG_TRAP(head != NULL);
+       BUG_TRAP(FRAG_CB(head)->offset == 0);
 
        /* Allocate a new buffer for the datagram. */
-       len = qp->ihlen + qp->len;
-       
+       ihlen = head->nh.iph->ihl*4;
+       len = ihlen + qp->len;
+
        if(len > 65535)
                goto out_oversize;
-       
+
        skb = dev_alloc_skb(len);
        if (!skb)
                goto out_nomem;
 
        /* Fill in the basic details. */
-       skb->mac.raw = ptr = skb->data;
-       skb->nh.iph = iph = (struct iphdr *) skb_put(skb, len);
+       skb->mac.raw = skb->data;
+       skb->nh.raw = skb->data;
+       FRAG_CB(skb)->h = FRAG_CB(head)->h;
+       skb->ip_summed = head->ip_summed;
+       skb->csum = 0;
 
        /* Copy the original IP headers into the new buffer. */
-       memcpy(ptr, qp->iph, qp->ihlen);
-       ptr += qp->ihlen;
+       memcpy(skb_put(skb, ihlen), head->nh.iph, ihlen);
 
        /* Copy the data portions of all fragments into the new buffer. */
-       fp = qp->fragments;
-       count = qp->ihlen;
-       while(fp) {
-               if ((fp->len <= 0) || ((count + fp->len) > skb->len))
-                       goto out_invalid;
-               memcpy((ptr + fp->offset), fp->ptr, fp->len);
-               if (count == qp->ihlen) {
-                       skb->dst = dst_clone(fp->skb->dst);
-                       skb->dev = fp->skb->dev;
-               }
-               count += fp->len;
-               fp = fp->next;
+       for (fp=head; fp; fp = fp->next) {
+               memcpy(skb_put(skb, fp->len), fp->data, fp->len);
+
+               if (skb->ip_summed != fp->ip_summed)
+                       skb->ip_summed = CHECKSUM_NONE;
+               else if (skb->ip_summed == CHECKSUM_HW)
+                       skb->csum = csum_chain(skb->csum, fp->csum);
        }
 
-       skb->pkt_type = qp->fragments->skb->pkt_type;
-       skb->protocol = qp->fragments->skb->protocol;
+       skb->dst = dst_clone(head->dst);
+       skb->pkt_type = head->pkt_type;
+       skb->protocol = head->protocol;
+       skb->dev = qp->dev;
+
        /*
        *  Clearly bogus, because security markings of the individual
        *  fragments should have been checked for consistency before
@@ -385,29+554,24 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        *  as well take the value associated with the first fragment.
        *       --rct
        */
-       skb->security = qp->fragments->skb->security;
+       skb->security = head->security;
 
 #ifdef CONFIG_NETFILTER
        /* Connection association is same as fragment (if any). */
-       skb->nfct = qp->fragments->skb->nfct;
+       skb->nfct = head->nfct;
        nf_conntrack_get(skb->nfct);
 #ifdef CONFIG_NETFILTER_DEBUG
-       skb->nf_debug = qp->fragments->skb->nf_debug;
+       skb->nf_debug = head->nf_debug;
 #endif
 #endif
 
        /* Done with all fragments. Fixup the new IP header. */
        iph = skb->nh.iph;
        iph->frag_off = 0;
-       iph->tot_len = htons(count);
+       iph->tot_len = htons(len);
        IP_INC_STATS_BH(IpReasmOKs);
        return skb;
 
-out_invalid:
-       NETDEBUG(printk(KERN_ERR
-                       "Invalid fragment list: Fragment over size.\n"));
-       kfree_skb(skb);
-       goto out_fail;
 out_nomem:
        NETDEBUG(printk(KERN_ERR 
                        "IP: queue_glue: no memory for gluing queue %p\n",
@@ -417,7+581,7 @@ out_oversize:
        if (net_ratelimit())
                printk(KERN_INFO
                        "Oversized IP packet from %d.%d.%d.%d.\n",
-                       NIPQUAD(qp->iph->saddr));
+                       NIPQUAD(qp->saddr));
 out_fail:
        IP_INC_STATS_BH(IpReasmFails);
        return NULL;
@@ -427,185+591,32 @@ out_fail:
 struct sk_buff *ip_defrag(struct sk_buff *skb)
 {
        struct iphdr *iph = skb->nh.iph;
-       struct ipfrag *prev, *next, *tmp, *tfp;
        struct ipq *qp;
-       unsigned char *ptr;
-       int flags, offset;
-       int i, ihl, end;
        
        IP_INC_STATS_BH(IpReasmReqds);
 
-       spin_lock(&ipfrag_lock);
-
        /* Start by cleaning up the memory. */
        if (atomic_read(&ip_frag_mem) > sysctl_ipfrag_high_thresh)
                ip_evictor();
 
-       /*
-        * Look for the entry for this IP datagram in the
-        * "incomplete datagrams" queue. If found, the
-        * timer is removed.
-        */
-       qp = ip_find(iph, skb->dst);
-
-       /* Is this a non-fragmented datagram? */
-       offset = ntohs(iph->frag_off);
-       flags = offset & ~IP_OFFSET;
-       offset &= IP_OFFSET;
+       /* Lookup (or create) queue header */
+       if ((qp = ip_find(iph)) != NULL) {
+               struct sk_buff *ret = NULL;
 
-       offset <<= 3;           /* offset is in 8-byte chunks */
-       ihl = iph->ihl * 4;
+               spin_lock(&qp->lock);
 
-       /*
-        * Check whether to create a fresh queue entry. If the
-        * queue already exists, its timer will be restarted as
-        * long as we continue to receive fragments.
-        */
-       if (qp) {
-               /* ANK. If the first fragment is received,
-                * we should remember the correct IP header (with options)
-                */
-               if (offset == 0) {
-                       /* Fragmented frame replaced by unfragmented copy? */
-                       if ((flags & IP_MF) == 0)
-                               goto out_freequeue;
-                       qp->ihlen = ihl;
-                       memcpy(qp->iph, iph, (ihl + 8));
-               }
-       } else {
-               /* Fragmented frame replaced by unfragmented copy? */
-               if ((offset == 0) && ((flags & IP_MF) == 0))
-                       goto out_skb;
-
-               /* If we failed to create it, then discard the frame. */
-               qp = ip_create(skb, iph);
-               if (!qp)
-                       goto out_freeskb;
-       }
-       
-       /* Attempt to construct an oversize packet. */
-       if((ntohs(iph->tot_len) + ((int) offset)) > 65535)
-               goto out_oversize;
+               ip_frag_queue(qp, skb);
 
-       /* Determine the position of this fragment. */
-       end = offset + ntohs(iph->tot_len) - ihl;
+               if (qp->last_in == (FIRST_IN|LAST_IN) &&
+                   qp->meat == qp->len)
+                       ret = ip_frag_reasm(qp);
 
-       /* Is this the final fragment? */
-       if ((flags & IP_MF) == 0)
-               qp->len = end;
-
-       /* Find out which fragments are in front and at the back of us
-        * in the chain of fragments so far.  We must know where to put
-        * this fragment, right?
-        */
-       prev = NULL;
-       for(next = qp->fragments; next != NULL; next = next->next) {
-               if (next->offset >= offset)
-                       break;  /* bingo! */
-               prev = next;
+               spin_unlock(&qp->lock);
+               ipq_put(qp);
+               return ret;
        }
 
-       /* Point into the IP datagram 'data' part. */
-       ptr = skb->data + ihl;
-
-       /* We found where to put this one.  Check for overlap with
-        * preceding fragment, and, if needed, align things so that
-        * any overlaps are eliminated.
-        */
-       if ((prev != NULL) && (offset < prev->end)) {
-               i = prev->end - offset;
-               offset += i;    /* ptr into datagram */
-               ptr += i;       /* ptr into fragment data */
-       }
-
-       /* Look for overlap with succeeding segments.
-        * If we can merge fragments, do it.
-        */
-       for (tmp = next; tmp != NULL; tmp = tfp) {
-               tfp = tmp->next;
-               if (tmp->offset >= end)
-                       break;          /* no overlaps at all   */
-
-               i = end - next->offset; /* overlap is 'i' bytes */
-               tmp->len -= i;          /* so reduce size of    */
-               tmp->offset += i;       /* next fragment        */
-               tmp->ptr += i;
-
-               /* If we get a frag size of <= 0, remove it and the packet
-                * that it goes with.
-                */
-               if (tmp->len <= 0) {
-                       if (tmp->prev != NULL)
-                               tmp->prev->next = tmp->next;
-                       else
-                               qp->fragments = tmp->next;
-
-                       if (tmp->next != NULL)
-                               tmp->next->prev = tmp->prev;
-                       
-                       /* We have killed the original next frame. */
-                       next = tfp;
-
-                       frag_kfree_skb(tmp->skb);
-                       frag_kfree_s(tmp, sizeof(struct ipfrag));
-               }
-       }
-
-       /*
-        * Create a fragment to hold this skb.
-        * No memory to save the fragment? throw the lot ...
-        */
-       tfp = ip_frag_create(offset, end, skb, ptr);
-       if (!tfp)
-               goto out_freeskb;
-
-       /* Insert this fragment in the chain of fragments. */
-       tfp->prev = prev;
-       tfp->next = next;
-       if (prev != NULL)
-               prev->next = tfp;
-       else
-               qp->fragments = tfp;
-
-       if (next != NULL)
-               next->prev = tfp;
-
-       /* OK, so we inserted this new fragment into the chain.
-        * Check if we now have a full IP datagram which we can
-        * bump up to the IP layer...
-        */
-       if (ip_done(qp)) {
-               /* Glue together the fragments. */
-               skb = ip_glue(qp);
-               /* Free the queue entry. */
-out_freequeue:
-               ip_free(qp);
-out_skb:
-               spin_unlock(&ipfrag_lock);
-               return skb;
-       }
-
-       /*
-        * The queue is still active ... reset its timer.
-        */
-out_timer:
-       mod_timer(&qp->timer, jiffies + sysctl_ipfrag_time); /* ~ 30 seconds */
-out:
-       spin_unlock(&ipfrag_lock);
-       return NULL;
-
-       /*
-        * Error exits ... we need to reset the timer if there's a queue.
-        */
-out_oversize:
-       if (net_ratelimit())
-               printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n",
-                       NIPQUAD(iph->saddr));
-       /* the skb isn't in a fragment, so fall through to free it */
-out_freeskb:
-       kfree_skb(skb);
        IP_INC_STATS_BH(IpReasmFails);
-       if (qp)
-               goto out_timer;
-       goto out;
+       kfree_skb(skb);
+       return NULL;
 }
index 79dc3d6..a316401 100644 (file)
 #include <net/ipip.h>
 #include <net/arp.h>
 #include <net/checksum.h>
+#include <net/inet_ecn.h>
 
 #ifdef CONFIG_IPV6
 #include <net/ipv6.h>
@@ -119,11+120,11 @@ static int ipgre_tunnel_init(struct net_device *dev);
 static int ipgre_fb_tunnel_init(struct net_device *dev);
 
 static struct net_device ipgre_fb_tunnel_dev = {
-       "gre%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
+       "gre0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipgre_fb_tunnel_init,
 };
 
 static struct ip_tunnel ipgre_fb_tunnel = {
-       NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre%d", }
+       NULL, &ipgre_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"gre0", }
 };
 
 /* Tunnel hash table */
@@ -530,6+531,34 @@ out:
 #endif
 }
 
+static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+       if (INET_ECN_is_ce(iph->tos)) {
+               if (skb->protocol == __constant_htons(ETH_P_IP)) {
+                       if (INET_ECN_is_not_ce(skb->nh.iph->tos))
+                               IP_ECN_set_ce(skb->nh.iph);
+               } else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
+                       if (INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+                               IP6_ECN_set_ce(skb->nh.ipv6h);
+               }
+       }
+}
+
+static inline u8
+ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb)
+{
+#ifdef CONFIG_INET_ECN
+       u8 inner = 0;
+       if (skb->protocol == __constant_htons(ETH_P_IP))
+               inner = old_iph->tos;
+       else if (skb->protocol == __constant_htons(ETH_P_IPV6))
+               inner = ip6_get_dsfield((struct ipv6hdr*)old_iph);
+       return INET_ECN_encapsulate(tos, inner);
+#else
+       return tos;
+#endif
+}
+
 int ipgre_rcv(struct sk_buff *skb, unsigned short len)
 {
        struct iphdr *iph = skb->nh.iph;
@@ -604,6+633,7 @@ int ipgre_rcv(struct sk_buff *skb, unsigned short len)
                nf_conntrack_put(skb->nfct);
                skb->nfct = NULL;
 #endif
+               ipgre_ecn_decapsulate(iph, skb);
                netif_rx(skb);
                read_unlock(&ipgre_lock);
                return(0);
@@ -638,6+668,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        int    gre_hlen;
        u32    dst;
        int    mtu;
+       int    err;
 
        if (tunnel->recursion++) {
                tunnel->stat.collisions++;
@@ -789,7+820,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        iph->ihl                =       sizeof(struct iphdr) >> 2;
        iph->frag_off           =       df;
        iph->protocol           =       IPPROTO_GRE;
-       iph->tos                =       tos;
+       iph->tos                =       ipgre_ecn_encapsulate(tos, old_iph, skb);
        iph->daddr              =       rt->rt_dst;
        iph->saddr              =       rt->rt_src;
 
@@ -834,10+865,17 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        skb->nfct = NULL;
 #endif
 
+       err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+               do_ip_send);
+       if(err < 0) {
+               if(net_ratelimit())
+                       printk(KERN_ERR "ipgre_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+               skb = NULL;
+               goto tx_error;
+       }
+
        stats->tx_bytes += skb->len;
        stats->tx_packets++;
-       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-               do_ip_send);
        tunnel->recursion--;
        return 0;
 
@@ -846,7+884,8 @@ tx_error_icmp:
 
 tx_error:
        stats->tx_errors++;
-       dev_kfree_skb(skb);
+       if(skb)
+               dev_kfree_skb(skb);
        tunnel->recursion--;
        return 0;
 }
index 90b7444..aea8b93 100644 (file)
@@ -5,7+5,7 @@
  *
  *             The IP to API glue.
  *             
- * Version:    $Id: ip_sockglue.c,v 1.47 2000/01/16 05:11:23 davem Exp $
+ * Version:    $Id: ip_sockglue.c,v 1.49 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    see ip.c
  *
@@ -327,6+327,8 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (err)
                goto out_free_skb;
 
+       sock_recv_timestamp(msg, sk, skb);
+
        serr = SKB_EXT_ERR(skb);
 
        sin = (struct sockaddr_in *)msg->msg_name;
@@ -462,8+464,15 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        break;
                case IP_TOS:    /* This sets both TOS and Precedence */
                          /* Reject setting of unused bits */
+#ifndef CONFIG_INET_ECN
                        if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))
                                goto e_inval;
+#else
+                       if (sk->type == SOCK_STREAM) {
+                               val &= ~3;
+                               val |= sk->protinfo.af_inet.tos & 3;
+                       }
+#endif
                        if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 
                            !capable(CAP_NET_ADMIN)) {
                                err = -EPERM;
index e343f34..1177033 100644 (file)
@@ -1,7+1,7 @@
 /*
  *     Linux NET3:     IP/IP protocol decoder. 
  *
- *     Version: $Id: ipip.c,v 1.35 2000/07/07 01:55:20 davem Exp $
+ *     Version: $Id: ipip.c,v 1.37 2000/07/07 23:47:45 davem Exp $
  *
  *     Authors:
  *             Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
 #include <net/icmp.h>
 #include <net/protocol.h>
 #include <net/ipip.h>
+#include <net/inet_ecn.h>
 
 #define HASH_SIZE  16
 #define HASH(addr) ((addr^(addr>>4))&0xF)
@@ -122,11+123,11 @@ static int ipip_fb_tunnel_init(struct net_device *dev);
 static int ipip_tunnel_init(struct net_device *dev);
 
 static struct net_device ipip_fb_tunnel_dev = {
-       "tunl%d", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
+       "tunl0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip_fb_tunnel_init,
 };
 
 static struct ip_tunnel ipip_fb_tunnel = {
-       NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl%d", }
+       NULL, &ipip_fb_tunnel_dev, {0, }, 0, 0, 0, 0, 0, 0, 0, {"tunl0", }
 };
 
 static struct ip_tunnel *tunnels_r_l[HASH_SIZE];
@@ -465,6+466,13 @@ out:
 #endif
 }
 
+static inline void ipip_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+       if (INET_ECN_is_ce(iph->tos) &&
+           INET_ECN_is_not_ce(skb->nh.iph->tos))
+               IP_ECN_set_ce(iph);
+}
+
 int ipip_rcv(struct sk_buff *skb, unsigned short len)
 {
        struct iphdr *iph;
@@ -489,6+497,7 @@ int ipip_rcv(struct sk_buff *skb, unsigned short len)
                nf_conntrack_put(skb->nfct);
                skb->nfct = NULL;
 #endif
+               ipip_ecn_decapsulate(iph, skb);
                netif_rx(skb);
                read_unlock(&ipip_lock);
                return 0;
@@ -525,6+534,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        int    max_headroom;                    /* The extra header space needed */
        u32    dst = tiph->daddr;
        int    mtu;
+       int    err;
 
        if (tunnel->recursion++) {
                tunnel->stat.collisions++;
@@ -620,7+630,7 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        iph->ihl                =       sizeof(struct iphdr)>>2;
        iph->frag_off           =       df;
        iph->protocol           =       IPPROTO_IPIP;
-       iph->tos                =       tos;
+       iph->tos                =       INET_ECN_encapsulate(tos, old_iph->tos);
        iph->daddr              =       rt->rt_dst;
        iph->saddr              =       rt->rt_src;
 
@@ -636,10+646,17 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        skb->nfct = NULL;
 #endif
 
+       err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+               do_ip_send);
+       if(err < 0) {
+               if(net_ratelimit())
+                       printk(KERN_ERR "ipip_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+               skb = NULL;
+               goto tx_error;
+       }
+
        stats->tx_bytes += skb->len;
        stats->tx_packets++;
-       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-               do_ip_send);
        tunnel->recursion--;
        return 0;
 
@@ -647,7+664,8 @@ tx_error_icmp:
        dst_link_failure(skb);
 tx_error:
        stats->tx_errors++;
-       dev_kfree_skb(skb);
+       if(skb)
+               dev_kfree_skb(skb);
        tunnel->recursion--;
        return 0;
 }
index 4d94a4c..f1ff8f1 100644 (file)
@@ -7,7+7,7 @@
  *             PROC file system.  It is mainly used for debugging and
  *             statistics.
  *
- * Version:    $Id: proc.c,v 1.42 2000/04/16 01:11:37 davem Exp $
+ * Version:    $Id: proc.c,v 1.43 2000/07/07 22:29:42 davem Exp $
  *
  * Authors:    Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -78,6+78,8 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length)
                       fold_prot_inuse(&udp_prot));
        len += sprintf(buffer+len,"RAW: inuse %d\n",
                       fold_prot_inuse(&raw_prot));
+       len += sprintf(buffer+len, "FRAG: inuse %d memory %d\n",
+                      ip_frag_nqueues, atomic_read(&ip_frag_mem));
        if (offset >= len)
        {
                *start = buffer;
index 6e3f192..5ac30dc 100644 (file)
@@ -5,7+5,7 @@
  *
  *             RAW - implementation of IP "raw" sockets.
  *
- * Version:    $Id: raw.c,v 1.50 2000/05/03 06:37:06 davem Exp $
+ * Version:    $Id: raw.c,v 1.52 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -502,7+502,7 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        if (err)
                goto done;
 
-       sk->stamp=skb->stamp;
+       sock_recv_timestamp(msg, sk, skb);
 
        /* Copy the address. */
        if (sin) {
@@ -580,6+580,36 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
        return -ENOPROTOOPT;
 }
 
+static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+       switch(cmd) {
+               case SIOCOUTQ:
+               {
+                       int amount = atomic_read(&sk->wmem_alloc);
+                       return put_user(amount, (int *)arg);
+               }
+               case SIOCINQ:
+               {
+                       struct sk_buff *skb;
+                       int amount = 0;
+
+                       spin_lock_irq(&sk->receive_queue.lock);
+                       skb = skb_peek(&sk->receive_queue);
+                       if (skb != NULL)
+                               amount = skb->len;
+                       spin_unlock_irq(&sk->receive_queue.lock);
+                       return put_user(amount, (int *)arg);
+               }
+
+               default:
+#ifdef CONFIG_IP_MROUTE
+                       return ipmr_ioctl(sk, cmd, arg);
+#else
+                       return -ENOIOCTLCMD;
+#endif
+       }
+}
+
 static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
 {
        unsigned int dest, src;
@@ -648,9+678,7 @@ struct proto raw_prot = {
        close:          raw_close,
        connect:        udp_connect,
        disconnect:     udp_disconnect,
-#ifdef CONFIG_IP_MROUTE
-       ioctl:          ipmr_ioctl,
-#endif
+       ioctl:          raw_ioctl,
        init:           raw_init,
        setsockopt:     raw_setsockopt,
        getsockopt:     raw_getsockopt,
index ec254e3..eb00518 100644 (file)
@@ -5,7+5,7 @@
  *
  *             ROUTE - implementation of the IP router.
  *
- * Version:    $Id: route.c,v 1.86 2000/04/24 07:03:14 davem Exp $
+ * Version:    $Id: route.c,v 1.88 2000/07/07 23:47:45 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -152,23+152,29 @@ struct dst_ops ipv4_dst_ops =
        sizeof(struct rtable),
 };
 
+#ifdef CONFIG_INET_ECN
+#define ECN_OR_COST(class)     TC_PRIO_##class
+#else
+#define ECN_OR_COST(class)     TC_PRIO_FILLER
+#endif
+
 __u8 ip_tos2prio[16] = {
        TC_PRIO_BESTEFFORT,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(FILLER),
        TC_PRIO_BESTEFFORT,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(BESTEFFORT),
        TC_PRIO_BULK,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(BULK),
        TC_PRIO_BULK,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(BULK),
        TC_PRIO_INTERACTIVE,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(INTERACTIVE),
        TC_PRIO_INTERACTIVE,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(INTERACTIVE),
        TC_PRIO_INTERACTIVE_BULK,
-       TC_PRIO_FILLER,
+       ECN_OR_COST(INTERACTIVE_BULK),
        TC_PRIO_INTERACTIVE_BULK,
-       TC_PRIO_FILLER
+       ECN_OR_COST(INTERACTIVE_BULK)
 };
 
 
@@ -582,9+588,15 @@ restart:
           route or unicast forwarding path.
         */
        if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) {
-               if (!arp_bind_neighbour(&rt->u.dst)) {
+               int err = arp_bind_neighbour(&rt->u.dst);
+               if (err) {
                        write_unlock_bh(&rt_hash_table[hash].lock);
 
+                       if (err != -ENOBUFS) {
+                               rt_drop(rt);
+                               return err;
+                       }
+
                        /* Neighbour tables are full and nothing
                           can be released. Try to shrink route cache,
                           it is most likely it holds some neighbour records.
@@ -600,13+612,8 @@ restart:
                                goto restart;
                        }
 
-                       if (net_ratelimit()) {
-                               if ((rt->u.dst.dev->flags&IFF_UP) &&
-                                   __in_dev_get(rt->u.dst.dev))
-                                       printk("Neighbour table overflow.\n");
-                               else
-                                       printk("Device %s is down.\n", rt->u.dst.dev->name);
-                       }
+                       if (net_ratelimit())
+                               printk("Neighbour table overflow.\n");
                        rt_drop(rt);
                        return -ENOBUFS;
                }
@@ -712,7+719,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
        u32  skeys[2] = { saddr, 0 };
        int  ikeys[2] = { dev->ifindex, 0 };
 
-       tos &= IPTOS_TOS_MASK;
+       tos &= IPTOS_RT_MASK;
 
        if (!in_dev)
                return;
@@ -791,7+798,7 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
                                if (rt->peer)
                                        atomic_inc(&rt->peer->refcnt);
 
-                               if (!arp_bind_neighbour(&rt->u.dst) ||
+                               if (arp_bind_neighbour(&rt->u.dst) ||
                                    !(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
                                        if (rt->u.dst.neighbour)
                                                neigh_event_send(rt->u.dst.neighbour, NULL);
@@ -967,7+974,7 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
        struct rtable *rth;
        u32  skeys[2] = { iph->saddr, 0, };
        u32  daddr = iph->daddr;
-       u8   tos = iph->tos & IPTOS_TOS_MASK;
+       u8   tos = iph->tos & IPTOS_RT_MASK;
        unsigned short est_mtu = 0;
 
        if (ipv4_config.no_pmtu_disc)
@@ -1546,7+1553,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
        unsigned        hash;
        int iif = dev->ifindex;
 
-       tos &= IPTOS_TOS_MASK;
+       tos &= IPTOS_RT_MASK;
        hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
 
        read_lock(&rt_hash_table[hash].lock);
@@ -1616,10+1623,10 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
        int free_res = 0;
        int err;
 
-       tos &= IPTOS_TOS_MASK|RTO_ONLINK;
+       tos &= IPTOS_RT_MASK|RTO_ONLINK;
        key.dst = daddr;
        key.src = saddr;
-       key.tos = tos&IPTOS_TOS_MASK;
+       key.tos = tos&IPTOS_RT_MASK;
        key.iif = loopback_dev.ifindex;
        key.oif = oif;
        key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
@@ -1889,7+1896,7 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
                    rth->key.src == saddr &&
                    rth->key.iif == 0 &&
                    rth->key.oif == oif &&
-                   !((rth->key.tos^tos)&(IPTOS_TOS_MASK|RTO_ONLINK)) &&
+                   !((rth->key.tos^tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
                    ((tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
                ) {
                        rth->u.dst.lastuse = jiffies;
index c4343b7..dbf6802 100644 (file)
@@ -5,7+5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.169 2000/04/20 14:41:16 davem Exp $
+ * Version:    $Id: tcp.c,v 1.170 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1018,9+1018,13 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size)
                        tcp_send_skb(sk, skb, queue_it, mss_now);
                }
        }
-       sk->err = 0;
        err = copied;
-       goto out;
+out:
+       __tcp_push_pending_frames(sk, tp, mss_now);
+       TCP_CHECK_TIMER(sk);
+out_unlock:
+       release_sock(sk);
+       return err;
 
 do_sock_err:
        if(copied)
@@ -1048,12+1052,7 @@ do_fault:
        kfree_skb(skb);
 do_fault2:
        err = -EFAULT;
-out:
-       __tcp_push_pending_frames(sk, tp, mss_now);
-       TCP_CHECK_TIMER(sk);
-out_unlock:
-       release_sock(sk);
-       return err;
+       goto out;
 }
 
 #undef PSH_NEEDED
@@ -1270,10+1269,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
 
        TCP_CHECK_TIMER(sk);
 
-
-       if (sk->err)
-               goto out_err;
-
        err = -ENOTCONN;
        if (sk->state == TCP_LISTEN)
                goto out;
@@ -1292,13+1287,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
 
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
 
-       /*
-        *      BUG BUG BUG
-        *      This violates 1003.1g compliance. We must wait for 
-        *      data to exist even if we read none!
-        */
-        
-       while (len > 0) {
+       do {
                struct sk_buff * skb;
                u32 offset;
 
@@ -1519,29+1508,6 @@ do_prequeue:
                        continue;
                skb->used = 1;
                tcp_eat_skb(sk, skb);
-
-#ifdef TCP_LESS_COARSE_ACKS
-               /* Possible improvement. When sender is faster than receiver,
-                * traffic looks like: fill window ... wait for window open ...
-                * fill window. We lose at least one rtt, because call
-                * cleanup_rbuf only once. Probably, if "len" was large
-                * we should insert several intermediate cleanup_rbuf(s).
-                *
-                * F.e.:
-                */
-               do {
-                       u32 full_space = min(tp->window_clamp, tcp_full_space(sk));
-
-                       /* Try to ACK, if total buffer length is larger
-                          than maximal window and if rcv_window has
-                          chances to increase twice. It will result
-                          to exponentially decreased ACKing during
-                          read to huge (usually, mmapped) buffer.
-                        */
-                       if (len >= full_space && tp->rcv_wnd <= full_space/2)
-                               cleanup_rbuf(sk, copied);
-               } while (0);
-#endif
                continue;
 
        found_fin_ok:
@@ -1552,7+1518,7 @@ do_prequeue:
                /* All is done. */
                skb->used = 1;
                break;
-       }
+       } while (len > 0);
 
        if (user_recv) {
                if (skb_queue_len(&tp->ucopy.prequeue)) {
@@ -1584,9+1550,6 @@ do_prequeue:
        release_sock(sk);
        return copied;
 
-out_err:
-       err = sock_error(sk);
-
 out:
        TCP_CHECK_TIMER(sk);
        release_sock(sk);
@@ -2012,7+1975,6 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
        struct open_request *req;
        struct sock *newsk;
        int error;
-       long timeo;
 
        lock_sock(sk); 
 
@@ -2023,10+1985,10 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
        if (sk->state != TCP_LISTEN)
                goto out;
 
-       timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-
        /* Find already established connection */
        if (!tp->accept_queue) {
+               long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
+
                /* If this is a non blocking socket don't sleep */
                error = -EAGAIN;
                if (!timeo)
@@ -2099,6+2061,8 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval,
                        break;
                }
                tp->nonagle = (val == 0) ? 0 : 1;
+               if (val)
+                       tcp_push_pending_frames(sk, tp);
                break;
 
        case TCP_CORK:
index a14c984..dec2a61 100644 (file)
@@ -5,7+5,7 @@
  *
  *             The User Datagram Protocol (UDP).
  *
- * Version:    $Id: udp.c,v 1.83 2000/06/09 07:35:49 davem Exp $
+ * Version:    $Id: udp.c,v 1.84 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -710,7+710,8 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
 
        if (err)
                goto out_free;
-       sk->stamp=skb->stamp;
+
+       sock_recv_timestamp(msg, sk, skb);
 
        /* Copy the address. */
        if (sin)
index 844ea82..986cd02 100644 (file)
@@ -5,7+5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: datagram.c,v 1.19 2000/02/27 19:51:47 davem Exp $
+ *     $Id: datagram.c,v 1.20 2000/07/08 00:20:43 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -127,6+127,8 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
        if (err)
                goto out_free_skb;
 
+       sock_recv_timestamp(msg, sk, skb);
+
        serr = SKB_EXT_ERR(skb);
 
        sin = (struct sockaddr_in6 *)msg->msg_name;
index 22c1fa3..944d665 100644 (file)
@@ -7,7+7,7 @@
  *             PROC file system.  This is very similar to the IPv4 version,
  *             except it reports the sockets in the INET6 address family.
  *
- * Version:    $Id: proc.c,v 1.14 2000/04/16 01:11:37 davem Exp $
+ * Version:    $Id: proc.c,v 1.15 2000/07/07 22:29:42 davem Exp $
  *
  * Authors:    David S. Miller (davem@caip.rutgers.edu)
  *
@@ -46,6+46,8 @@ int afinet6_get_info(char *buffer, char **start, off_t offset, int length, int d
                       fold_prot_inuse(&udpv6_prot));
        len += sprintf(buffer+len, "RAW6: inuse %d\n",
                       fold_prot_inuse(&rawv6_prot));
+       len += sprintf(buffer+len, "FRAG6: inuse %d memory %d\n",
+                      ip6_frag_nqueues, atomic_read(&ip6_frag_mem));
        *start = buffer + offset;
        len -= offset;
        if(len > length)
index 3f2ec70..e838704 100644 (file)
@@ -7,7+7,7 @@
  *
  *     Adapted from linux/net/ipv4/raw.c
  *
- *     $Id: raw.c,v 1.36 2000/05/03 06:37:07 davem Exp $
+ *     $Id: raw.c,v 1.39 2000/07/08 00:20:43 davem Exp $
  *
  *     Fixes:
  *     Hideaki YOSHIFUJI       :       sin6_scope_id support
@@ -331,7+331,6 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        }
 
        err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-       sk->stamp=skb->stamp;
        if (err)
                goto out_free;
 
@@ -348,6+347,8 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                }
        }
 
+       sock_recv_timestamp(msg, sk, skb);
+
        if (sk->net_pinfo.af_inet6.rxopt.all)
                datagram_recv_ctl(sk, msg, skb);
        err = copied;
@@ -535,6+536,8 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len)
 
        fl.proto = proto;
        fl.fl6_dst = daddr;
+       if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr))
+               fl.fl6_src = &np->saddr;
        fl.uli_u.icmpt.type = 0;
        fl.uli_u.icmpt.code = 0;
        
@@ -694,6+697,31 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
        return 0;
 }
 
+static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+       switch(cmd) {
+               case SIOCOUTQ:
+               {
+                       int amount = atomic_read(&sk->wmem_alloc);
+                       return put_user(amount, (int *)arg);
+               }
+               case SIOCINQ:
+               {
+                       struct sk_buff *skb;
+                       int amount = 0;
+
+                       spin_lock_irq(&sk->receive_queue.lock);
+                       skb = skb_peek(&sk->receive_queue);
+                       if (skb != NULL)
+                               amount = skb->tail - skb->h.raw;
+                       spin_unlock_irq(&sk->receive_queue.lock);
+                       return put_user(amount, (int *)arg);
+               }
+
+               default:
+                       return -ENOIOCTLCMD;
+       }
+}
 
 static void rawv6_close(struct sock *sk, long timeout)
 {
@@ -790,6+818,7 @@ struct proto rawv6_prot = {
        close:          rawv6_close,
        connect:        udpv6_connect,
        disconnect:     udp_disconnect,
+       ioctl:          rawv6_ioctl,
        init:           rawv6_init_sk,
        destroy:        inet6_destroy_sock,
        setsockopt:     rawv6_setsockopt,
dissimilarity index 60%
index 99f4a70..abdcdc7 100644 (file)
-/*
- *     IPv6 fragment reassembly
- *     Linux INET6 implementation 
- *
- *     Authors:
- *     Pedro Roque             <roque@di.fc.ul.pt>     
- *
- *     $Id: reassembly.c,v 1.17 2000/05/03 06:37:07 davem Exp $
- *
- *     Based on: net/ipv4/ip_fragment.c
- *
- *     This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-
-/* 
- *     Fixes:  
- *     Andi Kleen      Make it work with multiple hosts.
- *                     More RFC compliance.
- *
- *      Horst von Brand Add missing #include <linux/string.h>
- */
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/sched.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/in6.h>
-#include <linux/ipv6.h>
-#include <linux/icmpv6.h>
-
-#include <net/sock.h>
-#include <net/snmp.h>
-
-#include <net/ipv6.h>
-#include <net/protocol.h>
-#include <net/transp_v6.h>
-#include <net/rawv6.h>
-#include <net/ndisc.h>
-#include <net/addrconf.h>
-
-int sysctl_ip6frag_high_thresh = 256*1024;
-int sysctl_ip6frag_low_thresh = 192*1024;
-int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT;
-
-atomic_t ip6_frag_mem = ATOMIC_INIT(0);
-
-static spinlock_t ip6_frag_lock = SPIN_LOCK_UNLOCKED;
-
-struct ipv6_frag {
-       __u16                   offset;
-       __u16                   len;
-       struct sk_buff          *skb;
-
-       struct frag_hdr         *fhdr;
-
-       struct ipv6_frag        *next;
-};
-
-/*
- *     Equivalent of ipv4 struct ipq
- */
-
-struct frag_queue {
-
-       struct frag_queue       *next;
-       struct frag_queue       *prev;
-
-       __u32                   id;             /* fragment id          */
-       struct in6_addr         saddr;
-       struct in6_addr         daddr;
-       struct timer_list       timer;          /* expire timer         */
-       struct ipv6_frag        *fragments;
-       struct net_device               *dev;
-       int                     iif;
-       __u8                    last_in;        /* has first/last segment arrived? */
-#define FIRST_IN               2
-#define LAST_IN                        1
-       __u8                    nexthdr;
-       __u16                   nhoffset;
-};
-
-static struct frag_queue ipv6_frag_queue = {
-       &ipv6_frag_queue, &ipv6_frag_queue,
-};
-
-/* Memory Tracking Functions. */
-extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
-{
-       atomic_sub(skb->truesize, &ip6_frag_mem);
-       kfree_skb(skb);
-}
-
-extern __inline__ void frag_kfree_s(void *ptr, int len)
-{
-       atomic_sub(len, &ip6_frag_mem);
-       kfree(ptr);
-}
-extern __inline__ void *frag_kmalloc(int size, int pri)
-{
-       void *vp = kmalloc(size, pri);
-
-       if(!vp)
-               return NULL;
-       atomic_add(size, &ip6_frag_mem);
-       return vp;
-}
-
-
-static void                    create_frag_entry(struct sk_buff *skb, 
-                                                 __u8 *nhptr,
-                                                 struct frag_hdr *fhdr);
-static u8 *                    reasm_frag(struct frag_queue *fq, 
-                                          struct sk_buff **skb_in);
-
-static void                    reasm_queue(struct frag_queue *fq, 
-                                           struct sk_buff *skb, 
-                                           struct frag_hdr *fhdr,
-                                           u8 *nhptr);
-
-static void                    fq_free(struct frag_queue *fq);
-
-static void frag_prune(void)
-{
-       struct frag_queue *fq;
-
-       spin_lock(&ip6_frag_lock);
-       while ((fq = ipv6_frag_queue.next) != &ipv6_frag_queue) {
-               IP6_INC_STATS_BH(Ip6ReasmFails);
-               fq_free(fq);
-               if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) {
-                       spin_unlock(&ip6_frag_lock);
-                       return;
-               }
-       }
-       if (atomic_read(&ip6_frag_mem))
-               printk(KERN_DEBUG "IPv6 frag_prune: memleak\n");
-       atomic_set(&ip6_frag_mem, 0);
-       spin_unlock(&ip6_frag_lock);
-}
-
-
-u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
-{
-       struct sk_buff *skb = *skbp; 
-       struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
-       struct frag_queue *fq;
-       struct ipv6hdr *hdr;
-
-       hdr = skb->nh.ipv6h;
-
-       IP6_INC_STATS_BH(Ip6ReasmReqds);
-
-       /* Jumbo payload inhibits frag. header */
-       if (hdr->payload_len==0) {
-               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
-               return NULL;
-       }
-       if ((u8 *)(fhdr+1) > skb->tail) {
-               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
-               return NULL;
-       }
-       if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
-               frag_prune();
-
-       spin_lock(&ip6_frag_lock);
-       for (fq = ipv6_frag_queue.next; fq != &ipv6_frag_queue; fq = fq->next) {
-               if (fq->id == fhdr->identification && 
-                   !ipv6_addr_cmp(&hdr->saddr, &fq->saddr) &&
-                   !ipv6_addr_cmp(&hdr->daddr, &fq->daddr)) {
-                       u8 *ret = NULL;
-
-                       reasm_queue(fq, skb, fhdr, nhptr);
-
-                       if (fq->last_in == (FIRST_IN|LAST_IN))
-                               ret = reasm_frag(fq, skbp);
-
-                       spin_unlock(&ip6_frag_lock);
-                       return ret;
-               }
-       }
-
-       create_frag_entry(skb, nhptr, fhdr);
-       spin_unlock(&ip6_frag_lock);
-
-       return NULL;
-}
-
-
-static void fq_free(struct frag_queue *fq)
-{
-       struct ipv6_frag *fp, *back;
-
-       del_timer(&fq->timer);
-
-       for (fp = fq->fragments; fp; ) {
-               frag_kfree_skb(fp->skb);
-               back = fp;
-               fp=fp->next;
-               frag_kfree_s(back, sizeof(*back));
-       }
-
-       fq->prev->next = fq->next;
-       fq->next->prev = fq->prev;
-
-       fq->prev = fq->next = NULL;
-       
-       frag_kfree_s(fq, sizeof(*fq));
-}
-
-static void frag_expire(unsigned long data)
-{
-       struct frag_queue *fq;
-       struct ipv6_frag *frag;
-
-       fq = (struct frag_queue *) data;
-
-       spin_lock(&ip6_frag_lock);
-
-       frag = fq->fragments;
-
-       IP6_INC_STATS_BH(Ip6ReasmTimeout);
-       IP6_INC_STATS_BH(Ip6ReasmFails);
-
-       if (frag == NULL) {
-               spin_unlock(&ip6_frag_lock);
-               printk(KERN_DEBUG "invalid fragment queue\n");
-               return;
-       }
-
-       /* Send error only if the first segment arrived.
-          (fixed --ANK (980728))
-        */
-       if (fq->last_in&FIRST_IN) {
-               struct net_device *dev = dev_get_by_index(fq->iif);
-
-               /*
-                  But use as source device on which LAST ARRIVED
-                  segment was received. And do not use fq->dev
-                  pointer directly, device might already disappeared.
-                */
-               if (dev) {
-                       frag->skb->dev = dev;
-                       icmpv6_send(frag->skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
-                                   dev);
-                       dev_put(dev);
-               }
-       }
-       
-       fq_free(fq);
-       spin_unlock(&ip6_frag_lock);
-}
-
-
-static void create_frag_entry(struct sk_buff *skb,
-                             __u8 *nhptr,
-                             struct frag_hdr *fhdr)
-{
-       struct frag_queue *fq;
-       struct ipv6hdr *hdr; 
-
-       fq = (struct frag_queue *) frag_kmalloc(sizeof(struct frag_queue), 
-                                               GFP_ATOMIC);
-
-       if (fq == NULL) {
-               IP6_INC_STATS_BH(Ip6ReasmFails);
-               kfree_skb(skb);
-               return;
-       }
-
-       memset(fq, 0, sizeof(struct frag_queue));
-
-       fq->id = fhdr->identification;
-
-       hdr = skb->nh.ipv6h;
-       ipv6_addr_copy(&fq->saddr, &hdr->saddr);
-       ipv6_addr_copy(&fq->daddr, &hdr->daddr);
-
-       /* init_timer has been done by the memset */
-       fq->timer.function = frag_expire;
-       fq->timer.data = (long) fq;
-       fq->timer.expires = jiffies + sysctl_ip6frag_time;
-
-       reasm_queue(fq, skb, fhdr, nhptr);
-
-       if (fq->fragments) {
-               fq->prev = ipv6_frag_queue.prev;
-               fq->next = &ipv6_frag_queue;
-               fq->prev->next = fq;
-               ipv6_frag_queue.prev = fq;
-
-               add_timer(&fq->timer);
-       } else
-               frag_kfree_s(fq, sizeof(*fq));
-}
-
-
-/*
- *     We queue the packet even if it's the last.
- *     It's a trade off. This allows the reassembly 
- *     code to be simpler (=faster) and of the
- *     steps we do for queueing the only unnecessary 
- *     one it's the kmalloc for a struct ipv6_frag.
- *     Feel free to try other alternatives...
- */
-
-static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb, 
-                                    struct frag_hdr *fhdr, u8 *nhptr)
-{
-       struct ipv6_frag *nfp, *fp, **bptr;
-
-       nfp = (struct ipv6_frag *) frag_kmalloc(sizeof(struct ipv6_frag), 
-                                               GFP_ATOMIC);
-
-       if (nfp == NULL) {              
-               kfree_skb(skb);
-               return;
-       }
-
-       nfp->offset = ntohs(fhdr->frag_off) & ~0x7;
-       nfp->len = (ntohs(skb->nh.ipv6h->payload_len) -
-                   ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
-
-       if ((u32)nfp->offset + (u32)nfp->len >= 65536) {
-               icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off); 
-               goto err;
-       }
-       if (fhdr->frag_off & __constant_htons(0x0001)) {
-               /* Check if the fragment is rounded to 8 bytes.
-                * Required by the RFC.
-                * ... and would break our defragmentation algorithm 8)
-                */
-               if (nfp->len & 0x7) {
-                       printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
-
-                       /*
-                          It is not in specs, but I see no reasons
-                          to send an error in this case. --ANK
-                        */
-                       if (nfp->offset == 0)
-                               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 
-                                                 &skb->nh.ipv6h->payload_len);
-                       goto err;
-               }
-       }
-
-       nfp->skb  = skb;
-       nfp->fhdr = fhdr;
-       nfp->next = NULL;
-
-       bptr = &fq->fragments;
-
-       for (fp = fq->fragments; fp; fp=fp->next) {
-               if (nfp->offset <= fp->offset)
-                       break;
-               bptr = &fp->next;
-       }
-       if (fp && fp->offset == nfp->offset) {
-               if (nfp->len != fp->len) {
-                       printk(KERN_DEBUG "reasm_queue: dup with wrong len\n");
-               }
-
-               /* duplicate. discard it. */
-               goto err;
-       }
-
-       atomic_add(skb->truesize, &ip6_frag_mem);
-
-       /* All the checks are done, fragment is acepted.
-          Only now we are allowed to update reassembly data!
-          (fixed --ANK (980728))
-        */
-
-       /* iif always set to one of the last arrived segment */
-       fq->dev = skb->dev;
-       fq->iif = skb->dev->ifindex;
-
-       /* Last fragment */
-       if ((fhdr->frag_off & __constant_htons(0x0001)) == 0)
-               fq->last_in |= LAST_IN;
-
-       /* First fragment.
-          nexthdr and nhptr are get from the first fragment.
-          Moreover, nexthdr is UNDEFINED for all the fragments but the
-          first one.
-          (fixed --ANK (980728))
-        */
-       if (nfp->offset == 0) {
-               fq->nexthdr = fhdr->nexthdr;
-               fq->last_in |= FIRST_IN;
-               fq->nhoffset = nhptr - skb->nh.raw;
-       }
-
-       *bptr = nfp;
-       nfp->next = fp;
-       return;
-
-err:
-       frag_kfree_s(nfp, sizeof(*nfp));
-       kfree_skb(skb);
-}
-
-/*
- *     check if this fragment completes the packet
- *     returns true on success
- */
-static u8* reasm_frag(struct frag_queue *fq, struct sk_buff **skb_in)
-{
-       struct ipv6_frag *fp;
-       struct ipv6_frag *head = fq->fragments;
-       struct ipv6_frag *tail = NULL;
-       struct sk_buff *skb;
-       __u32  offset = 0;
-       __u32  payload_len;
-       __u16  unfrag_len;
-       __u16  copy;
-       u8     *nhptr;
-
-       for(fp = head; fp; fp=fp->next) {
-               if (offset != fp->offset)
-                       return NULL;
-
-               offset += fp->len;
-               tail = fp;
-       }
-
-       /* 
-        * we know the m_flag arrived and we have a queue,
-        * starting from 0, without gaps.
-        * this means we have all fragments.
-        */
-
-       /* Unfragmented part is taken from the first segment.
-          (fixed --ANK (980728))
-        */
-       unfrag_len = (u8 *) (head->fhdr) - (u8 *) (head->skb->nh.ipv6h + 1);
-
-       payload_len = (unfrag_len + tail->offset + 
-                      (tail->skb->tail - (__u8 *) (tail->fhdr + 1)));
-
-       if (payload_len > 65535) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "reasm_frag: payload len = %d\n", payload_len);
-               IP6_INC_STATS_BH(Ip6ReasmFails);
-               fq_free(fq);
-               return NULL;
-       }
-
-       if ((skb = dev_alloc_skb(sizeof(struct ipv6hdr) + payload_len))==NULL) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "reasm_frag: no memory for reassembly\n");
-               IP6_INC_STATS_BH(Ip6ReasmFails);
-               fq_free(fq);
-               return NULL;
-       }
-
-       copy = unfrag_len + sizeof(struct ipv6hdr);
-
-       skb->nh.ipv6h = (struct ipv6hdr *) skb->data;
-       skb->dev = fq->dev;
-       skb->protocol = __constant_htons(ETH_P_IPV6);
-       skb->pkt_type = head->skb->pkt_type;
-       memcpy(skb->cb, head->skb->cb, sizeof(skb->cb));
-       skb->dst = dst_clone(head->skb->dst);
-
-       memcpy(skb_put(skb, copy), head->skb->nh.ipv6h, copy);
-       nhptr = skb->nh.raw + fq->nhoffset;
-       *nhptr = fq->nexthdr;
-
-       skb->h.raw = skb->tail;
-
-       skb->nh.ipv6h->payload_len = ntohs(payload_len);
-
-       *skb_in = skb;
-
-       /*
-        *      FIXME: If we don't have a checksum we ought to be able
-        *      to defragment and checksum in this pass. [AC]
-        *      Note that we don't really know yet whether the protocol
-        *      needs checksums at all. It might still be a good idea. -AK
-        */
-       for(fp = fq->fragments; fp; ) {
-               struct ipv6_frag *back;
-
-               memcpy(skb_put(skb, fp->len), (__u8*)(fp->fhdr + 1), fp->len);
-               frag_kfree_skb(fp->skb);
-               back = fp;
-               fp=fp->next;
-               frag_kfree_s(back, sizeof(*back));
-       }
-
-       del_timer(&fq->timer);
-       fq->prev->next = fq->next;
-       fq->next->prev = fq->prev;
-       fq->prev = fq->next = NULL;
-
-       frag_kfree_s(fq, sizeof(*fq));
-
-       IP6_INC_STATS_BH(Ip6ReasmOKs);
-       return nhptr;
-}
+/*
+ *     IPv6 fragment reassembly
+ *     Linux INET6 implementation 
+ *
+ *     Authors:
+ *     Pedro Roque             <roque@di.fc.ul.pt>     
+ *
+ *     $Id: reassembly.c,v 1.18 2000/07/07 22:29:42 davem Exp $
+ *
+ *     Based on: net/ipv4/ip_fragment.c
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+/* 
+ *     Fixes:  
+ *     Andi Kleen      Make it work with multiple hosts.
+ *                     More RFC compliance.
+ *
+ *      Horst von Brand Add missing #include <linux/string.h>
+ *     Alexey Kuznetsov        SMP races, threading, cleanup.
+ */
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/sched.h>
+#include <linux/net.h>
+#include <linux/netdevice.h>
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+
+#include <net/sock.h>
+#include <net/snmp.h>
+
+#include <net/ipv6.h>
+#include <net/protocol.h>
+#include <net/transp_v6.h>
+#include <net/rawv6.h>
+#include <net/ndisc.h>
+#include <net/addrconf.h>
+
+int sysctl_ip6frag_high_thresh = 256*1024;
+int sysctl_ip6frag_low_thresh = 192*1024;
+
+int sysctl_ip6frag_time = IPV6_FRAG_TIMEOUT;
+
+struct ip6frag_skb_cb
+{
+       struct inet6_skb_parm   h;
+       int                     offset;
+};
+
+#define FRAG6_CB(skb)  ((struct ip6frag_skb_cb*)((skb)->cb))
+
+
+/*
+ *     Equivalent of ipv4 struct ipq
+ */
+
+struct frag_queue
+{
+       struct frag_queue       *next;
+
+       __u32                   id;             /* fragment id          */
+       struct in6_addr         saddr;
+       struct in6_addr         daddr;
+
+       spinlock_t              lock;
+       atomic_t                refcnt;
+       struct timer_list       timer;          /* expire timer         */
+       struct sk_buff          *fragments;
+       int                     len;
+       int                     meat;
+       struct net_device       *dev;
+       int                     iif;
+       __u8                    last_in;        /* has first/last segment arrived? */
+#define COMPLETE               4
+#define FIRST_IN               2
+#define LAST_IN                        1
+       __u8                    nexthdr;
+       __u16                   nhoffset;
+       struct frag_queue       **pprev;
+};
+
+/* Hash table. */
+
+#define IP6Q_HASHSZ    64
+
+static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
+static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
+int ip6_frag_nqueues = 0;
+
+static __inline__ void __fq_unlink(struct frag_queue *fq)
+{
+       if(fq->next)
+               fq->next->pprev = fq->pprev;
+       *fq->pprev = fq->next;
+       ip6_frag_nqueues--;
+}
+
+static __inline__ void fq_unlink(struct frag_queue *fq)
+{
+       write_lock(&ip6_frag_lock);
+       __fq_unlink(fq);
+       write_unlock(&ip6_frag_lock);
+}
+
+static __inline__ unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
+                                         struct in6_addr *daddr)
+{
+       unsigned int h = saddr->s6_addr32[3] ^ daddr->s6_addr32[3] ^ id;
+
+       h ^= (h>>16);
+       h ^= (h>>8);
+       return h & (IP6Q_HASHSZ - 1);
+}
+
+
+atomic_t ip6_frag_mem = ATOMIC_INIT(0);
+
+/* Memory Tracking Functions. */
+extern __inline__ void frag_kfree_skb(struct sk_buff *skb)
+{
+       atomic_sub(skb->truesize, &ip6_frag_mem);
+       kfree_skb(skb);
+}
+
+extern __inline__ void frag_free_queue(struct frag_queue *fq)
+{
+       atomic_sub(sizeof(struct frag_queue), &ip6_frag_mem);
+       kfree(fq);
+}
+
+extern __inline__ struct frag_queue *frag_alloc_queue(void)
+{
+       struct frag_queue *fq = kmalloc(sizeof(struct frag_queue), GFP_ATOMIC);
+
+       if(!fq)
+               return NULL;
+       atomic_add(sizeof(struct frag_queue), &ip6_frag_mem);
+       return fq;
+}
+
+/* Destruction primitives. */
+
+/* Complete destruction of fq. */
+static void ip6_frag_destroy(struct frag_queue *fq)
+{
+       struct sk_buff *fp;
+
+       BUG_TRAP(fq->last_in&COMPLETE);
+       BUG_TRAP(del_timer(&fq->timer) == 0);
+
+       /* Release all fragment data. */
+       fp = fq->fragments;
+       while (fp) {
+               struct sk_buff *xp = fp->next;
+
+               frag_kfree_skb(fp);
+               fp = xp;
+       }
+
+       frag_free_queue(fq);
+}
+
+static __inline__ void fq_put(struct frag_queue *fq)
+{
+       if (atomic_dec_and_test(&fq->refcnt))
+               ip6_frag_destroy(fq);
+}
+
+/* Kill fq entry. It is not destroyed immediately,
+ * because caller (and someone more) holds reference count.
+ */
+static __inline__ void fq_kill(struct frag_queue *fq)
+{
+       if (del_timer(&fq->timer))
+               atomic_dec(&fq->refcnt);
+
+       if (!(fq->last_in & COMPLETE)) {
+               fq_unlink(fq);
+               atomic_dec(&fq->refcnt);
+               fq->last_in |= COMPLETE;
+       }
+}
+
+static void ip6_evictor(void)
+{
+       int i, progress;
+
+       do {
+               if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh)
+                       return;
+               progress = 0;
+               for (i = 0; i < IP6Q_HASHSZ; i++) {
+                       struct frag_queue *fq;
+                       if (ip6_frag_hash[i] == NULL)
+                               continue;
+
+                       write_lock(&ip6_frag_lock);
+                       if ((fq = ip6_frag_hash[i]) != NULL) {
+                               /* find the oldest queue for this hash bucket */
+                               while (fq->next)
+                                       fq = fq->next;
+                               __fq_unlink(fq);
+                               write_unlock(&ip6_frag_lock);
+
+                               spin_lock(&fq->lock);
+                               if (del_timer(&fq->timer))
+                                       atomic_dec(&fq->refcnt);
+                               fq->last_in |= COMPLETE;
+                               spin_unlock(&fq->lock);
+
+                               fq_put(fq);
+                               IP6_INC_STATS_BH(Ip6ReasmFails);
+                               progress = 1;
+                               continue;
+                       }
+                       write_unlock(&ip6_frag_lock);
+               }
+       } while (progress);
+}
+
+static void ip6_frag_expire(unsigned long data)
+{
+       struct frag_queue *fq = (struct frag_queue *) data;
+
+       spin_lock(&fq->lock);
+
+       if (fq->last_in & COMPLETE)
+               goto out;
+
+       fq_kill(fq);
+
+       IP6_INC_STATS_BH(Ip6ReasmTimeout);
+       IP6_INC_STATS_BH(Ip6ReasmFails);
+
+       /* Send error only if the first segment arrived. */
+       if (fq->last_in&FIRST_IN && fq->fragments) {
+               struct net_device *dev = dev_get_by_index(fq->iif);
+
+               /*
+                  But use as source device on which LAST ARRIVED
+                  segment was received. And do not use fq->dev
+                  pointer directly, device might already disappeared.
+                */
+               if (dev) {
+                       fq->fragments->dev = dev;
+                       icmpv6_send(fq->fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0,
+                                   dev);
+                       dev_put(dev);
+               }
+       }
+out:
+       spin_unlock(&fq->lock);
+       fq_put(fq);
+}
+
+/* Creation primitives. */
+
+
+static struct frag_queue *ip6_frag_intern(unsigned int hash,
+                                         struct frag_queue *fq_in)
+{
+       struct frag_queue *fq;
+
+       write_lock(&ip6_frag_lock);
+#ifdef CONFIG_SMP
+       for (fq = ip6_frag_hash[hash]; fq; fq = fq->next) {
+               if (fq->id == fq_in->id && 
+                   !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) &&
+                   !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) {
+                       atomic_inc(&fq->refcnt);
+                       write_unlock(&ip6_frag_lock);
+                       fq_in->last_in |= COMPLETE;
+                       fq_put(fq_in);
+                       return fq;
+               }
+       }
+#endif
+       fq = fq_in;
+
+       atomic_inc(&fq->refcnt);
+       if((fq->next = ip6_frag_hash[hash]) != NULL)
+               fq->next->pprev = &fq->next;
+       ip6_frag_hash[hash] = fq;
+       fq->pprev = &ip6_frag_hash[hash];
+       ip6_frag_nqueues++;
+       write_unlock(&ip6_frag_lock);
+       return fq;
+}
+
+
+static struct frag_queue *
+ip6_frag_create(unsigned int hash, u32 id, struct in6_addr *src, struct in6_addr *dst)
+{
+       struct frag_queue *fq;
+
+       if ((fq = frag_alloc_queue()) == NULL)
+               goto oom;
+
+       memset(fq, 0, sizeof(struct frag_queue));
+
+       fq->id = id;
+       ipv6_addr_copy(&fq->saddr, src);
+       ipv6_addr_copy(&fq->daddr, dst);
+
+       /* init_timer has been done by the memset */
+       fq->timer.function = ip6_frag_expire;
+       fq->timer.data = (long) fq;
+       fq->lock = SPIN_LOCK_UNLOCKED;
+       atomic_set(&fq->refcnt, 1);
+
+       return ip6_frag_intern(hash, fq);
+
+oom:
+       IP6_INC_STATS_BH(Ip6ReasmFails);
+       return NULL;
+}
+
+static __inline__ struct frag_queue *
+fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst)
+{
+       struct frag_queue *fq;
+       unsigned int hash = ip6qhashfn(id, src, dst);
+
+       read_lock(&ip6_frag_lock);
+       for(fq = ip6_frag_hash[hash]; fq; fq = fq->next) {
+               if (fq->id == id && 
+                   !ipv6_addr_cmp(src, &fq->saddr) &&
+                   !ipv6_addr_cmp(dst, &fq->daddr)) {
+                       atomic_inc(&fq->refcnt);
+                       read_unlock(&ip6_frag_lock);
+                       return fq;
+               }
+       }
+       read_unlock(&ip6_frag_lock);
+
+       return ip6_frag_create(hash, id, src, dst);
+}
+
+
+static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, 
+                          struct frag_hdr *fhdr, u8 *nhptr)
+{
+       struct sk_buff *prev, *next;
+       int offset, end;
+
+       if (fq->last_in & COMPLETE)
+               goto err;
+
+       if (!mod_timer(&fq->timer, jiffies + sysctl_ip6frag_time))
+               atomic_inc(&fq->refcnt);
+
+       offset = ntohs(fhdr->frag_off) & ~0x7;
+       end = offset + (ntohs(skb->nh.ipv6h->payload_len) -
+                       ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1)));
+
+       if ((unsigned int)end >= 65536) {
+               icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off); 
+               goto err;
+       }
+
+       /* Is this the final fragment? */
+       if (!(fhdr->frag_off & __constant_htons(0x0001))) {
+               /* If we already have some bits beyond end
+                * or have different end, the segment is corrupted.
+                */
+               if (end < fq->len ||
+                   ((fq->last_in & LAST_IN) && end != fq->len))
+                       goto err;
+               fq->last_in |= LAST_IN;
+               fq->len = end;
+       } else {
+               /* Check if the fragment is rounded to 8 bytes.
+                * Required by the RFC.
+                */
+               if (end & 0x7) {
+                       printk(KERN_DEBUG "fragment not rounded to 8bytes\n");
+
+                       /*
+                          It is not in specs, but I see no reasons
+                          to send an error in this case. --ANK
+                        */
+                       if (offset == 0)
+                               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, 
+                                                 &skb->nh.ipv6h->payload_len);
+                       goto err;
+               }
+               if (end > fq->len) {
+                       /* Some bits beyond end -> corruption. */
+                       if (fq->last_in & LAST_IN)
+                               goto err;
+                       fq->len = end;
+               }
+       }
+
+       if (end == offset)
+               goto err;
+
+       /* Point into the IP datagram 'data' part. */
+       skb_pull(skb, (u8 *) (fhdr + 1) - skb->data);
+       skb_trim(skb, end - offset);
+
+       /* Find out which fragments are in front and at the back of us
+        * in the chain of fragments so far.  We must know where to put
+        * this fragment, right?
+        */
+       prev = NULL;
+       for(next = fq->fragments; next != NULL; next = next->next) {
+               if (FRAG6_CB(next)->offset >= offset)
+                       break;  /* bingo! */
+               prev = next;
+       }
+
+       /* We found where to put this one.  Check for overlap with
+        * preceding fragment, and, if needed, align things so that
+        * any overlaps are eliminated.
+        */
+       if (prev) {
+               int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
+
+               if (i > 0) {
+                       offset += i;
+                       if (end <= offset)
+                               goto err;
+                       skb_pull(skb, i);
+               }
+       }
+
+       /* Look for overlap with succeeding segments.
+        * If we can merge fragments, do it.
+        */
+       while (next && FRAG6_CB(next)->offset < end) {
+               int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
+
+               if (i < next->len) {
+                       /* Eat head of the next overlapped fragment
+                        * and leave the loop. The next ones cannot overlap.
+                        */
+                       FRAG6_CB(next)->offset += i;    /* next fragment */
+                       skb_pull(next, i);
+                       fq->meat -= i;
+                       break;
+               } else {
+                       struct sk_buff *free_it = next;
+
+                       /* Old fragmnet is completely overridden with
+                        * new one drop it.
+                        */
+                       next = next->next;
+
+                       if (prev)
+                               prev->next = next;
+                       else
+                               fq->fragments = next;
+
+                       fq->meat -= free_it->len;
+                       frag_kfree_skb(free_it);
+               }
+       }
+
+       FRAG6_CB(skb)->offset = offset;
+
+       /* Insert this fragment in the chain of fragments. */
+       skb->next = next;
+       if (prev)
+               prev->next = skb;
+       else
+               fq->fragments = skb;
+
+       fq->dev = skb->dev;
+       fq->iif = skb->dev->ifindex;
+       fq->meat += skb->len;
+       atomic_add(skb->truesize, &ip6_frag_mem);
+
+       /* First fragment.
+          nexthdr and nhptr are get from the first fragment.
+          Moreover, nexthdr is UNDEFINED for all the fragments but the
+          first one.
+          (fixed --ANK (980728))
+        */
+       if (offset == 0) {
+               fq->nexthdr = fhdr->nexthdr;
+               fq->nhoffset = nhptr - skb->nh.raw;
+               fq->last_in |= FIRST_IN;
+       }
+       return;
+
+err:
+       kfree_skb(skb);
+}
+
+/*
+ *     Check if this packet is complete.
+ *     Returns NULL on failure by any reason, and pointer
+ *     to current nexthdr field in reassembled frame.
+ *
+ *     It is called with locked fq, and caller must check that
+ *     queue is eligible for reassembly i.e. it is not COMPLETE,
+ *     the last and the first frames arrived and all the bits are here.
+ */
+static u8* ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in)
+{
+       struct sk_buff *fp, *head = fq->fragments;
+       struct sk_buff *skb;
+       int    payload_len;
+       int    unfrag_len;
+       int    copy;
+       u8     *nhptr;
+
+       /* 
+        * we know the m_flag arrived and we have a queue,
+        * starting from 0, without gaps.
+        * this means we have all fragments.
+        */
+
+       fq_kill(fq);
+
+       BUG_TRAP(head != NULL);
+       BUG_TRAP(FRAG6_CB(head)->offset == 0);
+
+       /* Unfragmented part is taken from the first segment. */
+       unfrag_len = head->h.raw - (u8 *) (head->nh.ipv6h + 1);
+       payload_len = unfrag_len + fq->len;
+
+       if (payload_len > 65535)
+               goto out_oversize;
+
+       if ((skb = dev_alloc_skb(sizeof(struct ipv6hdr) + payload_len))==NULL)
+               goto out_oom;
+
+       copy = unfrag_len + sizeof(struct ipv6hdr);
+
+       skb->mac.raw = skb->data;
+       skb->nh.ipv6h = (struct ipv6hdr *) skb->data;
+       skb->dev = fq->dev;
+       skb->protocol = __constant_htons(ETH_P_IPV6);
+       skb->pkt_type = head->pkt_type;
+       FRAG6_CB(skb)->h = FRAG6_CB(head)->h;
+       skb->dst = dst_clone(head->dst);
+
+       memcpy(skb_put(skb, copy), head->nh.ipv6h, copy);
+       nhptr = skb->nh.raw + fq->nhoffset;
+       *nhptr = fq->nexthdr;
+
+       skb->h.raw = skb->tail;
+
+       skb->nh.ipv6h->payload_len = ntohs(payload_len);
+
+       *skb_in = skb;
+
+       for (fp = fq->fragments; fp; fp=fp->next)
+               memcpy(skb_put(skb, fp->len), fp->data, fp->len);
+
+       IP6_INC_STATS_BH(Ip6ReasmOKs);
+       return nhptr;
+
+out_oversize:
+       if (net_ratelimit())
+               printk(KERN_DEBUG "ip6_frag_reasm: payload len = %d\n", payload_len);
+       goto out_fail;
+out_oom:
+       if (net_ratelimit())
+               printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
+out_fail:
+       IP6_INC_STATS_BH(Ip6ReasmFails);
+       return NULL;
+}
+
+u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
+{
+       struct sk_buff *skb = *skbp; 
+       struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw);
+       struct frag_queue *fq;
+       struct ipv6hdr *hdr;
+
+       hdr = skb->nh.ipv6h;
+
+       IP6_INC_STATS_BH(Ip6ReasmReqds);
+
+       /* Jumbo payload inhibits frag. header */
+       if (hdr->payload_len==0) {
+               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+               return NULL;
+       }
+       if ((u8 *)(fhdr+1) > skb->tail) {
+               icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw);
+               return NULL;
+       }
+
+       if (!(fhdr->frag_off & __constant_htons(0xFFF9))) {
+               /* It is not a fragmented frame */
+               skb->h.raw += sizeof(struct frag_hdr);
+               IP6_INC_STATS_BH(Ip6ReasmOKs);
+
+               return &fhdr->nexthdr;
+       }
+
+       if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
+               ip6_evictor();
+
+       if ((fq = fq_find(fhdr->identification, &hdr->saddr, &hdr->daddr)) != NULL) {
+               u8 *ret = NULL;
+
+               spin_lock(&fq->lock);
+
+               ip6_frag_queue(fq, skb, fhdr, nhptr);
+
+               if (fq->last_in == (FIRST_IN|LAST_IN) &&
+                   fq->meat == fq->len)
+                       ret = ip6_frag_reasm(fq, skbp);
+
+               spin_unlock(&fq->lock);
+               fq_put(fq);
+               return ret;
+       }
+
+       IP6_INC_STATS_BH(Ip6ReasmFails);
+       kfree_skb(skb);
+       return NULL;
+}
index dc6020c..dc5ddff 100644 (file)
@@ -5,7+5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: route.c,v 1.45 2000/01/16 05:11:38 davem Exp $
+ *     $Id: route.c,v 1.46 2000/07/07 22:40:35 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -769,10+769,12 @@ int ip6_route_add(struct in6_rtmsg *rtmsg)
                goto out;
 
        if (rtmsg->rtmsg_flags & (RTF_GATEWAY|RTF_NONEXTHOP)) {
-               rt->rt6i_nexthop = ndisc_get_neigh(dev, &rt->rt6i_gateway);
-               err = -ENOMEM;
-               if (rt->rt6i_nexthop == NULL)
+               rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+               if (IS_ERR(rt->rt6i_nexthop)) {
+                       err = PTR_ERR(rt->rt6i_nexthop);
+                       rt->rt6i_nexthop = NULL;
                        goto out;
+               }
        }
 
        if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
index 114b59d..c8a631f 100644 (file)
@@ -6,7+6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *     Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
  *
- *     $Id: sit.c,v 1.39 2000/07/07 01:55:20 davem Exp $
+ *     $Id: sit.c,v 1.41 2000/07/07 23:47:45 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
 #include <net/udp.h>
 #include <net/icmp.h>
 #include <net/ipip.h>
+#include <net/inet_ecn.h>
 
 /*
    This version of net/ipv6/sit.c is cloned of net/ipv4/ip_gre.c
@@ -59,7+60,7 @@ static int ipip6_fb_tunnel_init(struct net_device *dev);
 static int ipip6_tunnel_init(struct net_device *dev);
 
 static struct net_device ipip6_fb_tunnel_dev = {
-       "", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip6_fb_tunnel_init,
+       "sit0", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, ipip6_fb_tunnel_init,
 };
 
 static struct ip_tunnel ipip6_fb_tunnel = {
@@ -174,10+175,10 @@ struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create)
        dev->priv = (void*)(dev+1);
        nt = (struct ip_tunnel*)dev->priv;
        nt->dev = dev;
-       strcpy(dev->name, nt->parms.name);
        dev->init = ipip6_tunnel_init;
        dev->new_style = 1;
        memcpy(&nt->parms, parms, sizeof(*parms));
+       strcpy(dev->name, nt->parms.name);
        if (dev->name[0] == 0) {
                int i;
                for (i=1; i<100; i++) {
@@ -370,6+371,13 @@ out:
 #endif
 }
 
+static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+       if (INET_ECN_is_ce(iph->tos) &&
+           INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
+               IP6_ECN_set_ce(skb->nh.ipv6h);
+}
+
 int ipip6_rcv(struct sk_buff *skb, unsigned short len)
 {
        struct iphdr *iph;
@@ -394,6+402,7 @@ int ipip6_rcv(struct sk_buff *skb, unsigned short len)
                nf_conntrack_put(skb->nfct);
                skb->nfct = NULL;
 #endif
+               ipip6_ecn_decapsulate(iph, skb);
                netif_rx(skb);
                read_unlock(&ipip6_lock);
                return 0;
@@ -431,6+440,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        int    mtu;
        struct in6_addr *addr6; 
        int addr_type;
+       int err;
 
        if (tunnel->recursion++) {
                tunnel->stat.collisions++;
@@ -548,7+558,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
                iph->frag_off   =       0;
 
        iph->protocol           =       IPPROTO_IPV6;
-       iph->tos                =       tos;
+       iph->tos                =       INET_ECN_encapsulate(tos, ip6_get_dsfield(iph6));
        iph->daddr              =       rt->rt_dst;
        iph->saddr              =       rt->rt_src;
 
@@ -564,10+574,17 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        skb->nfct = NULL;
 #endif
 
+       err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, 
+               do_ip_send);
+       if(err < 0) {
+               if(net_ratelimit())
+                       printk(KERN_ERR "ipip6_tunnel_xmit: ip_send() failed, err=%d\n", -err);
+               skb = NULL;
+               goto tx_error;
+       }
+
        stats->tx_bytes += skb->len;
        stats->tx_packets++;
-       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-               do_ip_send);
 
        tunnel->recursion--;
        return 0;
@@ -576,7+593,8 @@ tx_error_icmp:
        dst_link_failure(skb);
 tx_error:
        stats->tx_errors++;
-       dev_kfree_skb(skb);
+       if(skb)
+               dev_kfree_skb(skb);
        tunnel->recursion--;
        return 0;
 }
index 4b3bf08..f9f0c0d 100644 (file)
@@ -7,7+7,7 @@
  *
  *     Based on linux/ipv4/udp.c
  *
- *     $Id: udp.c,v 1.53 2000/05/03 06:37:07 davem Exp $
+ *     $Id: udp.c,v 1.55 2000/07/08 00:20:43 davem Exp $
  *
  *     Fixes:
  *     Hideaki YOSHIFUJI       :       sin6_scope_id support
@@ -400,7+400,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        if (err)
                goto out_free;
 
-       sk->stamp=skb->stamp;
+       sock_recv_timestamp(msg, sk, skb);
 
        /* Copy the address. */
        if (msg->msg_name) {
@@ -868,6+868,8 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
 
        fl.proto = IPPROTO_UDP;
        fl.fl6_dst = daddr;
+       if (fl.fl6_src == NULL && !ipv6_addr_any(&np->saddr))
+               fl.fl6_src = &np->saddr;
        fl.uli_u.ports.dport = udh.uh.dest;
        fl.uli_u.ports.sport = udh.uh.source;
 
index e1bfc34..91c7a10 100644 (file)
@@ -69,17+69,6 @@ extern int netdev_finish_unregister(struct net_device *dev);
 
 #include <linux/rtnetlink.h>
 
-#if    defined(CONFIG_ULTRA)   ||      defined(CONFIG_WD80x3)          || \
-       defined(CONFIG_EL2)     ||      defined(CONFIG_NE2000)          || \
-       defined(CONFIG_E2100)   ||      defined(CONFIG_HPLAN_PLUS)      || \
-       defined(CONFIG_HPLAN)   ||      defined(CONFIG_AC3200)          || \
-       defined(CONFIG_ES3210)  ||      defined(CONFIG_ULTRA32)         || \
-       defined(CONFIG_LNE390)  ||      defined(CONFIG_NE3210)          || \
-       defined(CONFIG_NE2K_PCI) ||     defined(CONFIG_APNE)            || \
-       defined(CONFIG_DAYNAPORT)
-#include "../drivers/net/8390.h"
-#endif
-
 #ifdef CONFIG_IPX_MODULE
 extern struct datalink_proto   *make_EII_client(void);
 extern struct datalink_proto   *make_8023_client(void);
index 2955a04..3b2df4f 100644 (file)
@@ -5,7+5,7 @@
  *
  *             PACKET - implements raw packet sockets.
  *
- * Version:    $Id: af_packet.c,v 1.34 2000/04/25 04:13:35 davem Exp $
+ * Version:    $Id: af_packet.c,v 1.36 2000/07/08 00:20:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1053,7+1053,8 @@ static int packet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
        err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
        if (err)
                goto out_free;
-       sk->stamp=skb->stamp;
+
+       sock_recv_timestamp(msg, sk, skb);
 
        if (msg->msg_name)
                memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
@@ -1392,6+1393,23 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
 
        switch(cmd) 
        {
+               case SIOCOUTQ:
+               {
+                       int amount = atomic_read(&sk->wmem_alloc);
+                       return put_user(amount, (int *)arg);
+               }
+               case SIOCINQ:
+               {
+                       struct sk_buff *skb;
+                       int amount = 0;
+
+                       spin_lock_bh(&sk->receive_queue.lock);
+                       skb = skb_peek(&sk->receive_queue);
+                       if (skb)
+                               amount = skb->len;
+                       spin_unlock_bh(&sk->receive_queue.lock);
+                       return put_user(amount, (int *)arg);
+               }
                case FIOSETOWN:
                case SIOCSPGRP:
                        err = get_user(pid, (int *) arg);
index d8c1172..1a4a501 100644 (file)
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/pkt_sched.h>
+#include <net/inet_ecn.h>
 
 #define RED_ECN_ECT  0x02
 #define RED_ECN_CE   0x01
@@ -170,14+171,9 @@ static int red_ecn_mark(struct sk_buff *skb)
                if (!(tos & RED_ECN_ECT))
                        return 0;
 
-               if (!(tos & RED_ECN_CE)) {
-                       u32 check = skb->nh.iph->check;
+               if (!(tos & RED_ECN_CE))
+                       IP_ECN_set_ce(skb->nh.iph);
 
-                       check += __constant_htons(0xFFFE);
-                       skb->nh.iph->check = check + (check>>16);
-
-                       skb->nh.iph->tos = tos | RED_ECN_CE;
-               }
                return 1;
        }
 
index 7ea61ce..1b7119f 100644 (file)
@@ -242,9+242,9 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
            memcmp(n->primary_key, mn->primary_key, mn->tbl->key_len) == 0) {
                atomic_inc(&n->refcnt);
        } else {
-               n = __neigh_lookup(mn->tbl, mn->primary_key, dev, 1);
-               if (n == NULL)
-                       return -ENOBUFS;
+               n = __neigh_lookup_errno(mn->tbl, mn->primary_key, dev);
+               if (IS_ERR(n))
+                       return PTR_ERR(n);
        }
        if (neigh_event_send(n, skb_res) == 0) {
                int err;
close