]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.16 2.2.16
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:28 +0000 (15:21 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:21:28 +0000 (15:21 -0500)
The following security problems are fixed by this release

o Setuid applications. even when correctly checking for failures of
setuid() calls could fail to drop priviledges if the invoker had
made certain adjustments to the capability sets

o Opening a socket and issuing multiple connects on it could be used
to hang the box

o Readv/writev might misbehave on some very large inputs

o Potentially remote exploitable hole in the sunrpc code

o User causable oopses in Appletalk and Socket code

o Obscure exploitable bugs in the Sparc kernel

The full list of enhancements and other bug fixes will follow later.

Recommendations:

You should consider updating your 2.2 kernel to 2.2.16 if

o You have untrusted users on your system
o You have publically accessible kernel sunrpc services

Other major bug fixes include

o The tcp retransmit crash on very high load
o Poor VM performance under some load patterns
o Fix for 3com 3c590 8K card stalls

42 files changed:
MAINTAINERS
Makefile
arch/alpha/boot/bootp.c
arch/alpha/boot/main.c
arch/alpha/kernel/bios32.c
arch/alpha/kernel/core_irongate.c
arch/alpha/kernel/core_mcpcia.c
arch/alpha/kernel/irq.c
arch/alpha/kernel/proto.h
arch/alpha/kernel/setup.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/time.c
arch/alpha/kernel/traps.c
arch/alpha/lib/Makefile
arch/alpha/lib/callback_init.c [new file with mode: 0644]
arch/alpha/lib/callback_srm.S [new file with mode: 0644]
arch/alpha/lib/copy_user.S
arch/alpha/lib/srm_dispatch.S [deleted file]
arch/alpha/lib/srm_fixup.S [deleted file]
arch/alpha/lib/srm_printk.c
arch/alpha/lib/srm_puts.c
arch/alpha/mm/extable.c
arch/alpha/mm/fault.c
arch/alpha/mm/init.c
arch/alpha/vmlinux.lds
drivers/block/ide.c
drivers/i2o/i2o_block.c
drivers/i2o/i2o_config.c
drivers/i2o/i2o_core.c
drivers/net/dgrs.c
drivers/net/via-rhine.c
fs/ncpfs/dir.c
fs/ncpfs/inode.c
fs/ufs/inode.c
include/asm-alpha/console.h
include/asm-alpha/core_tsunami.h
include/asm-alpha/hwrpb.h
include/asm-alpha/pgtable.h
include/asm-alpha/system.h
include/asm-alpha/uaccess.h

index 8bad2b8ff8f3ed5b76212075c822922d6cbe2d58..b03d881b69fc8cef1ae90c2de79e41392efccf90 100644 (file)
@@ -257,7 +257,7 @@ S:      Maintained
 
 DIGI RIGHTSWITCH NETWORK DRIVER
 P:     Rick Richardson
-M:     rick@dgii.com
+M:     rick@remotepoint.com
 L:     linux-net@vger.rutgers.edu
 W:     http://www.dgii.com/linux/
 S:     Maintained
@@ -414,7 +414,7 @@ S:      Supported
 
 IDE DRIVER [GENERAL]
 P:     Andre Hedrick
-M:     hedrick@astro.dyer.vanderbilt.edu
+M:     andre@linux-ide.org
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
index 88db2995999f07c4cde21ce177f9b4b2b545d2af..a4dc55a42b336fdf173df0a6a24a0cecb9497582 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 16
-EXTRAVERSION = pre8
+EXTRAVERSION = 
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index 90fccb766cba8d4ef9c30f05a28b16e9d86ad62c..480d10995f8bfb325e59c0cde964d600692dd3e5 100644 (file)
@@ -171,8 +171,7 @@ start_kernel(void)
        srm_printk("Initrd positioned at %#lx\n", initrd_start);
 #endif
 
-       nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
-                             envval, sizeof(envval));
+       nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
        if (nbytes < 0 || nbytes >= sizeof(envval)) {
                nbytes = 0;
        }
index c97896e8bef5342ea2cf49468f386a61f7688d7b..86254172fb5e32b0dd6ac843f495296a60506d83 100644 (file)
@@ -107,15 +107,15 @@ static inline long openboot(void)
        char bootdev[256];
        long result;
 
-       result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
+       result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
        if (result < 0)
                return result;
-       return srm_dispatch(CCB_OPEN, bootdev, result & 255);
+       return callback_open(bootdev, result & 255);
 }
 
 static inline long close(long dev)
 {
-       return srm_dispatch(CCB_CLOSE, dev);
+       return callback_close(dev);
 }
 
 static inline long load(long dev, unsigned long addr, unsigned long count)
@@ -124,7 +124,7 @@ static inline long load(long dev, unsigned long addr, unsigned long count)
        extern char _end;
        long result, boot_size = &_end - (char *) BOOT_ADDR;
 
-       result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
+       result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
        if (result < 0)
                return result;
        result &= 255;
@@ -132,7 +132,7 @@ static inline long load(long dev, unsigned long addr, unsigned long count)
        if (result)
                srm_printk("Boot file specification (%s) not implemented\n",
                       bootfile);
-       return srm_dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1);
+       return callback_read(dev, count, addr, boot_size/512 + 1);
 }
 
 /*
@@ -176,8 +176,7 @@ void start_kernel(void)
                return;
        }
 
-       nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
-                         envval, sizeof(envval));
+       nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
        if (nbytes < 0) {
                nbytes = 0;
        }
index 42d6aef3f01719ee9a86d2b908305b6245c819ad..adc7dcfa377efdd45356108694f381620f8c64d7 100644 (file)
@@ -327,6 +327,28 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
  */
 #define ALIGN(val,align)       (((val) + ((align) - 1)) & ~((align) - 1))
 
+static short __inline__
+__disable_dev(struct pci_dev *dev)
+{
+       unsigned short cmd, orig_cmd;
+
+       pcibios_read_config_word(dev->bus->number, dev->devfn,
+                                PCI_COMMAND, &cmd);
+
+       orig_cmd = cmd;
+       cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
+
+       pcibios_write_config_word(dev->bus->number, dev->devfn,
+                                 PCI_COMMAND, cmd);
+       return orig_cmd;
+}
+
+static void __inline__
+__enable_dev(struct pci_dev *dev, short orig_cmd)
+{
+       pcibios_write_config_word(dev->bus->number, dev->devfn,
+                                 PCI_COMMAND, orig_cmd);
+}
 
 /* 
  * The following structure records initial configuration of devices
@@ -344,6 +366,7 @@ struct srm_io_reset {
        struct srm_io_reset *next;
        struct pci_dev *dev;
        u32 io;
+       short cmd;
        u8 reg;
 } *srm_io_resets;
 
@@ -354,6 +377,7 @@ reset_for_srm(void)
 {
        struct srm_irq_reset *qreset;
        struct srm_io_reset *ireset;
+       struct pci_dev *last_dev;
 
        /* Reset any IRQs that we changed.  */
        for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
@@ -370,6 +394,15 @@ reset_for_srm(void)
 #endif
        }
 
+       /* Disable any devices which had IO addresses that we changed.  */
+       last_dev = NULL;
+       for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+               if (ireset->dev != last_dev) {
+                       ireset->cmd = __disable_dev(ireset->dev);
+                       last_dev = ireset->dev;
+               }
+       }
+
        /* Reset any IO addresses that we changed.  */
        for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
                pcibios_write_config_dword(ireset->dev->bus->number,
@@ -383,31 +416,40 @@ reset_for_srm(void)
                       ireset->io);
 #endif
        }
+
+       /* Re-enable any devices which had IO addresses that we changed.  */
+       last_dev = NULL;
+       for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+               if (ireset->dev != last_dev) {
+                       __enable_dev(ireset->dev, ireset->cmd);
+                       last_dev = ireset->dev;
+               }
+       }
 }
 
 static void
 new_irq_reset(struct pci_dev *dev, u8 irq)
 {
-       struct srm_irq_reset *n;
-       n = kmalloc(sizeof(*n), GFP_KERNEL);
+       struct srm_irq_reset *new;
+       new = kmalloc(sizeof(*new), GFP_KERNEL);
 
-       n->next = srm_irq_resets;
-       n->dev = dev;
-       n->irq = irq;
-       srm_irq_resets = n;
+       new->next = srm_irq_resets;
+       new->dev = dev;
+       new->irq = irq;
+       srm_irq_resets = new;
 }
 
 static void
 new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
 {
-       struct srm_io_reset *n;
-       n = kmalloc(sizeof(*n), GFP_KERNEL);
-
-       n->next = srm_io_resets;
-       n->dev = dev;
-       n->reg = reg;
-       n->io = io;
-       srm_io_resets = n;
+       struct srm_io_reset *new;
+       new = kmalloc(sizeof(*new), GFP_KERNEL);
+
+       new->next = srm_io_resets;
+       new->dev = dev;
+       new->reg = reg;
+       new->io = io;
+       srm_io_resets = new;
 }
 
 
@@ -418,9 +460,6 @@ new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
 static void __init
 disable_dev(struct pci_dev *dev)
 {
-       struct pci_bus *bus;
-       unsigned short cmd;
-
        /*
         * HACK: the PCI-to-EISA bridge does not seem to identify
         *       itself as a bridge... :-(
@@ -442,10 +481,11 @@ disable_dev(struct pci_dev *dev)
        /*
         * We don't have code that will init the CYPRESS bridge correctly
         * so we do the next best thing, and depend on the previous
-        * console code to do the right thing, and ignore it here... :-\
+        * console code to do the right thing, and ignore it mostly... :-\
         */
        if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
-           dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
+           dev->device == PCI_DEVICE_ID_CONTAQ_82C693 &&
+           PCI_FUNC(dev->devfn) == 0) {
                DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n"));
                return;
        }
@@ -463,12 +503,7 @@ disable_dev(struct pci_dev *dev)
        DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
                  dev->vendor, dev->device));
 
-       bus = dev->bus;
-       pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
-       /* hack, turn it off first... */
-       cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
-       pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
+       (void)__disable_dev(dev);
 }
 
 
@@ -489,6 +524,7 @@ layout_dev(struct pci_dev *dev)
        unsigned int orig_base;
        unsigned int alignto;
        unsigned long handle;
+       int start_idx = 0;
 
        /*
         * HACK: the PCI-to-EISA bridge does not seem to identify
@@ -511,18 +547,24 @@ layout_dev(struct pci_dev *dev)
        /*
         * We don't have code that will init the CYPRESS bridge correctly
         * so we do the next best thing, and depend on the previous
-        * console code to do the right thing, and ignore it here... :-\
+        * console code to do the right thing, and ignore it mostly... :-\
         */
        if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
            dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
+           int func = PCI_FUNC(dev->devfn);
+           if (func == 0) {
                DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n"));
                return;
+           }
+           if (func == 1 || func == 2) { 
+               start_idx = 4; /* bypass BAR 0 - 3 for the IDE devs */
+           }
        }
 
        bus = dev->bus;
        pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
 
-       for (idx = 0; idx <= 5; idx++) {
+       for (idx = start_idx; idx <= 5; idx++) {
                off = PCI_BASE_ADDRESS_0 + 4*idx;
                /*
                 * Figure out how much space and of what type this
@@ -713,6 +755,46 @@ layout_dev(struct pci_dev *dev)
                  dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
 }
 
+/* We must save away the current bridge settings for restore during exit. */
+static void __init
+save_bridge_setup(struct pci_dev *bridge)
+{
+       unsigned int dword;
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_IO_BASE, &dword);
+       new_io_reset(bridge, PCI_IO_BASE, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_IO_BASE_UPPER16, &dword);
+       new_io_reset(bridge, PCI_IO_BASE_UPPER16, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_PREF_BASE_UPPER32, &dword);
+       new_io_reset(bridge, PCI_PREF_BASE_UPPER32, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_PREF_LIMIT_UPPER32, &dword);
+       new_io_reset(bridge, PCI_PREF_LIMIT_UPPER32, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_MEMORY_BASE, &dword);
+       new_io_reset(bridge, PCI_MEMORY_BASE, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_PREF_MEMORY_BASE, &dword);
+       new_io_reset(bridge, PCI_PREF_MEMORY_BASE, dword);
+
+       /* Must use dword that contains PCI_BRIDGE_CONTROL. */
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                 PCI_INTERRUPT_LINE, &dword);
+       new_io_reset(bridge, PCI_INTERRUPT_LINE, dword);
+
+       pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+                                  PCI_COMMAND, &dword);
+       new_io_reset(bridge, PCI_COMMAND, dword);
+}
+
 static int __init
 layout_bus(struct pci_bus *bus)
 {
@@ -764,6 +846,7 @@ layout_bus(struct pci_bus *bus)
                if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
                        found_vga = 1;
        }
+
        /*
         * Recursively allocate space for all of the sub-buses:
         */
@@ -772,6 +855,7 @@ layout_bus(struct pci_bus *bus)
        for (child = bus->children; child; child = child->next) {
                found_vga += layout_bus(child);
        }
+
        /*
         * Align the current bases on 4K and 1MB boundaries:
         */
@@ -783,6 +867,8 @@ layout_bus(struct pci_bus *bus)
 
                DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number));
 
+               save_bridge_setup(bridge);
+
                /*
                 * Set up the top and bottom of the PCI I/O segment
                 * for this bus.
@@ -1364,7 +1450,6 @@ static void __init
 layout_hoses(void)
 {
        struct linux_hose_info * hose;
-       int i;
 
        /* On multiple bus machines, we play games with pci_root in order
           that all of the busses are probed as part of the normal PCI
index 0408e76a78bdc931f52d499621390a0102b076b6..ba226c2e8fd6491975b36dced44727fac8a23ff7 100644 (file)
@@ -295,7 +295,7 @@ irongate_register_dump(const char *function_name)
               IRONGATE0->agpmode);
 }
 #else
-#define irongate_register_dump(x)      1
+#define irongate_register_dump(x)
 #endif
 
 void __init
index e2583bfd74add555d4c296cfd8a5eb8e366d077e..d75711c0179e381cb08c475560d88808f547bad7 100644 (file)
@@ -661,6 +661,65 @@ mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
               frame->ld_lock);
 }
 
+void
+mcpcia_print_system_area(unsigned long la_ptr)
+{
+       struct el_common *frame;
+       int i;
+
+       struct IOD_subpacket {
+         unsigned long base;
+         unsigned int whoami;
+         unsigned int rsvd1;
+         unsigned int pci_rev;
+         unsigned int cap_ctrl;
+         unsigned int hae_mem;
+         unsigned int hae_io;
+         unsigned int int_ctl;
+         unsigned int int_reg;
+         unsigned int int_mask0;
+         unsigned int int_mask1;
+         unsigned int mc_err0;
+         unsigned int mc_err1;
+         unsigned int cap_err;
+         unsigned int rsvd2;
+         unsigned int pci_err1;
+         unsigned int mdpa_stat;
+         unsigned int mdpa_syn;
+         unsigned int mdpb_stat;
+         unsigned int mdpb_syn;
+         unsigned int rsvd3;
+         unsigned int rsvd4;
+         unsigned int rsvd5;
+       } *iodpp;
+
+       frame = (struct el_common *)la_ptr;
+
+       iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
+
+       for (i = 0; i < hose_count; i++, iodpp++) {
+         printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
+                i, iodpp->base);
+         printk("  WHOAMI      = %8x\n", iodpp->whoami);
+         printk("  PCI_REV     = %8x\n", iodpp->pci_rev);
+         printk("  CAP_CTRL    = %8x\n", iodpp->cap_ctrl);
+         printk("  HAE_MEM     = %8x\n", iodpp->hae_mem);
+         printk("  HAE_IO      = %8x\n", iodpp->hae_io);
+         printk("  INT_CTL     = %8x\n", iodpp->int_ctl);
+         printk("  INT_REG     = %8x\n", iodpp->int_reg);
+         printk("  INT_MASK0   = %8x\n", iodpp->int_mask0);
+         printk("  INT_MASK1   = %8x\n", iodpp->int_mask1);
+         printk("  MC_ERR0     = %8x\n", iodpp->mc_err0);
+         printk("  MC_ERR1     = %8x\n", iodpp->mc_err1);
+         printk("  CAP_ERR     = %8x\n", iodpp->cap_err);
+         printk("  PCI_ERR1    = %8x\n", iodpp->pci_err1);
+         printk("  MDPA_STAT   = %8x\n", iodpp->mdpa_stat);
+         printk("  MDPA_SYN    = %8x\n", iodpp->mdpa_syn);
+         printk("  MDPB_STAT   = %8x\n", iodpp->mdpb_stat);
+         printk("  MDPB_SYN    = %8x\n", iodpp->mdpb_syn);
+       }
+}
+
 void
 mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
                     struct pt_regs * regs)
@@ -709,6 +768,7 @@ halt();
            if (vector != 0x620 && vector != 0x630
                && ! MCPCIA_mcheck_expected[cpu]) {
                mcpcia_print_uncorrectable(mchk_logout);
+               mcpcia_print_system_area(la_ptr);
            }
        }
 
index aa33e330e749394ad7f4ac516e166648bcea4085..776b9ca4ce9b086223d7fad0aca218a3ec0f5611 100644 (file)
@@ -896,7 +896,14 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
 unsigned long __init init_IRQ(unsigned long memory)
 {
        wrent(entInt, 0);
+
        alpha_mv.init_irq();
+
+        /* If we had wanted SRM console printk echoing early, undo it now. */
+        if (alpha_using_srm && srmcons_output) {
+                unregister_srm_console();
+        }
+
        return memory;
 }
 
index dcddc35042277d3bf3273f8f5d1cee3c20ce8aa1..9cfeb0021d61a8173f9a8f6bc564f408290a82c1 100644 (file)
@@ -60,6 +60,7 @@ extern int irongate_hose_write_config_dword (u8, u8, u8, u32 value,
                                            struct linux_hose_info *hose);
 extern void irongate_init_arch(unsigned long *, unsigned long *);
 extern void irongate_machine_check(u64, u64, struct pt_regs *);
+extern int irongate_pci_clr_err(void);
 
 /* core_lca.c */
 extern int lca_hose_read_config_byte (u8, u8, u8, u8 *value,
@@ -164,6 +165,9 @@ extern void tsunami_machine_check(u64, u64, struct pt_regs *);
 
 /* setup.c */
 extern unsigned long srm_hae;
+extern int srmcons_output;
+extern void register_srm_console(void);
+extern void unregister_srm_console(void);
 
 /* smp.c */
 extern void setup_smp(void);
@@ -219,6 +223,7 @@ extern int ptrace_set_bpt (struct task_struct *child);
 extern int ptrace_cancel_bpt (struct task_struct *child);
 
 /* ../mm/init.c */
+extern void switch_to_system_map(void);
 void srm_paging_stop(void);
 
 /* irq.c */
index 4f927bdee26f6502b0c517fc9538b05510df6a30..cd61bde288ac9770e2b451020700ab294bb25e48 100644 (file)
@@ -40,7 +40,7 @@
 #include <asm/page.h>
 #include <asm/dma.h>
 #include <asm/io.h>
-
+#include <asm/console.h>
 
 #include "proto.h"
 
@@ -52,6 +52,15 @@ struct alpha_machine_vector alpha_mv;
 int alpha_using_srm, alpha_use_srm_setup;
 #endif
 
+/* Using SRM callbacks for initial console output. This works from
+   setup_arch() time through the end of init_IRQ(), as those places
+   are under our control.
+
+   By default, OFF; set it with a bootcommand arg of "srmcons".
+*/
+int srmcons_output = 0;
+
+/* For PS/2 presence */
 unsigned char aux_device_present = 0xaa;
 
 #define N(a) (sizeof(a)/sizeof(a[0]))
@@ -144,23 +153,31 @@ void __init
 setup_arch(char **cmdline_p, unsigned long * memory_start_p,
           unsigned long * memory_end_p)
 {
-       extern char _end[];
-
        struct alpha_machine_vector *vec = NULL;
        struct percpu_struct *cpu;
        char *type_name, *var_name, *p;
        unsigned long memory_end_override = 0;
+       extern char _end;
+       void *kernel_end = &_end; /* End of the kernel. */
 
        hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
 
+#ifdef CONFIG_ALPHA_GENERIC
+       /* Assume that we've booted from SRM if we havn't booted from MILO.
+          Detect the later by looking for "MILO" in the system serial nr.  */
+       alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#endif
+
+       kernel_end = callback_init(kernel_end);
+
        /* 
-        * Locate the command line.
-        */
+          Process the command line.
 
-       /* Hack for Jensen... since we're restricted to 8 or 16 chars for
+          Hack for Jensen... since we're restricted to 8 or 16 chars for
           boot flags depending on the boot mode, we need some shorthand.
           This should do for installation.  Later we'll add other
-          abbreviations as well... */
+          abbreviations as well...
+       */
        if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
                strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
        } else {
@@ -198,11 +215,20 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
                        memory_end_override = get_memory_end_override(p+4);
                        continue;
                }
+               if (strncmp(p, "srmcons", 7) == 0) {
+                       srmcons_output = 1;
+                       continue;
+               }
        }
 
        /* Replace the command line, not that we've killed it with strtok.  */
        strcpy(command_line, saved_command_line);
 
+       /* If we want SRM console printk echoing early, do it now. */
+       if (alpha_using_srm && srmcons_output) {
+               register_srm_console();
+       }
+
        /*
         * Indentify and reconfigure for the current system.
         */
@@ -228,12 +254,6 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
                alpha_mv = *vec;
        }
        
-#ifdef CONFIG_ALPHA_GENERIC
-       /* Assume that we've booted from SRM if we havn't booted from MILO.
-          Detect the later by looking for "MILO" in the system serial nr.  */
-       alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#endif
-
        printk("%s on %s%s%s using machine vector %s from %s\n",
 #ifdef CONFIG_ALPHA_GENERIC
               "Booting GENERIC",
@@ -258,7 +278,7 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
        wrmces(0x7);
 
        /* Find our memory.  */
-       *memory_start_p = (unsigned long) _end;
+       *memory_start_p = (unsigned long)kernel_end;
        *memory_end_p = find_end_memory();
        if (memory_end_override && memory_end_override < *memory_end_p) {
                printk("Overriding memory size from %luMB to %luMB\n",
@@ -342,7 +362,7 @@ find_end_memory(void)
        struct memdesc_struct * memdesc;
 
        memdesc = (struct memdesc_struct *)
-               (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+               (hwrpb->mddt_offset + (unsigned long)hwrpb);
        cluster = memdesc->cluster;
 
        for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
@@ -421,7 +441,7 @@ static char rawhide_names[][16] = {
 static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
 
 static char tsunami_names[][16] = {
-       "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
+       "EarlyMonet", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
        "Goldrush", "Webbrick", "Catamaran"
 };
 static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8};
@@ -508,7 +528,7 @@ get_sysvec(long type, long variation, long cpu)
 
        static struct alpha_machine_vector *tsunami_vecs[]  __initlocaldata =
        {
-               NULL,
+               &monet_mv,              /* HACK for early Monets */
                &dp264_mv,              /* dp264 */
                &dp264_mv,              /* warhol */
                &dp264_mv,              /* windjammer */
@@ -543,7 +563,7 @@ get_sysvec(long type, long variation, long cpu)
 
        if (!vec) {
                /* Member ID is a bit-field. */
-               long member = (variation >> 10) & 0x3f;
+               long member = HWRPB_MEMBER_ID(variation);
 
                switch (type) {
                case ST_DEC_ALCOR:
@@ -832,3 +852,65 @@ int get_cpuinfo(char *buffer)
 
        return len;
 }
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+/*
+ *      Manage the SRM callbacks as a "console".
+ */
+static struct console srmcons;
+
+void __init register_srm_console(void)
+{
+        register_console(&srmcons);
+}
+
+void __init unregister_srm_console(void)
+{
+        unregister_console(&srmcons);
+}
+
+static void srm_console_write(struct console *co, const char *s,
+                                unsigned count)
+{
+       srm_printk(s);
+}
+
+static kdev_t srm_console_device(struct console *c)
+{
+  /* Huh? */
+        return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int srm_console_wait_key(struct console *co)
+{
+  /* Huh? */
+       return 1;
+}
+
+static int __init srm_console_setup(struct console *co, char *options)
+{
+       return 1;
+}
+
+static struct console srmcons = {
+        "srm0",
+        srm_console_write,
+        NULL,
+        srm_console_device,
+        srm_console_wait_key,
+        NULL,
+       srm_console_setup,
+        CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
+        -1,
+        0,
+        NULL
+};
+
+#else
+void __init register_srm_console(void)
+{
+}
+void __init unregister_srm_console(void)
+{
+}
+#endif
index e80e364f34209103a9db1edba6667e4463a110b6..8beaa9503caf3798254b49061932be2fc645c58c 100644 (file)
@@ -393,7 +393,12 @@ monet_pci_fixup(void)
        layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
        common_pci_fixup(monet_map_irq, monet_swizzle);
        SMC669_Init(1);
-       es1888_init();
+
+       /* HACK: early Monets had a member ID of 0 and the ES1888
+          located in a non-standard spot, so do this only for
+          official Monets */
+       if (HWRPB_MEMBER_ID(hwrpb->sys_variation) != 0)
+               es1888_init();
 }
 
 static void __init
index 9952c311fd482e9b99719b8d2520efa7a5eafc93..fa438dfb9a030ee496d00b4569758a11b95cbd56 100644 (file)
@@ -155,13 +155,14 @@ static void
 mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
                     struct pt_regs * regs)
 {
-#define MCHK_NO_DEVSEL 0x205L
-#define MCHK_NO_TABT 0x204L
+#define MCHK_NO_DEVSEL 0x205U
+#define MCHK_NO_TABT 0x204U
 
        struct el_common *mchk_header;
        struct el_apecs_procdata *mchk_procdata;
        struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
        unsigned long *ptr;
+       unsigned int code; /* workaround EGCS problem */
        int i;
 
        mchk_header = (struct el_common *)la_ptr;
@@ -193,9 +194,11 @@ mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
         * ignore the machine check.
         */
 
-       if (apecs_mcheck_expected
-           && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
-               || (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
+       code = mchk_header->code; /* workaround EGCS problem */
+
+       if (apecs_mcheck_expected &&
+           (code == MCHK_NO_DEVSEL || code == MCHK_NO_TABT))
+       {
                apecs_mcheck_expected = 0;
                apecs_mcheck_taken = 1;
                mb();
@@ -214,9 +217,9 @@ mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
                       vector);
        }
        else {
-               printk(KERN_CRIT "APECS machine check:\n");
-               printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx\n",
-                      vector, la_ptr);
+               printk(KERN_CRIT "MIKASA APECS machine check:\n");
+               printk(KERN_CRIT "  vector=0x%lx la_ptr=0x%lx code=0x%x\n",
+                      vector, la_ptr, code);
                printk(KERN_CRIT
                       "  pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
                       regs->pc, mchk_header->size, mchk_header->proc_offset,
@@ -274,7 +277,7 @@ struct alpha_machine_vector mikasa_primo_mv __initmv = {
        DO_DEFAULT_RTC,
        DO_CIA_IO,
        DO_CIA_BUS,
-       machine_check:          mikasa_machine_check,
+       machine_check:          cia_machine_check,
        max_dma_address:        ALPHA_MAX_DMA_ADDRESS,
 
        nr_irqs:                32,
index 95539f811416836817ea34cc8f1874471c7c6aac..d495b000cb4976e12316041fa89362f78911129a 100644 (file)
@@ -94,7 +94,7 @@ nautilus_kill_arch (int mode, char *restart_cmd)
        {
                unsigned char control;
 
-               cli();
+               __cli();
 
                /* Reset periodic interrupt frequency.  */
                CMOS_WRITE(0x26, RTC_FREQ_SELECT);
@@ -105,7 +105,7 @@ nautilus_kill_arch (int mode, char *restart_cmd)
                CMOS_WRITE(control, RTC_CONTROL);       
                CMOS_READ(RTC_INTR_FLAGS);
 
-               sti();
+               __sti();
        }
 #endif
 
@@ -115,7 +115,7 @@ nautilus_kill_arch (int mode, char *restart_cmd)
                break;
        case LINUX_REBOOT_CMD_RESTART:
                {
-                       int v;
+                       unsigned char v;
                        irongate_hose_read_config_byte(0, 0x07<<3, 0x43, &v, 0);
                        irongate_hose_write_config_byte(0, 0x07<<3, 0x43, v | 0x80, 0);
                        outb(1, 0x92);
@@ -504,7 +504,8 @@ void nautilus_machine_check(unsigned long vector, unsigned long la_ptr,
        break;
     }
 
-    printk(KERN_CRIT "> NAUTILUS Machine check 0x%x [%s]\n", vector, mchk_class);
+    printk(KERN_CRIT "> NAUTILUS Machine check 0x%lx [%s]\n",
+          vector, mchk_class);
 
     if ( cpu_analysis )        
        ev6_cpu_machine_check(  vector,
index 06da880679f02296f753ab9d70a8243eea071aae..ebe39e330e69dbf4080861a600c0c20d2261f99d 100644 (file)
@@ -236,7 +236,7 @@ time_init(void)
 {
        void (*irq_handler)(int, void *, struct pt_regs *);
        unsigned int year, mon, day, hour, min, sec, cc1, cc2;
-       unsigned long cycle_freq, one_percent;
+       unsigned long cycle_freq, ppm_error;
        long diff;
 
        /*
@@ -261,17 +261,29 @@ time_init(void)
                cc1 = cc2;
        }
 
-       /* If the given value is within 1% of what we calculated, 
-          accept it.  Otherwise, use what we found.  */
-       cycle_freq = hwrpb->cycle_freq;
-       one_percent = cycle_freq / 100;
+       /* This code used to check for a 1% error.
+        * PWS600au reports 598802395 which is way off. (ntpd has problems.)
+        * So I tightened down the check.  Hal Murray, Feb 27, 2000.
+        *
+        * HWRPB cycle_freq may be 0 (uninitialized) due to MILO, so make
+        * sure that we handle this case by forcing use of est_cycle_freq.
+        */
+       if (!(cycle_freq = hwrpb->cycle_freq))
+               cycle_freq = est_cycle_freq;
+
        diff = cycle_freq - est_cycle_freq;
        if (diff < 0)
                diff = -diff;
-       if (diff > one_percent) {
+       ppm_error = (diff * 1000000L) / cycle_freq;
+#if 0
+       printk("Alpha clock init: HWRPB %lu, Measured %lu, error=%lu ppm.\n",
+              hwrpb->cycle_freq, est_cycle_freq, ppm_error);
+#endif
+       if (ppm_error > 1000) {
+               printk("HWRPB cycle frequency (%lu) seems inaccurate -"
+                      " using the measured value of %lu Hz\n",
+                      cycle_freq, est_cycle_freq);
                cycle_freq = est_cycle_freq;
-               printk("HWRPB cycle frequency bogus.  Estimated %lu Hz\n",
-                      cycle_freq);
        }
        else {
                est_cycle_freq = 0;
index 03225a5d6ae628ab760a2e046ab850c4c8ddf5ff..655582653f672aaef60c742c9a1fe889adbd7c02 100644 (file)
@@ -652,7 +652,7 @@ do_entUna(void * va, unsigned long opcode, unsigned long reg,
 got_exception:
        /* Ok, we caught the exception, but we don't want it.  Is there
           someone to pass it along to?  */
-       if ((fixup = search_exception_table(pc)) != 0) {
+       if ((fixup = search_exception_table(pc, regs.gp)) != 0) {
                unsigned long newpc;
                newpc = fixup_exception(una_reg, fixup, pc);
 
index 400adf0e1de2e456698063a15ba208a7a89616cb..dba908e863a5ff95648942669921bb6c45d5fdca 100644 (file)
@@ -2,13 +2,18 @@
 # Makefile for alpha-specific library files..
 #
 
+.S.s:
+       $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+       $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
 OBJS  = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
        checksum.o csum_partial_copy.o strlen.o \
        strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
        strchr.o strrchr.o \
        copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
        csum_ipv6_magic.o strcasecmp.o semaphore.o \
-       srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
+       callback_srm.o callback_init.o srm_puts.o srm_printk.o
 
 lib.a: $(OBJS)
        $(AR) rcs lib.a $(OBJS)
diff --git a/arch/alpha/lib/callback_init.c b/arch/alpha/lib/callback_init.c
new file mode 100644 (file)
index 0000000..b9c185f
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ *      arch/alpha/lib/callback_init.c
+ */
+
+#include <asm/page.h>
+#include <asm/hwrpb.h>
+#include <asm/console.h>
+#include <asm/pgtable.h>
+#include <asm/init.h>
+
+#include "../kernel/proto.h"
+
+int callback_init_done = 0;
+
+/* This is the SRM version.  Maybe there will be a DBM version. */
+
+void * __init callback_init(void * kernel_end)
+{
+       int i, j;
+       unsigned long vaddr = CONSOLE_REMAP_START;
+       struct crb_struct * crb;
+       pgd_t * pgd = pgd_offset_k(vaddr);
+       pmd_t * pmd;
+       void * two_pte_pages;
+
+       /* Always page align the end of the kernel. */
+       kernel_end = (void *)
+         (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
+
+       if (!alpha_using_srm) {
+               switch_to_system_map();
+               return kernel_end;
+       }
+
+       /* Allocate some memory for the pages. */
+       two_pte_pages = kernel_end;
+       kernel_end = two_pte_pages + 2*PAGE_SIZE;
+       memset(two_pte_pages, 0, 2*PAGE_SIZE);
+
+       /* Starting at the HWRPB, locate the CRB. */
+       crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
+
+       /* Tell the console whither the console is to be remapped. */
+       if (srm_fixup(vaddr, (unsigned long)hwrpb))
+               __halt();               /* "We're boned."  --Bender */
+
+       /* Edit the procedure descriptors for DISPATCH and FIXUP. */
+       crb->dispatch_va = (struct procdesc_struct *)
+               (vaddr + (unsigned long)crb->dispatch_va - crb->map[0].va);
+       crb->fixup_va = (struct procdesc_struct *)
+               (vaddr + (unsigned long)crb->fixup_va - crb->map[0].va);
+
+       switch_to_system_map();
+
+       /*
+        * Set up the first and second level PTEs for console callbacks.
+        * There is an assumption here that only one of each is needed,
+        * and this allows for 8MB.  Currently (late 1999), big consoles
+        * are still under 3MB.
+        */
+       pgd_set(pgd, (pmd_t *)two_pte_pages);
+       pmd = pmd_offset(pgd, vaddr);
+       pmd_set(pmd, (pte_t *)(two_pte_pages + PAGE_SIZE));
+
+       /*
+        * Set up the third level PTEs and update the virtual addresses
+        * of the CRB entries.
+        */
+       for (i = 0; i < crb->map_entries; ++i) {
+               unsigned long paddr = crb->map[i].pa;
+               crb->map[i].va = vaddr;
+               for (j = 0; j < crb->map[i].count; ++j) {
+                       set_pte(pte_offset(pmd, vaddr),
+                               mk_pte_phys(paddr, PAGE_KERNEL));
+                       paddr += PAGE_SIZE;
+                       vaddr += PAGE_SIZE;
+               }
+       }
+
+       callback_init_done = 1;
+       return kernel_end;
+}
+
diff --git a/arch/alpha/lib/callback_srm.S b/arch/alpha/lib/callback_srm.S
new file mode 100644 (file)
index 0000000..9d6d8af
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ *     arch/alpha/lib/callback_srm.S
+ */
+
+#include <linux/config.h>
+#include <asm/console.h>
+
+.text
+#define HWRPB_CRB_OFFSET 0xc0
+
+#if defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC)
+.align 4
+srm_dispatch:
+#if defined(CONFIG_ALPHA_GENERIC)
+       ldl     $4,alpha_using_srm
+       beq     $4,nosrm
+#endif
+       ldq     $0,hwrpb        # gp is set up by CALLBACK macro.
+       ldl     $25,0($25)      # Pick up the wrapper data.
+       mov     $20,$21         # Shift arguments right.
+       mov     $19,$20
+       ldq     $1,HWRPB_CRB_OFFSET($0)
+       mov     $18,$19
+       mov     $17,$18
+       mov     $16,$17
+       addq    $0,$1,$2        # CRB address
+       ldq     $27,0($2)       # DISPATCH procedure descriptor (VMS call std)
+       extwl   $25,0,$16       # SRM callback function code
+       ldq     $3,8($27)       # call address
+       extwl   $25,2,$25       # argument information (VMS calling std)
+       jmp     ($3)            # Return directly to caller of wrapper.
+
+.align 4
+.globl srm_fixup
+.ent   srm_fixup
+srm_fixup:
+       ldgp    $29,0($27)
+#if defined(CONFIG_ALPHA_GENERIC)
+       ldl     $4,alpha_using_srm
+       beq     $4,nosrm
+#endif
+       ldq     $0,hwrpb
+       ldq     $1,HWRPB_CRB_OFFSET($0)
+       addq    $0,$1,$2        # CRB address
+       ldq     $27,16($2)      # VA of FIXUP procedure descriptor
+       ldq     $3,8($27)       # call address
+       lda     $25,2($31)      # two integer arguments
+       jmp     ($3)            # Return directly to caller of srm_fixup.
+.end    srm_fixup
+
+#if defined(CONFIG_ALPHA_GENERIC)
+.align 3
+nosrm:
+       lda     $0,-1($31)
+       ret
+#endif
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 4; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+ldgp $29,0($27); br $25,srm_dispatch; .word CODE, ARG_CNT; .end callback_##NAME
+
+#else /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 3; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+lda $0,-1($31); ret; .end callback_##NAME
+
+.align 3
+.globl srm_fixup
+.ent   srm_fixup
+srm_fixup:
+       lda     $0,-1($31)
+       ret
+.end   srm_fixup
+#endif /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+CALLBACK(puts, CCB_PUTS, 4)
+CALLBACK(open, CCB_OPEN, 3)
+CALLBACK(close, CCB_CLOSE, 2)
+CALLBACK(read, CCB_READ, 5)
+CALLBACK(getenv, CCB_GET_ENV, 4)
+CALLBACK(setenv, CCB_SET_ENV, 4)
+CALLBACK(getc, CCB_GETC, 2)
+CALLBACK(reset_term, CCB_RESET_TERM, 2)
+CALLBACK(term_int, CCB_SET_TERM_INT, 3)
+CALLBACK(term_ctl, CCB_SET_TERM_CTL, 3)
+CALLBACK(process_keycode, CCB_PROCESS_KEYCODE, 3)
+CALLBACK(ioctl, CCB_IOCTL, 6)
+CALLBACK(write, CCB_WRITE, 5)
+CALLBACK(reset_env, CCB_RESET_ENV, 4)
+CALLBACK(save_env, CCB_SAVE_ENV, 1)
+CALLBACK(pswitch, CCB_PSWITCH, 3)
+CALLBACK(bios_emul, CCB_BIOS_EMUL, 5)
+       
+.data
+__alpha_using_srm:             # For use by bootpheader
+       .long 7                 # value is not 1 for link debugging
+       .weak alpha_using_srm; alpha_using_srm = __alpha_using_srm
+__callback_init_done:           # For use by bootpheader
+        .long 7                 # value is not 1 for link debugging
+        .weak callback_init_done; callback_init_done = __callback_init_done
+
index 7cc7382ab314ff135e5c89351c9f64081ad7f805..d8f1a24cfeddcdb82959b8f69b7a64578b1ef2fb 100644 (file)
@@ -80,7 +80,7 @@ $50:
        extql $3,$7,$3
        extqh $2,$7,$1
        bis $3,$1,$1
-       stq $1,0($6)
+       EXO( stq $1,0($6) )
        addq $7,8,$7
        subq $0,8,$0
        addq $6,8,$6
diff --git a/arch/alpha/lib/srm_dispatch.S b/arch/alpha/lib/srm_dispatch.S
deleted file mode 100644 (file)
index 2bcea30..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *     arch/alpha/lib/srm_dispatch.S
- */
-
-.globl srm_dispatch
-.ent   srm_dispatch
-srm_dispatch:
-       .frame  $30,30,$26
-       subq    $30,80,$30
-       stq     $26,0($30)
-       stq     $8,8($30)
-       stq     $9,16($30)
-       stq     $10,24($30)
-       stq     $11,32($30)
-       stq     $12,40($30)
-       stq     $13,48($30)
-       stq     $14,56($30)
-       stq     $15,64($30)
-       stq     $29,72($30)
-       .mask   0x2400FF00, -80
-       .prologue 0
-
-       ldq     $1,hwrpb
-       ldq     $2,0xc0($1)             /* crb offset */
-       addq    $2,$1,$2                /* crb */
-       ldq     $27,0($2)               /* dispatch procedure value */
-
-       ldq     $2,8($27)               /* dispatch call address */
-       jsr     $26,($2)                /* call it (weird VMS call seq) */
-
-       ldq     $26,0($30)
-       ldq     $8,8($30)
-       ldq     $9,16($30)
-       ldq     $10,24($30)
-       ldq     $11,32($30)
-       ldq     $12,40($30)
-       ldq     $13,48($30)
-       ldq     $14,56($30)
-       ldq     $15,64($30)
-       ldq     $29,72($30)
-       addq    $30,80,$30
-       ret     $31,($26),1
-.end    srm_dispatch
diff --git a/arch/alpha/lib/srm_fixup.S b/arch/alpha/lib/srm_fixup.S
deleted file mode 100644 (file)
index 9cf2d78..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *     arch/alpha/lib/srm_fixup.S
- */
-
-.globl srm_fixup
-.ent   srm_fixup
-srm_fixup:
-       .frame  $30,30,$26
-       subq    $30,80,$30
-       stq     $26,0($30)
-       stq     $8,8($30)
-       stq     $9,16($30)
-       stq     $10,24($30)
-       stq     $11,32($30)
-       stq     $12,40($30)
-       stq     $13,48($30)
-       stq     $14,56($30)
-       stq     $15,64($30)
-       stq     $29,72($30)
-       .mask   0x2400FF00, -80
-       .prologue 0
-
-       ldq     $2,0xc0($17)            /* crb offset */
-       addq    $2,$1,$2                /* crb */
-       ldq     $27,16($2)              /* fixup procedure value */
-
-       ldq     $2,8($27)               /* dispatch call address */
-       jsr     $26,($2)                /* call it (weird VMS call seq) */
-
-       ldq     $26,0($30)
-       ldq     $8,8($30)
-       ldq     $9,16($30)
-       ldq     $10,24($30)
-       ldq     $11,32($30)
-       ldq     $12,40($30)
-       ldq     $13,48($30)
-       ldq     $14,56($30)
-       ldq     $15,64($30)
-       ldq     $29,72($30)
-       addq    $30,80,$30
-       ret     $31,($26),1
-.end    srm_fixup
index b5baee15ffd21c88fe983a97d46e5b38e288c291..547bc9f8a17f9b9636d482124ba62c0ae527f863 100644 (file)
@@ -10,12 +10,31 @@ srm_printk(const char *fmt, ...)
 {
        static char buf[1024];
         va_list args;
-        long i;
+        long len, num_lf;
+        char *src, *dst;
 
         va_start(args, fmt);
-        i = vsprintf(buf,fmt,args);
+        len = vsprintf(buf, fmt, args);
         va_end(args);
 
-       srm_puts(buf);  
-        return i;
+        /* Count number of linefeeds in string. */
+        num_lf = 0;
+        for (src = buf; *src; ++src) {
+                if (*src == '\n') {
+                        ++num_lf;
+                }
+        }
+
+       /* Expand each linefeed into carriage-return/linefeed. */
+        if (num_lf) {
+                for (dst = src + num_lf; src >= buf; ) {
+                        if (*src == '\n') {
+                                *dst-- = '\r';
+                        }
+                        *dst-- = *src--;
+                }
+        }
+
+       srm_puts(buf, num_lf+len);      
+        return len;
 }
index 87b1d11559a461c762ee4795f34bbda70d6e4f6d..caded3e1b95b1d812bdb626c151813b0187f0e67 100644 (file)
@@ -5,30 +5,19 @@
 #include <linux/string.h>
 #include <asm/console.h>
 
-void
-srm_puts(const char *str)
+long
+srm_puts(const char *str, long len)
 {
-       /* Expand \n to \r\n as we go.  */
+        long remaining, written;
 
-       while (*str) {
-               long len;
-               const char *e = str;
+        if (!callback_init_done)
+                return len;
 
-               if (*str == '\n') {
-                       if (srm_dispatch(CCB_PUTS, 0, "\r", 1) < 0)
-                               return;
-                       ++e;
-               }
-
-               e = strchr(e, '\n') ? : strchr(e, '\0');
-               len = e - str;
-
-               while (len > 0) {
-                       long written = srm_dispatch(CCB_PUTS, 0, str, len);
-                       if (written < 0)
-                               return;
-                       len -= written & 0xffffffff;
-                       str += written & 0xffffffff;
-               }
-       }
+        for (remaining = len; remaining > 0; remaining -= written)
+        {
+                written = callback_puts(0, str, remaining);
+                written &= 0xffffffff;
+                str += written;
+        }
+        return len;
 }
index b0cb627ad6976a6b4f62e22324bcab94f6ec0a07..acbc394cb6d7cc745b0c8597a4de2b92ebfedd13 100644 (file)
@@ -36,8 +36,8 @@ search_one_table(const struct exception_table_entry *first,
 
 register unsigned long gp __asm__("$29");
 
-unsigned
-search_exception_table(unsigned long addr)
+static unsigned
+search_exception_table_without_gp(unsigned long addr)
 {
        unsigned ret;
 
@@ -60,3 +60,38 @@ search_exception_table(unsigned long addr)
 
        return 0;
 }
+
+unsigned
+search_exception_table(unsigned long addr, unsigned long exc_gp)
+{
+       unsigned ret;
+
+#ifndef CONFIG_MODULES
+       ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
+                              addr - exc_gp);
+       if (ret) return ret;
+#else
+       /* The kernel is the last "module" -- no need to treat it special. */
+       struct module *mp;
+       for (mp = module_list; mp ; mp = mp->next) {
+               if (!mp->ex_table_start)
+                       continue;
+               ret = search_one_table(mp->ex_table_start,
+                                      mp->ex_table_end - 1, addr - exc_gp);
+               if (ret) return ret;
+       }
+#endif
+
+       /*
+        * The search failed with the exception gp. To be safe, try the
+        * old method before giving up.
+        */
+       ret = search_exception_table_without_gp(addr);
+       if (ret) {
+               printk(KERN_ALERT, "%s: [%lx] EX_TABLE search fail with"
+                      "exc frame GP, success with raw GP\n",
+                      current->comm, addr);
+               return ret;
+       }
+        return 0;
+}
index f0c0fc7bc2a1d9584b0b1c4ca60d39444e4b5eaa..6e0ed901f5506c7210f6ea4367727f70e43b5272 100644 (file)
@@ -147,11 +147,11 @@ bad_area:
 
 no_context:
        /* Are we prepared to handle this fault as an exception?  */
-       if ((fixup = search_exception_table(regs->pc)) != 0) {
+       if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) {
                unsigned long newpc;
                newpc = fixup_exception(dpf_reg, fixup, regs->pc);
-#if 0
-               printk("%s: Exception at [<%lx>] (%lx)\n",
+#if 1
+               printk("%s: Exception at [<%lx>] (%lx) handled successfully.\n",
                       current->comm, regs->pc, newpc);
 #endif
                regs->pc = newpc;
index 606fe1e5a9208d40ad2cafaecab4791598bec069..b6a1d2ffff900549b3ffaf5631a78b69461b0b98 100644 (file)
@@ -182,6 +182,44 @@ load_PCB(struct thread_struct * pcb)
        return (struct thread_struct *) __reload_tss(pcb);
 }
 
+void
+switch_to_system_map(void)
+{
+       unsigned long newptbr;
+       struct thread_struct *original_pcb_ptr;
+
+       memset(swapper_pg_dir, 0, PAGE_SIZE);
+       newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
+       pgd_val(swapper_pg_dir[1023]) =
+               (newptbr << 32) | pgprot_val(PAGE_KERNEL);
+
+
+       /* Also set up the real kernel PCB while we're at it.  */
+       init_task.tss.ptbr = newptbr;
+       init_task.tss.pal_flags = 1;    /* set FEN, clear everything else */
+       init_task.tss.flags = 0;
+
+       hwrpb->vptb = 0xfffffffe00000000;
+       hwrpb_update_checksum(hwrpb);
+
+       wrvptptr(0xfffffffe00000000);
+       original_pcb_ptr = load_PCB(&init_task.tss);
+       tbia();
+
+       /* Save off the contents of the original PCB so that we can
+          restore the original console's page tables for a clean reboot.
+
+          Note that the PCB is supposed to be a physical address, but
+          since KSEG values also happen to work, folks get confused.
+          Check this here.  */
+
+       if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
+               original_pcb_ptr = (struct thread_struct *)
+                 phys_to_virt((unsigned long) original_pcb_ptr);
+       }
+       original_pcb = *original_pcb_ptr;
+}
+
 /*
  * paging_init() sets up the page tables: in the alpha version this actually
  * unmaps the bootup page table (as we're now in KSEG, so we don't need it).
@@ -190,10 +228,8 @@ unsigned long
 paging_init(unsigned long start_mem, unsigned long end_mem)
 {
        int i;
-       unsigned long newptbr;
        struct memclust_struct * cluster;
        struct memdesc_struct * memdesc;
-       struct thread_struct *original_pcb_ptr;
 
        /* initialize mem_map[] */
        start_mem = free_area_init(start_mem, end_mem);
@@ -221,41 +257,7 @@ paging_init(unsigned long start_mem, unsigned long end_mem)
                        clear_bit(PG_reserved, &mem_map[pfn++].flags);
        }
 
-       /* Initialize the kernel's page tables.  Linux puts the vptb in
-          the last slot of the L1 page table.  */
        memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
-       memset(swapper_pg_dir, 0, PAGE_SIZE);
-       newptbr = MAP_NR(swapper_pg_dir);
-       pgd_val(swapper_pg_dir[1023]) =
-               (newptbr << 32) | pgprot_val(PAGE_KERNEL);
-
-       /* Set the vptb.  This is often done by the bootloader, but 
-          shouldn't be required.  */
-       if (hwrpb->vptb != 0xfffffffe00000000) {
-               wrvptptr(0xfffffffe00000000);
-               hwrpb->vptb = 0xfffffffe00000000;
-               hwrpb_update_checksum(hwrpb);
-       }
-
-       /* Also set up the real kernel PCB while we're at it.  */
-       init_task.tss.ptbr = newptbr;
-       init_task.tss.pal_flags = 1;    /* set FEN, clear everything else */
-       init_task.tss.flags = 0;
-       original_pcb_ptr = load_PCB(&init_task.tss);
-       tbia();
-
-       /* Save off the contents of the original PCB so that we can
-          restore the original console's page tables for a clean reboot.
-
-          Note that the PCB is supposed to be a physical address, but
-          since KSEG values also happen to work, folks get confused.
-          Check this here.  */
-
-       if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
-               original_pcb_ptr = (struct thread_struct *)
-                 phys_to_virt((unsigned long) original_pcb_ptr);
-       }
-       original_pcb = *original_pcb_ptr;
 
        return start_mem;
 }
index 0fb2276eabd7507ec12a287bd156d672c1ac45cf..6e7117a48dcda3ec085601b9a267b404962666fa 100644 (file)
@@ -1,10 +1,11 @@
 OUTPUT_FORMAT("elf64-alpha")
 ENTRY(__start)
+PHDRS { kernel PT_LOAD ; }
 SECTIONS
 {
    . = 0xfffffc0000310000;
    _text = .;
-   .text : { *(.text) }
+   .text : { *(.text) } :kernel
    .text2 : { *(.text2) }
    _etext = .;
 
index 8ec52dcf893b987fe9f0675cf87573c52fcd896c..7f9ec34addcb943a1d148d99c8ce03e8f67c61a7 100644 (file)
@@ -274,6 +274,7 @@ int drive_is_flashcard (ide_drive_t *drive)
                if (!strncmp(id->model, "KODAK ATA_FLASH", 15)  /* Kodak */
                 || !strncmp(id->model, "Hitachi CV", 10)               /* Hitachi */
                 || !strncmp(id->model, "SunDisk SDCFB", 13)    /* SunDisk */
+                || !strncmp(id->model, "ATA_FLASH", 9) /* Simple Tech */
                 || !strncmp(id->model, "HAGIWARA HPC", 12))    /* Hagiwara */
                {
                        return 1;       /* yes, it is a flash memory card */
index 6d91e7187d9ff1870e99c1c2e4b99cc7ccbb9f98..b31425264df142dc3f4c450f0bb4aef1db1416d2 100644 (file)
@@ -1289,7 +1289,7 @@ void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d)
          * so we just sleep for a little while and let it do it's thing
          */
         current->state = TASK_INTERRUPTIBLE;
-        schedule_timeout(3*HZ);
+        schedule_timeout(5*HZ);
 
         if(i2o_claim_device(d, &i2o_block_handler))
         {
index d00dd8dbde68d698aafabccf67b6633d098d001f..fc6ab62e06ee969e447f25b91572041c590fe0fc 100644 (file)
@@ -42,7 +42,8 @@
 static int i2o_cfg_context = -1;
 static void *page_buf;
 static void *i2o_buffer;
-static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t i2o_queue_lock = SPIN_LOCK_UNLOCKED;
+
 struct wait_queue *i2o_wait_queue;
 
 #define MODINC(x,y) (x = x++ % y)
@@ -144,7 +145,7 @@ static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struc
                                (unsigned char *)(msg + 5),
                                inf->event_q[inf->q_in].data_size);
 
-               spin_lock(&i2o_config_lock);
+               spin_lock(&i2o_queue_lock);
                MODINC(inf->q_in, I2O_EVT_Q_LEN);
                if(inf->q_len == I2O_EVT_Q_LEN)
                {
@@ -156,7 +157,7 @@ static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struc
                        // Keep I2OEVTGET on another CPU from touching this
                        inf->q_len++;
                }
-               spin_unlock(&i2o_config_lock);
+               spin_unlock(&i2o_queue_lock);
                
 
 //             printk(KERN_INFO "File %p w/id %d has %d events\n",
@@ -808,11 +809,12 @@ static int ioctl_evt_get(unsigned long arg, struct file *fp)
 
        memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
        MODINC(p->q_out, I2O_EVT_Q_LEN);
-       spin_lock_irqsave(&i2o_config_lock, flags);
+       spin_lock_irqsave(&i2o_queue_lock, flags);
+       /* FIXME - ought to lock the q_ values here!! */
        p->q_len--;
        kget.pending = p->q_len;
        kget.lost = p->q_lost;
-       spin_unlock_irqrestore(&i2o_config_lock, flags);
+       spin_unlock_irqrestore(&i2o_queue_lock, flags);
 
        __copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
 
@@ -838,9 +840,9 @@ static int cfg_open(struct inode *inode, struct file *file)
        tmp->q_lost = 0;
        tmp->next = open_files;
 
-       spin_lock_irqsave(&i2o_config_lock, flags);
+       spin_lock_irqsave(&i2o_queue_lock, flags);
        open_files = tmp;
-       spin_unlock_irqrestore(&i2o_config_lock, flags);
+       spin_unlock_irqrestore(&i2o_queue_lock, flags);
        
        MOD_INC_USE_COUNT;
        return 0;
@@ -854,7 +856,7 @@ static int cfg_release(struct inode *inode, struct file *file)
 
        p1 = p2 = NULL;
 
-       spin_lock_irqsave(&i2o_config_lock, flags);
+       spin_lock_irqsave(&i2o_queue_lock, flags);
        for(p1 = open_files; p1; )
        {
                if(p1->q_id == id)
@@ -873,7 +875,7 @@ static int cfg_release(struct inode *inode, struct file *file)
                p2 = p1;
                p1 = p1->next;
        }
-       spin_unlock_irqrestore(&i2o_config_lock, flags);
+       spin_unlock_irqrestore(&i2o_queue_lock, flags);
 
        MOD_DEC_USE_COUNT;
        return 0;
index d00ac40009b903ca97c9f739a160893ecd3eebc5..8c7a693c2b95ad065615ee261254262c59dcfd19 100644 (file)
@@ -180,11 +180,11 @@ static int evt_q_len = 0;
 #define MODINC(x,y) (x = x++ % y)
 
 /*
- *     I2O configuration spinlock. This isnt a big deal for contention
+ *     I2O configuration semaphore. This isnt a big deal for contention
  *     so we have one only
  */
  
-static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED;
+static struct semaphore i2o_configuration_lock = MUTEX;
 
 
 /*
@@ -317,18 +317,18 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
 int i2o_install_handler(struct i2o_handler *h)
 {
        int i;
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        for(i=0;i<MAX_I2O_MODULES;i++)
        {
                if(i2o_handlers[i]==NULL)
                {
                        h->context = i;
                        i2o_handlers[i]=h;
-                       spin_unlock(&i2o_configuration_lock);
+                       up(&i2o_configuration_lock);
                        return 0;
                }
        }
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return -ENOSPC;
 }
 
@@ -348,7 +348,7 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
 {
        int i;
 
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        d->controller=c;
        d->owner=NULL;
        d->next=c->devices;
@@ -358,7 +358,7 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
        for(i = 0; i < I2O_MAX_MANAGERS; i++)
                d->managers[i] = NULL;
 
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return 0;
 }
 
@@ -431,11 +431,11 @@ int i2o_delete_device(struct i2o_device *d)
 {
        int ret;
 
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
 
        ret = __i2o_delete_device(d);
 
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
 
        return ret;
 }
@@ -447,7 +447,7 @@ int i2o_delete_device(struct i2o_device *d)
 int i2o_install_controller(struct i2o_controller *c)
 {
        int i;
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        for(i=0;i<MAX_I2O_CONTROLLERS;i++)
        {
                if(i2o_controllers[i]==NULL)
@@ -465,13 +465,13 @@ int i2o_install_controller(struct i2o_controller *c)
                           sprintf(c->name, "i2o/iop%d", i);
                           i2o_num_controllers++;
                           sema_init(&c->lct_sem, 0);
-                          spin_unlock(&i2o_configuration_lock);
+                          up(&i2o_configuration_lock);
                           return 0;
 
                }
        }
        printk(KERN_ERR "No free i2o controller slots.\n");
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return -EBUSY;
 }
 
@@ -488,12 +488,12 @@ int i2o_delete_controller(struct i2o_controller *c)
         if(c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
                  i2o_event_register(c, core_context, 0, 0, 0);
 
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        if((users=atomic_read(&c->users)))
        {
                printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users);
                c->bus_disable(c); 
-               spin_unlock(&i2o_configuration_lock);
+               up(&i2o_configuration_lock);
                return -EBUSY;
        }
        while(c->devices)
@@ -502,7 +502,7 @@ int i2o_delete_controller(struct i2o_controller *c)
                {
                        /* Shouldnt happen */
                        c->bus_disable(c); 
-                       spin_unlock(&i2o_configuration_lock);
+                       up(&i2o_configuration_lock);
                        return -EBUSY;
                }
        }
@@ -541,7 +541,7 @@ int i2o_delete_controller(struct i2o_controller *c)
                        c->destructor(c);
 
                        *p=c->next;
-                       spin_unlock(&i2o_configuration_lock);
+                       up(&i2o_configuration_lock);
 
                        if(c->page_frame)
                                kfree(c->page_frame);
@@ -565,7 +565,7 @@ int i2o_delete_controller(struct i2o_controller *c)
                }
                p=&((*p)->next);
        }
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        printk(KERN_ERR "i2o_delete_controller: bad pointer!\n");
        return -ENOENT;
 }
@@ -582,11 +582,11 @@ struct i2o_controller *i2o_find_controller(int n)
        if(n<0 || n>=MAX_I2O_CONTROLLERS)
                return NULL;
        
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        c=i2o_controllers[n];
        if(c!=NULL)
                atomic_inc(&c->users);
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return c;
 }
        
@@ -597,23 +597,23 @@ struct i2o_controller *i2o_find_controller(int n)
  */
 int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h)
 {
-        spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
 
        if(d->owner)
        {
                printk(KERN_INFO "issue claim called, but dev has owner!");
-               spin_unlock(&i2o_configuration_lock);
+               up(&i2o_configuration_lock);
                return -EBUSY;
        }
 
        if(i2o_issue_claim(d->controller,d->lct_data.tid, h->context, 1, I2O_CLAIM_PRIMARY))
        {
-               spin_unlock(&i2o_configuration_lock);
+               up(&i2o_configuration_lock);
                return -EBUSY;
        }
 
        d->owner=h;
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return 0;
 }
 
@@ -621,10 +621,10 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
 {
        int err = 0;
 
-       spin_lock(&i2o_configuration_lock);
+       down(&i2o_configuration_lock);
        if(d->owner != h)
        {
-               spin_unlock(&i2o_configuration_lock);
+               up(&i2o_configuration_lock);
                return -ENOENT;
        }
 
@@ -636,7 +636,7 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h)
 
        d->owner = NULL;
 
-       spin_unlock(&i2o_configuration_lock);
+       up(&i2o_configuration_lock);
        return err;
 }
 
@@ -1178,7 +1178,7 @@ static int i2o_reset_controller(struct i2o_controller *c)
        u32 *msg;
        long time;
 
-       printk("begin RESET\n");
+       dprintk(("begin RESET\n"));
        /* Quiesce all IOPs first */
 
        for (iop = i2o_controller_chain; iop; iop = iop->next)
@@ -1484,13 +1484,13 @@ rebuild_sys_tab:
         * as we can't init the IOPs w/o a system table
         */     
         
-       printk("SYSTAB\n");
+       dprintk(("SYSTAB\n"));
        if (i2o_build_sys_table() < 0) {
                i2o_sys_shutdown();
                return;
        }
 
-       printk("ONLINE\n");
+       dprintk(("ONLINE\n"));
 
        /* If IOP don't get online, we need to rebuild the System table */
        for (iop = i2o_controller_chain; iop; iop = niop) {
@@ -1499,7 +1499,7 @@ rebuild_sys_tab:
                        goto rebuild_sys_tab;
        }
 
-       printk("ACTIVE\n");
+       dprintk(("ACTIVE\n"));
        
        /* Active IOPs now in OPERATIONAL state
         *
@@ -1522,7 +1522,7 @@ rebuild_sys_tab:
                i2o_event_register(iop, core_context, 0, 0, 0xFFFFFFFF);
        }
 
-       printk("DONE\n");
+       dprintk(("DONE\n"));
 }
 
 /*
@@ -1548,9 +1548,8 @@ int i2o_activate_controller(struct i2o_controller *iop)
 {
        /* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */
        /* In READY state, Get status */
-       u32 m;
 
-       printk("ACTIVATE\n");
+       dprintk(("ACTIVATE\n"));
        
        if (i2o_status_get(iop) < 0) {
                printk(KERN_INFO "Unable to obtain status of IOP, attempting a reset.\n");
@@ -1575,42 +1574,30 @@ int i2o_activate_controller(struct i2o_controller *iop)
        {
                dprintk((KERN_INFO "%s: already running...trying to reset\n",
                        iop->name));
-               printk("Outbound q2\n");
-
-               if (i2o_init_outbound_q(iop) < 0) {
-                       i2o_reset_controller(iop);                      
+               dprintk(("Outbound q2\n"));
 
-                       if (i2o_status_get(iop) < 0 || 
-                               iop->status_block->iop_state != ADAPTER_STATE_RESET)
-                       {
-                               printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
-                               i2o_delete_controller(iop);
-                               return -1;
-                       }
-                       if (i2o_init_outbound_q(iop) < 0) {
-                               i2o_delete_controller(iop);
-                               return -1;
-                       }
-               }
-       }
-       else
-       {
-               printk("Outbound q\n");
-
-               if (i2o_init_outbound_q(iop) < 0) {
+               i2o_reset_controller(iop);                      
+               if (i2o_status_get(iop) < 0 || iop->status_block->iop_state != ADAPTER_STATE_RESET)
+               {
+                       printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
                        i2o_delete_controller(iop);
                        return -1;
                }
        }
 
+       if (i2o_init_outbound_q(iop) < 0) {
+               i2o_delete_controller(iop);
+               return -1;
+       }
+
        /* In HOLD state */
-       printk("HRT\n");
+       dprintk("HRT\n");
        
        if (i2o_hrt_get(iop) < 0) {
                i2o_delete_controller(iop);
                return -1;
        }
-       printk("DONE\n");
+       dprintk("DONE\n");
 
        return 0;
 }
@@ -2150,9 +2137,9 @@ static int i2o_core_evt(void *reply_data)
                                    {
                                        if(i2o_handlers[i] && i2o_handlers[i]->new_dev_notify && (i2o_handlers[i]->class&d->lct_data.class_id))
                                        {
-                                               spin_lock(&i2o_dev_lock);
+                                               spin_lock_irqsave(&i2o_dev_lock, flags);
                                                i2o_handlers[i]->new_dev_notify(c,d);
-                                               spin_unlock(&i2o_dev_lock);
+                                               spin_unlock_irqrestore(&i2o_dev_lock, flags);
                                        }
                                    }
 
@@ -2214,6 +2201,7 @@ static int i2o_dyn_lct(void *foo)
         void *tmp;
         char name[16];
         struct fs_struct *fs;
+        unsigned long flags;
 
         lock_kernel();
 
@@ -2283,9 +2271,9 @@ static int i2o_dyn_lct(void *foo)
                           if(!found)
                           {
                                dprintk((KERN_INFO "Deleted device!\n"));
-                               spin_lock(&i2o_dev_lock);
+                               spin_lock_irqsave(&i2o_dev_lock,flags);
                                i2o_delete_device(d);
-                               spin_unlock(&i2o_dev_lock);
+                               spin_unlock_irqrestore(&i2o_dev_lock,flags);
                           }
                           d = d1;
                  }
index 5227b3956390d2d370f1d1b66ecf25928f451fe6..3fb5ef4a55f59427fce11e43d9d64d77769fa70d 100644 (file)
@@ -4,7 +4,7 @@
  *     The RightSwitch is a 4 (EISA) or 6 (PCI) port etherswitch and
  *     a NIC on an internal board.
  *
- *     Author: Rick Richardson, rick@dgii.com, rick_richardson@dgii.com
+ *     Author: Rick Richardson, rick@remotepoint.com
  *     Derived from the SVR4.2 (UnixWare) driver for the same card.
  *
  *     Copyright 1995-1996 Digi International Inc.
@@ -73,7 +73,7 @@
  *
  */
 
-static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
+static char *version = "$Id: dgrs.c,v 1.13 2000/06/06 04:07:00 rick Exp $";
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -209,7 +209,7 @@ typedef struct
         I596_RFD        *rfdp;          /* Current RFD list */
         I596_RBD        *rbdp;          /* Current RBD list */
 
-        int             intrcnt;        /* Count of interrupts */
+        volatile int    intrcnt;        /* Count of interrupts */
 
         /*
          *      SE-4 (EISA) board variables
@@ -1193,7 +1193,7 @@ dgrs_probe1(struct device *dev))
         */
        if (priv->plxreg)
                OUTL(dev->base_addr + PLX_LCL2PCI_DOORBELL, 1);
-       rc = request_irq(dev->irq, &dgrs_intr, 0, "RightSwitch", dev);
+       rc = request_irq(dev->irq, &dgrs_intr, SA_SHIRQ, "RightSwitch", dev);
        if (rc)
                return (rc);
 
index 50b517c8fa5685e95c6c7018d40e5433812cd275..f7f42ba344bf19237b20af130ec4b608fa385293 100644 (file)
@@ -508,7 +508,9 @@ static int pci_etherdev_probe(struct device *dev, struct pci_id_info pci_tbl[])
 #ifndef MODULE
 int via_rhine_probe(struct device *dev)
 {
-       printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+       static int did_version = 0;
+       if (!did_version++)
+               printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
        return pci_etherdev_probe(dev, pci_tbl);
 }
 #endif
index 3dcea50a905af270ab5e47f83b51fda30c3c3c02..63bb0650fa59e07ea605a87cda15309f7838a36d 100644 (file)
@@ -1018,9 +1018,9 @@ printk(KERN_DEBUG "ncp_unlink: closing file\n");
 
        error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
 #ifdef CONFIG_NCPFS_STRONG
-       /* 9C is Invalid path.. It should be 8F, 90 - read only, but
-          it is not :-( */
-       if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
+       /* 9C is Invalid path, used by traditional NW filesystem... 
+          8F, 90 is Some/All read-only and is used by NSS :-( */
+       if ((error == 0x9C || error == 0x8F || error == 0x90) && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
                error = ncp_force_unlink(dir, dentry);
        }
 #endif
@@ -1085,7 +1085,7 @@ static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
                                            old_dir, _old_name,
                                            new_dir, _new_name);
 #ifdef CONFIG_NCPFS_STRONG
-       if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) {   /* RO */
+       if ((error == 0x90 || error == 0x8B || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) {  /* RO */
                error = ncp_force_rename(old_dir, old_dentry, _old_name,
                                          new_dir, new_dentry, _new_name);
        }
index 0d565a44e764ae171c017baaea3995b2eda15dc2..0d498e65bbf3531944af1521bf5ea0ecce5733a8 100644 (file)
@@ -105,8 +105,7 @@ void ncp_update_inode2(struct inode* inode, struct nw_file_info *nwinfo)
                                switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
                                        case aHIDDEN:
                                                if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-                                                       if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-                                                        && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+                                                       if (inode->i_size <= NCP_MAX_SYMLINK_SIZE) {
                                                                inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
                                                                break;
                                                        }
@@ -168,8 +167,7 @@ static void ncp_set_attr(struct inode *inode, struct nw_file_info *nwinfo)
                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
                                case aHIDDEN:
                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
-                                               if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
-                                                && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+                                               if (inode->i_size <= NCP_MAX_SYMLINK_SIZE) {
                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
                                                        break;
                                                }
index c22297f6507aa5771f65320e57d559d598cdb3bc..74baa4de70b2e12a719848d47009f281cc5978ff 100644 (file)
@@ -336,6 +336,7 @@ repeat:
                        goto repeat;
                }
                else {
+                       brelse (bh);
                        return NULL;
                }
        }               
index 89f39911f33726e0ef835467f2a9bb38b7b12a25..44ea5535bd79aef2d46329e6aa9d9f46f6d4fe04 100644 (file)
@@ -22,6 +22,8 @@
 #define CCB_GET_ENV            0x22
 #define CCB_SAVE_ENV           0x23
 
+#define CCB_PSWITCH            0x30
+#define CCB_BIOS_EMUL          0x32
 /*
  * Environment variable numbers
  */
 #define ENV_BOOT_RESET         0x09
 #define ENV_DUMP_DEV           0x0A
 #define ENV_ENABLE_AUDIT       0x0B
-#define ENV_LICENCE            0x0C
+#define ENV_LICENSE            0x0C
 #define ENV_CHAR_SET           0x0D
 #define ENV_LANGUAGE           0x0E
 #define ENV_TTY_DEV            0x0F
 
+#define NO_SRM_CONSOLE         -1L
+
 #ifdef __KERNEL__
-extern long srm_dispatch(long code, ...);
-extern void srm_puts(const char *);
+#ifndef __ASSEMBLY__
+extern long callback_puts(long unit, const char *s, long length);
+extern long callback_open(const char *device, long length);
+extern long callback_close(long unit);
+extern long callback_read(long channel, long count, const char *buf, long lbn);
+extern long callback_getenv(long id, const char *buf, unsigned long buf_size);
+
+extern int srm_fixup(unsigned long new_callback_addr,
+                     unsigned long new_hwrpb_addr);
+extern long srm_puts(const char *, long len);
 extern long srm_printk(const char *, ...)
        __attribute__ ((format (printf, 1, 2)));
 
 struct crb_struct;
 struct hwrpb_struct;
-extern long srm_fixup(struct crb_struct *, struct hwrpb_struct *);
+
+extern int callback_init_done;
+extern void * callback_init(void *);
+#endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
 #endif /* __AXP_CONSOLE_H */
index a1a7c2429ccf96d29575f12aba233acb50d0647f..3bccc03c17bf189c8745831e41866473a3111ba4 100644 (file)
@@ -80,6 +80,7 @@ typedef struct {
        tsunami_64      mpr2;
        tsunami_64      mpr3;
        tsunami_64      mctl;
+       tsunami_64      __pad1;
        tsunami_64      ttr;
        tsunami_64      tdr;
        tsunami_64      dim2;
index ec65678bb88ff8397515442a0d7dbc45b9084fdc..b225f3e7a730952695dd2336a14d17dd7e50c2c9 100644 (file)
@@ -190,6 +190,8 @@ struct hwrpb_struct {
        unsigned long dsr_offset;       /* "Dynamic System Recognition Data Block Table" */
 };
 
+#define HWRPB_MEMBER_ID(v)     (((v) >> 10) & 0x3f)
+
 #ifdef __KERNEL__
 
 extern struct hwrpb_struct *hwrpb;
index 889737c82494499666fb06d83896141ef0156c85..b881d0e16b0acd0a4693f5908f1a061e1f2bc9d3 100644 (file)
@@ -9,6 +9,7 @@
  * in <asm/page.h> (currently 8192).
  */
 #include <linux/config.h>
+#include <linux/mm.h>
 
 #include <asm/system.h>
 #include <asm/processor.h>     /* For TASK_SIZE */
@@ -219,7 +220,8 @@ extern void flush_tlb_range(struct mm_struct *, unsigned long, unsigned long);
 /* Number of pointers that fit on a page:  this will go away. */
 #define PTRS_PER_PAGE  (1UL << (PAGE_SHIFT-3))
 
-#define VMALLOC_START          0xFFFFFE0000000000
+#define CONSOLE_REMAP_START    0xFFFFFE0000000000
+#define VMALLOC_START          (CONSOLE_REMAP_START + PMD_SIZE)
 #define VMALLOC_VMADDR(x)      ((unsigned long)(x))
 #define VMALLOC_END            (~0UL)
 
index 17268460fe8ca2b497256366ce40d03d2b5575df..d6881efc79b539e262dbef79297dc053e8108a00 100644 (file)
@@ -137,6 +137,9 @@ __asm__ __volatile__ ("call_pal %0 #imb" : : "i" (PAL_imb) : "memory")
 #define draina() \
 __asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
 
+#define __halt() \
+__asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
+
 enum implver_enum {
        IMPLVER_EV4,
        IMPLVER_EV5,
index 80d1efcbd6cf310a9b058fef742a3fd7a15e880a..177732abbb1e5a19fa18bf94d02883110649a549 100644 (file)
@@ -530,7 +530,7 @@ struct exception_table_entry
 };
 
 /* Returns 0 if exception not found and fixup.unit otherwise.  */
-extern unsigned search_exception_table(unsigned long);
+extern unsigned search_exception_table(unsigned long, unsigned long);
 
 /* Returns the new pc */
 #define fixup_exception(map_reg, fixup_unit, pc)               \